Docker / build (push) Failing after 1m43s
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]>
158 lines
9.7 KiB
Markdown
158 lines
9.7 KiB
Markdown
# design-sync notes — Cloudrite
|
|
|
|
Repo-specific gotchas for future syncs. Read this before re-running.
|
|
|
|
## What this repo is
|
|
|
|
Not a component library — a Next.js 16 marketing site (`private: true`, no `dist/`,
|
|
no `exports`, no `.d.ts` tree). The DS surface is `components/ui/*` (54 shadcn/ui
|
|
primitives, new-york style) plus 7 hand-built Cloudrite page sections.
|
|
|
|
## The staging package (`.ds-pkg/`)
|
|
|
|
The converter needs a package with a built entry and a `.d.ts` tree. Three scripts
|
|
under `.design-sync/` build one from source; run them **in this order** (this is
|
|
`cfg.buildCmd`):
|
|
|
|
1. `node_modules/.bin/tsc -p .design-sync/tsconfig.dts.json` — declaration emit,
|
|
69 `.d.ts` files. Exits 0; all three steps are chained with `&&`, so a real
|
|
failure stops the run.
|
|
**`../next-env.d.ts` must stay in that config's `include`.** It pulls in Next's
|
|
JSX augmentation for styled-jsx; without it the `<style jsx>` blocks in
|
|
`hero.tsx` and `footer.tsx` raise TS2322 and the emit exits non-zero. Those are
|
|
not repo errors — `pnpm build` and `tsc --noEmit -p tsconfig.json` are both clean.
|
|
2. `node .design-sync/build-css.mjs` — compiles Tailwind v4 → `.design-sync/compiled.css`.
|
|
3. `node .design-sync/make-pkg.mjs` — writes `.ds-pkg/{package.json,index.js,index.d.ts}`,
|
|
copies the stylesheet + fonts in, and regenerates `.design-sync/docs/*.md`.
|
|
|
|
`index.js` re-exports **every** symbol from source (292 exports → `window.Cloudrite`),
|
|
while `index.d.ts` re-exports only the 61 **roots**. That split is deliberate: shadcn
|
|
exports compound parts flat (`CardHeader`, not `Card.Header`), and the converter's
|
|
subcomponent grouping only recognises TS-namespace compounds — so without the split
|
|
all 292 exports would each get their own preview card. The parts are instead
|
|
documented per-root in the generated `.design-sync/docs/<Root>.md` parts tables,
|
|
which become the `.prompt.md` the design agent reads.
|
|
|
|
## Known render warns
|
|
|
|
- `[DTS_STYLE_SYSTEM] filtering @types/react props` — expected. Most shadcn
|
|
primitives type their props as `React.ComponentProps<'div'>`, so the CSS-shorthand
|
|
filter trips on React's own DOM prop bag. The emitted `<Name>Props` still carry the
|
|
real API (variant unions, `asChild`, etc.). Not a defect.
|
|
- `inlined npm packages: 1` in the build log is a pnpm artifact, not a real count —
|
|
the metafile regex matches `.pnpm` first in pnpm's `node_modules/.pnpm/<pkg>@ver/...`
|
|
layout. The bundle really does inline radix, lucide, cva, etc.
|
|
|
|
## Gotchas that cost a debugging cycle
|
|
|
|
- **`cfg.tsconfig` must use `/* */` comments only.** The converter strips `//`
|
|
comments with a regex that also mangles a `"//"` JSON *key*, leaving unparseable
|
|
JSON. The failure is **silent**: `tsconfigPathsPlugin` returns null, esbuild falls
|
|
back to autodiscovering the repo's own `tsconfig.json`, and `next/link` resolves to
|
|
the real Next runtime — which bundles the App Router and makes every preview die
|
|
with `ReferenceError: process is not defined`.
|
|
- **`next/link` is shimmed** to a plain anchor (`.design-sync/shims/next-link.tsx`)
|
|
via `compilerOptions.paths`. Header, Hero and Footer import it; the real one needs
|
|
`AppRouterContext`, which doesn't exist outside a Next app.
|
|
- **CSS edits need a full `package-build.mjs`.** `lib/preview-rebuild.mjs` only
|
|
recompiles `_preview/*.js`; it does not re-copy the stylesheet, so a CSS fix appears
|
|
to do nothing until the full build runs.
|
|
- **Never set `html { background }` in the DS stylesheet.** The card harness paints
|
|
`body{background:#fff}` in a later inline `<style>`, so a dark `html` under a white
|
|
`body` box paints a black band across the bottom of every card. `body` alone is
|
|
correct: designs get the brand surface, cards keep the harness's white chrome.
|
|
- **Fonts are self-hosted.** `next/font/google` supplies Space Grotesk + Inter at
|
|
runtime in the app, so the repo has no font files. Latin + latin-ext woff2 subsets
|
|
were downloaded from Google Fonts into `.design-sync/fonts/` (SIL OFL) and are
|
|
committed. `app/globals.css` declares `--font-sans: var(--font-sans), …`, which is a
|
|
self-reference that is invalid outside Next — `.design-sync/tailwind-entry.css`
|
|
re-declares both families with real stacks.
|
|
|
|
## Preview conventions (apply to every new preview)
|
|
|
|
- **Wrap every story in a `Surface`** — `<div className="bg-background text-foreground rounded-lg p-6">`.
|
|
Cloudrite is dark-only; `ghost`, `link`, `outline` and `border-border` are all
|
|
invisible against the harness's white card body.
|
|
- **Overlay / menu components need an open state.** Give them a `defaultOpen` story
|
|
and set `cfg.overrides.<Name> = {"cardMode":"single","primaryStory":"Open","viewport":"WxH"}`
|
|
— see `Select`. A closed trigger shows none of the compound parts.
|
|
- **Animated sections need transitions zeroed.** `Hero` fades in on a 300 ms timer
|
|
plus a 1 s transition; the capture harness only waits on fonts and images, so an
|
|
unmodified render screenshots at ~10 % opacity. See the `still` style in
|
|
`previews/Hero.tsx`. `Features` and `Process` use IntersectionObserver instead and
|
|
settle on their own.
|
|
- Use real Cloudrite copy (Auckland IT services, 021 107 7483, the four service
|
|
lines), never `foo`/`bar`.
|
|
- Recompile the CSS after authoring previews: Tailwind only emits utilities for
|
|
classes it can see, and `@source './previews'` covers the preview files.
|
|
|
|
## Excluded from the DS, on purpose
|
|
|
|
- `components/chatwidget.tsx` — Chatwoot script injector. Renders no markup and
|
|
fetches `/api/chatwoot` on mount.
|
|
- `components/ui/toaster.tsx` — legacy `Toaster`, colliding with `ui/sonner.tsx`'s.
|
|
Sonner wins; the site uses neither.
|
|
- `ThemeProvider` — in the bundle (wrap-able) but given no card.
|
|
|
|
## Re-sync risks
|
|
|
|
- **`.ds-pkg/` and `.design-sync/compiled.css` are gitignored and regenerated.** A
|
|
fresh clone must run all three `buildCmd` steps before the converter, or the entry
|
|
and stylesheet won't exist.
|
|
- **The scaffolding is inert to the app build, but only because of dot-prefixing.**
|
|
`tsconfig.json` includes `**/*.ts(x)` from the repo root with only `node_modules`
|
|
excluded; TypeScript's glob matcher skips directories beginning with `.`, which is
|
|
the sole reason `.design-sync/previews/*.tsx` (they import `'cloudrite'`, which
|
|
does not resolve in the app) and `.ds-pkg/types/**` don't enter the app's program.
|
|
Verified: `pnpm build` and a cold `tsc --noEmit` both exit 0. If any of this is ever
|
|
moved to a non-dotted path, add it to the app tsconfig's `exclude` first.
|
|
- **`next build` is not a substitute for the staging package**, but it *does* compile
|
|
the Tailwind stylesheet (~136 KB, hash-named under `.next/static/chunks/*.css`).
|
|
That is smaller than `.design-sync/compiled.css` (~170 KB) because Tailwind only
|
|
emits classes it can see and the app never references the utilities used by
|
|
`.design-sync/previews/`. The app build supplies no library entry and no
|
|
declarations, which is what `.ds-pkg/` exists to provide.
|
|
- **The fonts are a point-in-time copy.** If Google Fonts revs the woff2, nothing here
|
|
notices; the committed files keep working. Re-download only deliberately.
|
|
- **The parts tables in `.design-sync/docs/` are generated** by `make-pkg.mjs` from the
|
|
declaration emit — never hand-edit them; they are overwritten every run. The prop
|
|
signature column falls back to `—` for declarations that aren't plain functions.
|
|
- **`ROOT_OVERRIDE` in `make-pkg.mjs` is a hand-maintained exception list** (currently
|
|
just `toast.tsx → Toast`, whose first export is the provider). A new shadcn component
|
|
whose first export isn't the root needs an entry there.
|
|
- Only 40 of 61 components have authored previews; the other 21 ship the floor card and
|
|
can be authored on any later sync. `.design-sync/previews/` and the grades carry forward.
|
|
- Playwright drives the machine's installed Google Chrome via
|
|
`DS_CHROMIUM_PATH="/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"`
|
|
(no 200 MB chromium download). Export it before `package-validate.mjs` /
|
|
`package-capture.mjs`, or the render check is skipped.
|
|
|
|
## Findings for the Cloudrite team (not sync bugs)
|
|
|
|
- **`--accent` is set to the brand green**, byte-identical to `--primary`
|
|
(`oklch(0.75 0.18 145)`), in both the `:root` and `.dark` blocks of
|
|
`app/globals.css`. shadcn's default is a low-contrast neutral used for hover and
|
|
placeholder surfaces, so every `bg-accent` consumer is now vivid green — most
|
|
visibly `Skeleton` (loading blocks render as solid green bars), plus the hover
|
|
states in `dropdown-menu`, `command`, `menubar`, `navigation-menu`, `calendar`,
|
|
`item`, `toggle`, `button` and `dialog`. The previews render this faithfully
|
|
rather than papering over it. If it wasn't intentional, giving `--accent` its own
|
|
muted value is a one-line change.
|
|
- `styles/globals.css` is an unused light-theme duplicate of `app/globals.css`
|
|
(v0 scaffolding). Nothing imports it.
|
|
|
|
## Gotchas found after the first NOTES pass
|
|
|
|
- **`package-build.mjs` wipes the whole `--out` dir**, `_screenshots/` included. Any
|
|
review sheet captured before a full rebuild is gone; re-run `package-capture.mjs`
|
|
for anything still awaiting a grade.
|
|
- **Overlay content must not be given `className="relative"`.** Radix positions
|
|
`DialogContent` with `fixed` plus `translate(-50%,-50%)`; switching it to `relative`
|
|
keeps the translate but drops the centring anchor, so the card clips the title.
|
|
Size the card via `cfg.overrides.<Name>.viewport` instead.
|
|
- Radix autofocuses the first focusable in an open overlay, which screenshots as a
|
|
green text selection. `onOpenAutoFocus={(e) => e.preventDefault()}` gives a clean
|
|
still.
|
|
- `DS_CHROMIUM_PATH` must be exported for `resync.mjs` too — without it the driver's
|
|
validate stage fails `[RENDER_SKIPPED]` and skips capture on `prior_failure`.
|