T
Sign in

COMPONENTS.md — component-first forms (the thin-shell standard)

COMPONENTS.md — component-first forms (the thin-shell standard)

Rule (AGENTS.md mandate 12): a route +page.svelte is a thin shell. It loads data, then composes small components. It must not grow into a monolith. Small, well-named components keep each correction scoped to its own files, so a row session touches little and reviews stay short.

Why

If ten rows all edit one big page, every one of them wades through the same monolith. Small, well-named components keep each correction in its own file.

A file topping that list is the next thing to split.

Layout

src/routes/<area>/
  +page.server.ts        # data load + form actions (unchanged contract)
  +page.svelte           # THIN shell: composes components, holds page state
  new/+page.svelte       # thin shell for the new-record wizard
  edit/+page.svelte      # thin shell
src/lib/components/<area>/
  Wizard.svelte          # the entry wizard (steps)
  TermsPopup.svelte      # one concern per component
  WeightsPanel.svelte
  ListRows.svelte
  ...

Rules

  1. One concern per component. If a component does two unrelated things, split it. Target: each component under ~300 lines; each route page under ~150 lines.
  2. Never change the contract while splitting. Form action=, method, POST field names, share/print output and server validation stay identical. A split is a pure refactor — the full test suite must pass unchanged.
  3. State: keep page-level state in the shell; pass props down, emit events up. Shared stores (src/lib/*.svelte.ts) are fine for cross-cutting state (toasts, drafts) — don't invent new globals per form.
  4. Tests travel with the component. Split the test file the same way; keep the existing pins green.
  5. Split on demand, not everywhere. Only split a form when it becomes a hotspot (--hotspots). New forms are born split; old ones are retrofitted one hotspot at a time. Reference: C88 (the quote flow).

New-form checklist

  • +page.server.ts owns load + actions (no UI).
  • +page.svelte is a thin shell composing <area> components.
  • Each wizard step / popup / panel is its own component file.
  • docs/OWNERSHIP.md lists the new components under the area lane.