Organize Vertex starter into reusable sections

Use remote logos and avatars, refine landing copy, and document the template structure.
This commit is contained in:
Rami Bitar
2026-09-15 10:49:07 -04:00
parent ad7d003ed4
commit c84dc9dbe7
45 changed files with 959 additions and 825 deletions
+27
View File
@@ -0,0 +1,27 @@
import Image from "next/image"
import { cn } from "@/lib/utils"
export function VertexMark({ className }: { className?: string }) {
return (
<Image
src="/logo.svg"
alt=""
width={24}
height={24}
className={cn("brightness-0 dark:invert", className)}
aria-hidden="true"
/>
)
}
export function Brand({ compact = false }: { compact?: boolean }) {
return (
<span className="inline-flex items-center gap-2.5">
<VertexMark className="size-8" />
{!compact && (
<span className="text-[17px] font-semibold tracking-[-0.03em]">Vertex</span>
)}
</span>
)
}
+14
View File
@@ -0,0 +1,14 @@
export function FeatureCopy({
title,
description,
}: {
title: string
description: string
}) {
return (
<div className="relative z-10 bg-background p-6 sm:p-7">
<h3 className="text-lg font-medium tracking-[-0.025em]">{title}</h3>
<p className="mt-2 max-w-md text-sm leading-6 text-muted-foreground">{description}</p>
</div>
)
}
+10
View File
@@ -0,0 +1,10 @@
export function FrameCrosses() {
return (
<>
<span className="frame-cross left-0 top-0" aria-hidden="true" />
<span className="frame-cross right-0 top-0" aria-hidden="true" />
<span className="frame-cross bottom-0 left-0" aria-hidden="true" />
<span className="frame-cross bottom-0 right-0" aria-hidden="true" />
</>
)
}
+31
View File
@@ -0,0 +1,31 @@
import Image from "next/image"
export interface Testimonial {
avatar: string
name: string
role: string
quote: string
}
export function ReviewCard({ review }: { review: Testimonial }) {
return (
<figure className="h-full w-[310px] shrink-0 rounded-xl border bg-card/75 p-5 shadow-sm transition-colors hover:bg-muted/40 sm:w-[360px]">
<blockquote className="text-sm leading-6 text-foreground/85">“{review.quote}”</blockquote>
<figcaption className="mt-6 flex items-center gap-3">
<Image
src={review.avatar}
alt=""
width={36}
height={36}
sizes="36px"
unoptimized
className="size-9 shrink-0 rounded-full border object-cover"
/>
<span>
<span className="block text-sm font-medium">{review.name}</span>
<span className="block text-xs text-muted-foreground">{review.role}</span>
</span>
</figcaption>
</figure>
)
}
+29
View File
@@ -0,0 +1,29 @@
import { cn } from "@/lib/utils"
export function SectionHeading({
eyebrow,
title,
description,
className,
}: {
eyebrow: string
title: string
description: string
className?: string
}) {
return (
<div className={cn("border-b px-6 py-16 text-center sm:px-10 sm:py-20", className)}>
<div className="mx-auto max-w-2xl">
<p className="mb-4 font-mono text-[11px] font-medium uppercase tracking-[0.18em] text-blue-600 dark:text-blue-400">
{eyebrow}
</p>
<h2 className="text-balance text-3xl font-medium tracking-[-0.045em] sm:text-4xl md:text-[44px] md:leading-[1.05]">
{title}
</h2>
<p className="mx-auto mt-4 max-w-xl text-pretty text-sm leading-6 text-muted-foreground sm:text-base">
{description}
</p>
</div>
</div>
)
}