Prerequisites
- Node ≥ 20 (24 in use)
- pnpm ≥ 11
- gh (GitHub CLI) — for PR / repo workflows
Setup
pnpm installCommands (root)
| Cmd | Effect |
|---|---|
pnpm dev | Turbo orchestrates dev servers for every app (currently only apps/web on :3000) |
pnpm build | Builds every app (static export for web) |
pnpm lint | ESLint across every workspace package |
pnpm typecheck | tsc --noEmit across every package |
pnpm clean | Wipes build outputs + root node_modules |
Commands (per-package)
pnpm --filter @arno/web dev # Next.js dev
pnpm --filter @arno/web build # → apps/web/out/
pnpm --filter @arno/web typecheckCSS convention
Plain global CSS, not CSS Modules, not SCSS. One .css file next to every .tsx, imported explicitly:
import "./component-name.css";Naming: kebab-case, pattern {component}-{element}[-{modifier}]. No BEM __/--. Active state via a space class:
.library-page-tab { ... }
.library-page-tab.is-active { ... }
.library-page-tabs-hint { ... }Modifier prefixes: is-* (state), has-* (presence). No bare active/open/disabled (collides with library styles).
Why this way:
- CSS Modules under Next 14 static export break clean class names in Storybook (Vite builder) — different strings in dev vs prod
- Global scope is OK with a component prefix — collision risk is low, inspecting in DevTools is easier
- Not SCSS: the PostCSS pipeline already provides
:has(), nesting, custom properties
Tokens (CSS vars) hot-swap = single source of truth for design tokens. tokensStore.applyPublishedToDOM writes via document.documentElement.style.setProperty('--' + name, value) — the browser repaints without a React rerender. See ADR 0020 §D3, ADR 0025.
Spacing scale (when touching padding/margin/gap/radius): strictly 0/2/4/8/12/16/20/24/32/40/48/56/64, round up only. No 3/9/14/22.
Monorepo
| Folder | What |
|---|---|
apps/web | Next.js 14 App Router — frontend |
tools/tsconfig | Shared tsconfig (base, nextjs, node) |
tools/eslint-config | Shared ESLint configs (base, next) |
packages/ | (TBD) — domain types, editor, render-adapter, ... |
Cloudflare Pages deploy
See cloudflare-pages.md.