Files
cloudrite/.design-sync/conventions.md
T
ASOwnerYTandClaude Opus 5 3970cf9a00
Docker / build (push) Failing after 1m43s
Add design-sync inputs for claude.ai/design
Import this repo's components into a Claude Design project so the design
agent builds with the real Cloudrite library instead of generic components.

The repo is a Next.js app, not a component library: no dist/, no exports
map, no .d.ts tree, and Tailwind exists only as build directives. So
.design-sync/ carries a small build that manufactures a consumable package
from source (staged to the gitignored .ds-pkg/):

- tsconfig.dts.json  declaration emit, for real <Name>Props contracts
- build-css.mjs      Tailwind v4 -> a static stylesheet via @tailwindcss/postcss
- make-pkg.mjs       stages the package; index.js exports all 292 symbols
                     while index.d.ts exports only the 61 roots, so shadcn's
                     flat compound parts don't each become a preview card.
                     Also generates the per-root parts tables in docs/
- shims/next-link    router-free anchor; the real next/link needs
                     AppRouterContext and drags in the App Router runtime
- fonts/             Space Grotesk + Inter woff2 (SIL OFL). next/font supplies
                     these at runtime in the app, so the bundle has none

previews/ holds 40 authored preview stories, conventions.md is prepended to
the generated README as the design agent's usage guide, and NOTES.md records
the gotchas a future sync would otherwise rediscover.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-08-05 17:04:10 +12:00

4.2 KiB

Building with Cloudrite

Cloudrite is the component library behind cloudrite.co.nz — 54 shadcn/ui (new-york) primitives plus 7 ready-made page sections, styled with Tailwind v4 utilities over CSS custom properties.

Dark is the only theme

:root carries the dark palette — there is no light mode. styles.css already puts background-color: var(--background) and color: var(--foreground) on body, so a plain page is correct by default. Any container that paints its own background must also set the pair, or foreground-coloured content vanishes:

<div className="bg-background text-foreground"></div>

ghost and link buttons, border-border hairlines and text-muted-foreground are all near-invisible on a light surface. If something renders blank, this is why.

No global provider — four local exceptions

Components work unwrapped. These four do not:

  • Tooltip — must be inside TooltipProvider, or it throws.
  • Sidebar and its parts — must be inside SidebarProvider.
  • Form — this is react-hook-form's FormProvider. Spread a useForm() instance into it (<Form {...form}>) and wire controls with FormField.
  • Toast/ToastViewport — need ToastProvider. Prefer Toaster (sonner) for new work.

Compound parts are flat exports, not namespaces

Write <CardHeader>, never <Card.Header>. Every part is its own top-level import:

import { Card, CardHeader, CardTitle, CardContent } from 'cloudrite';

Each component's .prompt.md carries a parts table listing its exports and their props — read it before composing a compound.

The class vocabulary

Semantic Tailwind utilities backed by tokens. Use these, not raw colours:

Family Names
Surfaces bg-background bg-card bg-popover bg-muted bg-secondary bg-primary bg-accent bg-destructive bg-sidebar
Text text-foreground text-muted-foreground text-primary text-card-foreground text-primary-foreground text-secondary-foreground text-accent-foreground text-destructive
Lines border-border border-input ring-ring
Radius rounded-md rounded-lg rounded-xl
Type font-sans (Space Grotesk — headings) font-body (Inter — body copy) font-mono

Opacity modifiers are idiomatic here: bg-primary/10, border-primary/50, bg-primary/20 blur-[100px] for the brand glow.

--accent is the brand green, identical to --primary — not shadcn's usual neutral hover tint. So bg-accent is a saturated green, and Skeleton (bg-accent) is a green block. For a quiet hover or placeholder surface use bg-muted or bg-secondary.

The brand accent is --primary: oklch(0.75 0.18 145) on --background: oklch(0.08 0 0).

Where the truth is

  • styles.css — the entry; @imports fonts/fonts.css and _ds_bundle.css.
  • _ds_bundle.css — every token definition and compiled utility. Grep it before inventing a class name.
  • components/<group>/<Name>/<Name>.prompt.md — per-component API and parts table.

Idiomatic composition

Library components for the controls, these utilities for your own layout glue:

import { Badge, Button, Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from 'cloudrite';
import { Cloud } from 'lucide-react';

<section className="bg-background text-foreground p-8">
  <Card className="max-w-sm">
    <CardHeader>
      <div className="flex size-12 items-center justify-center rounded-xl bg-primary/10 text-primary">
        <Cloud className="size-6" />
      </div>
      <CardTitle className="mt-4">Cloud Hosting</CardTitle>
      <CardDescription>Fast, easy hosting  proudly hosted in New Zealand.</CardDescription>
    </CardHeader>
    <CardContent>
      <Badge variant="secondary">NZ Hosted</Badge>
    </CardContent>
    <CardFooter>
      <Button className="w-full">Explore hosting</Button>
    </CardFooter>
  </Card>
</section>

The sections group

Header Hero Services Features Process Contact Footer are complete, prop-less cloudrite.co.nz page sections. Compose a full marketing page from them directly; use the primitives for anything new. Header is position: fixed — give it a relative parent with height, or it contributes none.