Development

Prerequisites

  • Node ≥ 20 (24 in use)
  • pnpm ≥ 11
  • gh (GitHub CLI) — for PR / repo workflows

Setup

pnpm install

Commands (root)

CmdEffect
pnpm devTurbo orchestrates dev servers for every app (currently only apps/web on :3000)
pnpm buildBuilds every app (static export for web)
pnpm lintESLint across every workspace package
pnpm typechecktsc --noEmit across every package
pnpm cleanWipes 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 typecheck

CSS 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

FolderWhat
apps/webNext.js 14 App Router — frontend
tools/tsconfigShared tsconfig (base, nextjs, node)
tools/eslint-configShared ESLint configs (base, next)
packages/(TBD) — domain types, editor, render-adapter, ...

Cloudflare Pages deploy

See cloudflare-pages.md.