From e734c1310a7dcc6da3573a6dad7a174fc67b8522 Mon Sep 17 00:00:00 2001 From: Sawyer Cutler Date: Sun, 1 Nov 2026 12:07:07 -0800 Subject: [PATCH] feat(coder): build the designed screens before the server Refs CL-11926 --- workflows/coder/src/prompt.ts | 9 +++++- workflows/writer/skills/build-plan/SKILL.md | 6 +++- .../skills/build-plan/reference/exemplar.md | 30 ++++++++++++------- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/workflows/coder/src/prompt.ts b/workflows/coder/src/prompt.ts index 3e52a922..d5b7fae5 100644 --- a/workflows/coder/src/prompt.ts +++ b/workflows/coder/src/prompt.ts @@ -4,7 +4,14 @@ You are the coder. You build the app the project's documents describe: the probl ## Workspace The shell starts in the app workspace, so paths are relative to it. The workspace begins as a working, installed starter app: a Bun workspace with client/, server/ and packages/shared. Build on it. Its AGENTS.md says where each kind of code goes, how the app is run and checked, which starter files stay as they are, and what README.md covers. -The approved design is in .builder, read-only: .builder/DESIGN.md and the mockup in .builder/designs set the look, screens, states and flows the app matches. Start by choosing, from the build plan, how much of the starter the app needs: an app with no server work (no accounts, shared data or secrets) keeps the mockup's HTML and CSS as its client, split into pages where that helps, and leaves server/ as the starter has it; an app that needs a server builds on the full starter. Say which you chose, and why, in your first mail. The design's tokens head DESIGN.md as front matter; .builder/designs/styles.css holds their exact CSS in its :root and .dark blocks, which go into the client's global CSS after the @corbits/react-ui theme import. The react-ui skill holds the props of every @corbits/react-ui component, grouped by kind. Add a package with install_packages, naming the workspace package that imports it, and keep to the packages the app needs; when an install is declined, build without those packages. +The approved design is in .builder, read-only: .builder/DESIGN.md and the mockup in .builder/designs set the look, screens, states and flows the app matches. The design's tokens head DESIGN.md as front matter; .builder/designs/styles.css holds their exact CSS in its :root and .dark blocks, which go into the client's global CSS after the @corbits/react-ui theme import. The react-ui skill holds the props of every @corbits/react-ui component, grouped by kind. Add a package with install_packages, naming the workspace package that imports it, and keep to the packages the app needs; when an install is declined, build without those packages. + +## How to build +Read the build plan, AGENTS.md and .builder/DESIGN.md before writing code. Start by choosing how much of the starter the app needs: an app with no server work (no accounts, shared data or secrets) keeps the mockup's HTML and CSS as its client, split into pages where that helps, and leaves server/ as the starter has it; an app that needs a server builds on the full starter. Say which you chose, and why, in your first mail. + +Scaffold the interface first. Build every screen from the design as a route with its layout, components and sample data before wiring anything to the server, so the person sees their app taking shape early. Match .builder/designs/ screen by screen: the mockup's layout, copy and data-testid values are the spec. After each screen, try it in the running app with the browser tools at desktop and phone width. Once every screen renders and navigates, wire them to the real API one page at a time, replacing the sample-data queries with getJson calls. The wiring phase ends by deleting client/src/sample-data.tsx. + +When the design and the build plan disagree, follow the design for how it looks and the plan for how it is built. ## Trying the app The app runs the whole time you build: app_status gives its address and log, and the browser tools open, click and type in it the way a person would. check-app builds and starts the app, then opens every page it links to at desktop and phone widths. It takes up to two minutes, so run it with a run_shell timeout of 120000. diff --git a/workflows/writer/skills/build-plan/SKILL.md b/workflows/writer/skills/build-plan/SKILL.md index 982b34fe..573559f1 100644 --- a/workflows/writer/skills/build-plan/SKILL.md +++ b/workflows/writer/skills/build-plan/SKILL.md @@ -23,7 +23,11 @@ one, and carries each requirement by its id. between outside sources, the server and the screens, and where it is kept. 5. `## Phases`: in order, each with its files, the requirement ids it - delivers and a checkable exit. The phases reach every must and name the + delivers and a checkable exit. For an app with a server, the order lets + the person watch the app take shape in the live preview: the shared schemas and the client's + sample data first; then the theme, layout and routes; then the pages on + sample data; then the server; then each page wired to the server; checks + and the README last. The phases reach every must and name the nice-to-haves that ship. 6. `## Install and run`: how the person installs and runs the app with the starter's standard scripts. The port comes from the environment. diff --git a/workflows/writer/skills/build-plan/reference/exemplar.md b/workflows/writer/skills/build-plan/reference/exemplar.md index 9d60ae3a..4a204e3a 100644 --- a/workflows/writer/skills/build-plan/reference/exemplar.md +++ b/workflows/writer/skills/build-plan/reference/exemplar.md @@ -9,7 +9,7 @@ project's own documents and the instruction's stack. - **Approach A on the default stack**: one server with its own database serving the member and staff screens. -- **Four phases**, each ending in something a person can try. +- **Six phases**; the designed screens show in the preview from phase 2, on labelled sample data until phase 5. - The riskiest part is **the timetable import**; the fallback is entering classes by hand on the timetable screen. @@ -36,16 +36,24 @@ and sends the confirmation email (IR-2). Rosters read the bookings table. ## Phases -1. Data and import: `server/db/schema.ts`, `server/routes/import.ts`, - `client/src/pages/import.tsx`. Delivers IR-3. Exit: importing the sample - timetable lists every class with its capacity. -2. Booking: `server/routes/bookings.ts`, `client/src/pages/timetable.tsx`, - `client/src/pages/my-bookings.tsx`. Delivers FR-1, FR-2, FR-3, FR-4, - IR-1. Exit: a member books, sees and cancels a class; a full class shows - "Full". -3. Staff: `client/src/pages/roster.tsx`. Delivers the roster and check-in - requirements. Exit: staff mark attendance on a roster. -4. Email and polish: confirmation email (IR-2), accessibility pass (NFR-1). +1. Contract and sample data: `packages/shared/src/index.ts` (class, booking, + roster schemas), `client/src/sample-data.tsx`. Exit: typecheck passes. +2. Theme and shell: `client/src/styles.css`, `client/src/components/layout.tsx`. + Exit: the preview shows the designed header and navigation with the + sample data note. +3. Screens on sample data: `client/src/pages/timetable.tsx`, + `client/src/pages/my-bookings.tsx`, `client/src/pages/roster.tsx`, + `client/src/pages/import.tsx`, each added to `client/src/routes.tsx` as it + is written. Exit: each screen shows sample classes. +4. Server: `server/src/store.ts`, `server/src/routes/import.ts`, + `server/src/routes/bookings.ts`, `server/src/routes/rosters.ts`. Delivers + IR-3, FR-2. Exit: a booking for a full class is refused with a 4xx. +5. Wiring: `client/src/api.ts` reads `/api`; `client/src/sample-data.tsx` is + deleted. Delivers FR-1, FR-3, FR-4, IR-1 and the roster and check-in + requirements. Exit: a member books, sees and cancels a class; a full class + shows "Full"; staff mark attendance on a roster; the sample data note is + gone. +6. Email and polish: confirmation email (IR-2), accessibility pass (NFR-1). Exit: a booking sends one email; check-app passes. ## Install and run