SaaS Starter

Primitives

Los siete primitives de brand — qué es cada uno, cuándo usarlo, y el ejemplo canónico.

Todos los primitives viven en apps/client/components/brand/ y se barrelean a través de @/components/brand. Importá el símbolo; nunca copies y pegues el markup.

import {
  BrandMark,
  VersionChip,
  GridGlowBackground,
  NoiseOverlay,
  MonoLabel,
  AuthCard,
  BrandCard,
} from '@/components/brand';

BrandMark

El wordmark UseDeploy. Renderiza como <Link href="/"> por default; pasá href={null} para un span inline no-link. Los children se renderizan al lado (uso típico: un <VersionChip>).

Source: apps/client/components/brand/BrandMark.tsx

PropTipoDefaultNotas
size'sm' | 'md' | 'lg''md'Mapea a text-base / text-lg / text-2xl.
hrefstring | null'/'null renderiza un <span> inline en lugar de un link.
childrenReactNodeRenderizados después del wordmark dentro de la misma fila flex.
classNamestringMergeado con el outer del link / span.
aria-labelstringNombre accesible.
<BrandMark>
  <VersionChip />
</BrandMark>

Cuándo usarlo. Donde sea que tipearías la palabra "UseDeploy" en markup estilizado — nav de landing, header del dashboard, título de auth card.


VersionChip

Pequeño chip mono en mayúsculas mostrando la versión de la app. Default a process.env.NEXT_PUBLIC_APP_VERSION (cae a v0.1.0). Override pasando children.

Source: apps/client/components/brand/VersionChip.tsx

PropTipoDefaultNotas
childrenReactNodeversión derivada de envOverride del string mostrado.
classNamestring
<BrandMark>
  <VersionChip />
</BrandMark>

<BrandMark>
  <VersionChip>BETA</VersionChip>
</BrandMark>

Cuándo usarlo. Pegado al wordmark para surfaces de producto. Mantenelo chico — es una señal de metadata, no un badge.


GridGlowBackground

Dos capas apiladas — un radial glow violeta y un grid de líneas blancas de 64 px enmascarado por detrás — que le dan a cada surface UseDeploy su signature ambient depth sin apoyarse en una imagen hero. CSS puro, server-rendered, cero JS.

Source: apps/client/components/brand/GridGlowBackground.tsx

PropTipoDefaultNotas
intensity'subtle' | 'default' | 'bold''default'Tunea opacidad de glow y de grid.
classNamestringAplicada a la capa de glow.
<div className="relative min-h-screen bg-background">
  <GridGlowBackground intensity="subtle" />
  {/* contenido de la página acá, position relative o z-10 */}
</div>

El container necesita position: relative porque el primitive usa absolute inset-0. Envolvé tu contenido en otro elemento por encima (relative z-10) para que se apoye arriba.

Cuándo usarlo. Toda surface fullscreen — landing, auth, marketing pages. Salteá en pantallas de data densa (tablas del dashboard, settings) donde competiría con el contenido.


NoiseOverlay

Noise estático SVG turbulence, fixed across the viewport. Agrega textura de film-grain para que las surfaces oscuras no se vean planamente digitales. Data URI inline, cero network requests.

Source: apps/client/components/brand/NoiseOverlay.tsx

PropTipoDefaultNotas
opacitynumber0.03Tuneá con cuidado — 0.05 ya es demasiado.
classNamestring
<>
  <GridGlowBackground />
  <NoiseOverlay />
  {/* contenido */}
</>

Es position: fixed; z-index: 1; mix-blend-mode: overlay. Contenido con z-index más alto se apoya arriba; contenido en z: auto por default no.

Cuándo usarlo. Junto con <GridGlowBackground> en hero surfaces. No lo apiles dos veces a través de layouts anidados — una instancia por página.


MonoLabel

El patrón recurrente de metadata uppercase tracked-wide — texto pequeño mono usado como section eyebrows, KPI labels, list section headers. Envuelve la utility class .label-mono.

Source: apps/client/components/brand/MonoLabel.tsx

PropTipoDefaultNotas
as'span' | 'div' | 'p''span'El elemento renderizado.
classNamestringMergeado con label-mono.
childrenReactNodeEl texto del label.
<MonoLabel as="div">Members</MonoLabel>
<div className="text-3xl font-semibold">42</div>

Cuándo usarlo. Cualquier metadata uppercase — captions de KPI, "Step 01", "Section", section eyebrows. No re-rolles los estilos inline.


AuthCard

Glass card usada por toda página (auth). Centraliza el markup wrapper para que las páginas dejen de divergir en estilos de shell y sólo declaren el contenido de su form.

Source: apps/client/components/brand/AuthCard.tsx

PropTipoNotas
titleReactNodeRenderizado en <h1 class="text-2xl font-semibold">.
subtitleReactNodeRenderizado como body copy muted bajo el título.
footerReactNodeBajo el form, separado por una hairline — típico "¿Ya tenés cuenta? Sign in".
childrenReactNodeEl form.
classNamestringMergeado en el div de card.
<AuthCard
  title="Sign in to UseDeploy"
  subtitle="Welcome back."
  footer={<Link href="/register">Create an account</Link>}
>
  <SignInForm />
</AuthCard>

Cuándo usarlo. Toda página de auth: sign-in, register, forgot password, reset password, magic-link. El (auth)/layout.tsx ya monta el <GridGlowBackground> y centra la card; las páginas son dueñas sólo del form.


BrandCard

La surface de card del dashboard / marketing. Border hairline, glass surface sutil, gradient-sweep hover opcional que espeja las feature cards de landing. Token-driven así trackea el tema oscuro automáticamente.

Source: apps/client/components/brand/BrandCard.tsx

PropTipoDefaultNotas
labelReactNodeEyebrow mono uppercase sobre el título (ej. "01", "MEMBERS").
titleReactNodeBold, tracking apretado. Más grande cuando hay label o action.
actionReactNodeSlot top-right — típico: un ícono.
interactivebooleanfalseSuma el sweep hairline card-glow + shift de bg en hover. Usar para cards clickeables.
classNamestring
childrenReactNodeContenido body bajo el título.
<BrandCard label="MEMBERS" title="42">
  <p className="text-muted-foreground">3 invited last week</p>
</BrandCard>

<BrandCard interactive label="01" title="Add a project" action={<ArrowUpRight />}>
  Spin up a workspace and invite your team.
</BrandCard>

Cuándo usarlo. KPIs del dashboard, list rows, feature cards de marketing. Usá interactive sólo cuando el user puede clickear toda la card — si no, el hint de hover engaña.


Qué no está acá (y por qué)

Vas a notar que no hay Button, Input, Dialog, etc. — esos son primitives derivados de shadcn en apps/client/components/ui/, ya token-aware. El namespace brand/ es sólo para las surfaces y motivos únicos de UseDeploy. Si algo es genérico (un botón, un checkbox), vive en ui/. Si es específico de la identidad del producto (un wordmark, una glass auth card, un grid-and-glow background), vive en brand/.

En esta página