code.scaffold_react_node
The engine behind the Full-stack app generator: given a name, a description, a list of pages and API routes, it writes a real, runnable npm-workspaces monorepo — not a single-file demo.
Schema
Input = { name: string, // product/project name description: string, // what the app is for; drives generated copy and sample data pages?: Array<string | { name: string, path?: string, description?: string }>, apiRoutes?: Array<string | { method: 'GET'|'POST'|'PUT'|'PATCH'|'DELETE', path: string, description?: string }>, style?: string, // default 'clean, modern, generous whitespace, one accent colour' dir?: string, // sub-folder of the workspace to write into build?: boolean, // default true — npm install + vite build, best effort buildTimeoutMs?: number, // 10s-10min, default 180000}
Output = { dir: string, files: string[], pages: Array<{ name: string, path: string, file: string }>, apiRoutes: Array<{ method: string, path: string, file: string }>, built: boolean, previewPath: string | null, // relative path of dist/index.html when the build succeeded buildLog: string, contentSource: 'model' | 'placeholder', costUsd: number, runSteps: string[],}apiRoutes accepts a loose string shorthand too: "GET /api/items" or just "/api/items"
(defaults to GET) parses into the structured form.
What actually gets written
A real workspace: root package.json (npm workspaces: apps/*, packages/*), a packages/shared
package for types shared between front and back, apps/web (Vite + React 19 + React Router 7,
tsconfig, a hand-styled styles.css with an accent colour, one .tsx file per page complete with
nav), apps/api (Fastify 5 + CORS, one route file per API route, /api/health), and a real
README.md documenting how to run it. Every page and route’s copy/sample-data comes from one
cheap-tier structured call (planWithModel()) — coverage is guaranteed by merging the model’s
output back onto a deterministic placeholder plan for anything it dropped, so every requested page
and route always exists even if the model forgets one.
The build step
If build is true (the default), it runs npm install then npm run build for the web workspace
only, best-effort, within buildTimeoutMs. Secrets are stripped from the child process environment
first (OPENROUTER, SECRET, TOKEN, PASSWORD env keys deleted) before the install/build runs.
On success, previewPath points at apps/web/dist/index.html — this is what
assembleOutputs() later detects as a react-app/fullstack-app output with a
live preview. If the build fails or times out, the skill still returns success with built: false —
the source is still there and downloadable even without a working preview.
Example
curl -s -X POST http://localhost:4000/api/studio/skills/invoke \ -H 'content-type: application/json' -b cookies.txt \ -d '{"name":"code.scaffold_react_node","input":{"name":"Ledgerly","description":"A shared expense tracker for a household.","pages":["Home","History"],"apiRoutes":["GET /api/expenses","POST /api/expenses"],"build":false}}'