ucode-agent 1.26.2 → 1.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +438 -399
- package/package.json +1 -1
- package/skills/build-app/DIGEST.md +94 -0
- package/skills/build-app/SKILL.md +222 -181
- package/skills/ui-ux/DIGEST.md +135 -0
- package/src/core/context.js +164 -151
- package/src/core/loop.js +189 -24
- package/src/core/provider.js +6 -0
- package/src/core/skills.js +189 -165
- package/src/core/window.js +27 -2
- package/src/tools/blocks.js +117 -27
- package/src/tools/index.js +71 -23
- package/src/tools/scaffold.js +104 -14
- package/src/ui/plain.js +358 -351
- package/src/ui/screen.js +1574 -1475
- package/src/ui/theme.js +587 -412
- package/templates/blocks/plain/filter-bar.js +133 -0
- package/templates/blocks/plain/item-list.js +249 -0
- package/templates/blocks/plain/modal.js +141 -0
- package/templates/blocks/plain/store.js +93 -0
- package/templates/blocks/plain/theme-toggle.js +116 -0
- package/templates/blocks/plain/toast.js +107 -0
- package/templates/plain-html/styles.css +4 -0
package/package.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Building something from nothing — the short form
|
|
2
|
+
|
|
3
|
+
The failure mode is not bad code. It is a folder of files that has never been
|
|
4
|
+
run, handed over as if it works.
|
|
5
|
+
|
|
6
|
+
## 1. Decide the shape before any file exists
|
|
7
|
+
|
|
8
|
+
One line each: **what it does**, **the core loop** (the one path that must work
|
|
9
|
+
perfectly), **the stack**, **the file list**.
|
|
10
|
+
|
|
11
|
+
| Need | Choose |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| One page, no secrets, no server | `create_app` with `plain-html` |
|
|
14
|
+
| Interactive client app, no secrets | `plain-html` still, unless it truly needs a build |
|
|
15
|
+
| Pages plus a server, secrets, API routes, SEO | `create_app` with `next-shadcn` |
|
|
16
|
+
| An API on its own | Node (Hono/Express) or Python (FastAPI) |
|
|
17
|
+
|
|
18
|
+
Pick the smallest one that does the job and mean it: a tasks app, a
|
|
19
|
+
calculator, a timer, a game, a visualisation — all one page. Next.js costs an
|
|
20
|
+
install and a build, minutes the user waits through, and buys nothing an app
|
|
21
|
+
with no server needs.
|
|
22
|
+
|
|
23
|
+
## 2. Start from the starter — and finish in the same call
|
|
24
|
+
|
|
25
|
+
`create_app` takes `files`, so for a one-page app the scaffold and the whole
|
|
26
|
+
app are one call:
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
create_app({ folder: "tide", name: "Tide", files: [
|
|
30
|
+
{ path: "tide/index.html", content: "…" },
|
|
31
|
+
{ path: "tide/styles.css", content: "…" },
|
|
32
|
+
{ path: "tide/app.js", content: "…" },
|
|
33
|
+
]})
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Every round trip is ten to forty seconds of the user's time, so one call
|
|
37
|
+
instead of four is most of how long the build takes.
|
|
38
|
+
|
|
39
|
+
- `plain-html` is the default: three files, no install, no build. Its files
|
|
40
|
+
come back in full inside the result — **never read them back**.
|
|
41
|
+
- `next-shadcn` installs in the background; commands in that folder wait for
|
|
42
|
+
it on their own, so start writing components at once. Re-tint `globals.css`
|
|
43
|
+
for the app's direction rather than shipping the slate default.
|
|
44
|
+
- Never run `create-next-app` or `shadcn init`. Nothing you run has a
|
|
45
|
+
keyboard: every scaffolder needs its answers as flags up front.
|
|
46
|
+
|
|
47
|
+
## 2b. Do not type what already exists
|
|
48
|
+
|
|
49
|
+
`add_block` has the pieces every app needs, written for whichever starter this
|
|
50
|
+
one uses: a list you can add to, tick off, rename and remove; a filter row; a
|
|
51
|
+
localStorage store; a dialog; toasts; a theme toggle; a table; an empty state.
|
|
52
|
+
Call it before writing any of those by hand. Each is a hundred lines you skip,
|
|
53
|
+
and typing is the slowest part of a build — a page assembled from blocks is
|
|
54
|
+
done minutes before the same page typed out. Call `add_block` with no name to
|
|
55
|
+
see what fits this app.
|
|
56
|
+
|
|
57
|
+
## 3. Structure
|
|
58
|
+
|
|
59
|
+
One component per file, named for what it is, not a 600-line `page.tsx`. In
|
|
60
|
+
Next.js: `src/app` (routes, `globals.css`, `api/<name>/route.ts`),
|
|
61
|
+
`src/components/<feature>/`, `src/lib/` for outside services and schemas.
|
|
62
|
+
Server components by default, `"use client"` only where it is interactive.
|
|
63
|
+
Types at every boundary; parse external data rather than trusting its shape.
|
|
64
|
+
|
|
65
|
+
## 4. Secrets and outside services
|
|
66
|
+
|
|
67
|
+
- **A key never reaches the browser.** It lives in a server route. Anything
|
|
68
|
+
imported by a `"use client"` file ships to every visitor, including a
|
|
69
|
+
"hardcoded for now" key — put it in a server-only module and say where.
|
|
70
|
+
- Every outbound call gets a timeout (`AbortSignal.timeout(60_000)`), a status
|
|
71
|
+
check, and an error that says what failed — surfaced as a real message,
|
|
72
|
+
never a silent `catch {}`.
|
|
73
|
+
- Calling a model: ask for JSON and parse it defensively (extract the first
|
|
74
|
+
`{...}`, validate, clamp numbers), put the judgement rules in the prompt
|
|
75
|
+
explicitly, and make the route timeout longer than the model takes.
|
|
76
|
+
|
|
77
|
+
## 5. Build order
|
|
78
|
+
|
|
79
|
+
Skeleton and design tokens first, so everything after is styled correctly the
|
|
80
|
+
first time; then the server route with the real integration; then the core
|
|
81
|
+
loop UI wired to it; then every state — empty, loading, success, error,
|
|
82
|
+
invalid input; then polish: motion, responsive, copy, title and metadata.
|
|
83
|
+
|
|
84
|
+
## 6. Prove it works, then report
|
|
85
|
+
|
|
86
|
+
`npm run build` type-checks and lints — a build that fails is not done. Start
|
|
87
|
+
it (`npm run dev` backgrounds itself and returns the URL; do not start it
|
|
88
|
+
twice), then `look_at_app` on every page. A clean build proves it compiles,
|
|
89
|
+
not that it works. Fix what you find and check again.
|
|
90
|
+
|
|
91
|
+
Done means: the core loop works end to end, no TODO, no placeholder copy, no
|
|
92
|
+
dead buttons, no console errors, every async action has its states, secrets
|
|
93
|
+
server-side, build passes. Then say what you built, how to run it, and — in
|
|
94
|
+
one sentence — anything you did not finish or could not test.
|
|
@@ -1,181 +1,222 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: build-app
|
|
3
|
-
description: Take an app from nothing to running and finished — stack choice, non-interactive scaffolding, project structure, secrets, AI and API integration, error handling, and proving it works before saying it does.
|
|
4
|
-
auto: scaffold, new project, from scratch, build an app, make an app, create an app, build a website, make a website, build a site, build me a, next.js app, nextjs app, next app, react app, vite app, shadcn, create-next-app, full stack, fullstack, saas, mvp
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# Building something from nothing
|
|
8
|
-
|
|
9
|
-
The failure mode is not bad code. It is a folder of files that has never been
|
|
10
|
-
run, handed over as if it works. Everything here is ordered to prevent that.
|
|
11
|
-
|
|
12
|
-
## 1. Decide the shape, out loud, before any file exists
|
|
13
|
-
|
|
14
|
-
One line each:
|
|
15
|
-
|
|
16
|
-
- **What it does** — the sentence a user would say.
|
|
17
|
-
- **The core loop** — the one path through it that must work perfectly
|
|
18
|
-
(e.g. upload a photo → analysed → see a score and the problems).
|
|
19
|
-
- **The stack, and why** — the smallest thing that does the job:
|
|
20
|
-
|
|
21
|
-
| Need | Choose |
|
|
22
|
-
| --- | --- |
|
|
23
|
-
| One page, no secrets, no server |
|
|
24
|
-
| Interactive client app, no secrets |
|
|
25
|
-
| Pages plus a server, secrets, API routes, SEO |
|
|
26
|
-
| An API on its own | Node (Hono/Express) or Python (FastAPI) |
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
```
|
|
134
|
-
|
|
135
|
-
- **
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
1
|
+
---
|
|
2
|
+
name: build-app
|
|
3
|
+
description: Take an app from nothing to running and finished — stack choice, non-interactive scaffolding, project structure, secrets, AI and API integration, error handling, and proving it works before saying it does.
|
|
4
|
+
auto: scaffold, new project, from scratch, build an app, make an app, create an app, build a website, make a website, build a site, build me a, next.js app, nextjs app, next app, react app, vite app, shadcn, create-next-app, full stack, fullstack, saas, mvp
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Building something from nothing
|
|
8
|
+
|
|
9
|
+
The failure mode is not bad code. It is a folder of files that has never been
|
|
10
|
+
run, handed over as if it works. Everything here is ordered to prevent that.
|
|
11
|
+
|
|
12
|
+
## 1. Decide the shape, out loud, before any file exists
|
|
13
|
+
|
|
14
|
+
One line each:
|
|
15
|
+
|
|
16
|
+
- **What it does** — the sentence a user would say.
|
|
17
|
+
- **The core loop** — the one path through it that must work perfectly
|
|
18
|
+
(e.g. upload a photo → analysed → see a score and the problems).
|
|
19
|
+
- **The stack, and why** — the smallest thing that does the job:
|
|
20
|
+
|
|
21
|
+
| Need | Choose |
|
|
22
|
+
| --- | --- |
|
|
23
|
+
| One page, no secrets, no server | `create_app` with the `plain-html` starter |
|
|
24
|
+
| Interactive client app, no secrets | `plain-html` still, unless it truly needs a build |
|
|
25
|
+
| Pages plus a server, secrets, API routes, SEO | `create_app` with `next-shadcn` |
|
|
26
|
+
| An API on its own | Node (Hono/Express) or Python (FastAPI) |
|
|
27
|
+
|
|
28
|
+
Choose the smallest one that does the job, and mean it: a tasks app, a
|
|
29
|
+
calculator, a timer, a game, a visualisation, a converter — all one page.
|
|
30
|
+
Next.js costs an install and a build, minutes the user waits through, and
|
|
31
|
+
buys nothing an app with no server needs.
|
|
32
|
+
|
|
33
|
+
- **The file list** — the whole tree, before creating any of it.
|
|
34
|
+
|
|
35
|
+
If there is a user interface, the `ui-ux` skill is already loaded. Decide the
|
|
36
|
+
design direction now, not after the logic works. If the app calls a model,
|
|
37
|
+
load `ai-features`; if it has accounts, keys or uploads, load `security`.
|
|
38
|
+
|
|
39
|
+
## 2. Start from the starter — and finish in the same call
|
|
40
|
+
|
|
41
|
+
`create_app` copies a starter that is already known to build. It also takes
|
|
42
|
+
`files`, so for a one-page app the scaffold and the whole app are one call:
|
|
43
|
+
|
|
44
|
+
```
|
|
45
|
+
create_app({
|
|
46
|
+
folder: "tide", name: "Tide", description: "…",
|
|
47
|
+
files: [
|
|
48
|
+
{ path: "tide/index.html", content: "…" },
|
|
49
|
+
{ path: "tide/styles.css", content: "…" },
|
|
50
|
+
{ path: "tide/app.js", content: "…" },
|
|
51
|
+
],
|
|
52
|
+
})
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
That is the whole build. Every round trip is ten to forty seconds of the
|
|
56
|
+
user's time, so the difference between one call and four is most of how long
|
|
57
|
+
this takes.
|
|
58
|
+
|
|
59
|
+
- **`plain-html` is the default**: three files, no install, no build, opens in
|
|
60
|
+
a browser. Its files come back in full inside the result — **never read them
|
|
61
|
+
back**, they are already in front of you.
|
|
62
|
+
- **`next-shadcn`** only when the app needs routes, a database or many
|
|
63
|
+
screens. It copies Next.js 16, TypeScript, Tailwind 4 and shadcn with its
|
|
64
|
+
components, light/dark and toasts, and starts `npm install` in the
|
|
65
|
+
background — commands in that folder wait for the install on their own, so
|
|
66
|
+
start writing components at once. Read the `TEMPLATE.md` in the result, and
|
|
67
|
+
re-tint `globals.css` for the app's direction.
|
|
68
|
+
|
|
69
|
+
Never run `create-next-app` or `shadcn init` — that is four minutes and a
|
|
70
|
+
dozen steps the starter already did.
|
|
71
|
+
|
|
72
|
+
### Other stacks
|
|
73
|
+
|
|
74
|
+
Nothing you run has a keyboard. A scaffolder that asks "Would you like to use
|
|
75
|
+
TypeScript?" gets no answer and fails, so give it every answer up front:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
# Next.js into ./my-app (use . to fill the current folder — it must be empty)
|
|
79
|
+
npx create-next-app@latest my-app --ts --tailwind --eslint --app --src-dir --import-alias "@/*" --use-npm --yes
|
|
80
|
+
|
|
81
|
+
# shadcn/ui, from inside the project — every component you need, in one add
|
|
82
|
+
npx shadcn@latest init -d -y
|
|
83
|
+
npx shadcn@latest add button card input label badge progress separator skeleton sonner tooltip -y
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- `create-next-app` refuses a folder that already has files. If the current
|
|
87
|
+
folder is not empty, scaffold into a named subfolder and pass it as `cwd` to
|
|
88
|
+
every later command.
|
|
89
|
+
- For any other scaffolder, find the flag for every question (`--help`) first.
|
|
90
|
+
- Install dependencies once, all together: `npm i zod lucide-react` — not one
|
|
91
|
+
`npm i` per package.
|
|
92
|
+
|
|
93
|
+
## 2b. Do not type what already exists
|
|
94
|
+
|
|
95
|
+
`add_block` has the pieces every app needs, written once and carefully, for
|
|
96
|
+
whichever starter this app uses. For a plain page: `item-list` (add, tick off,
|
|
97
|
+
rename, remove, empty state, counts, keyboard), `filter-bar`, `store`
|
|
98
|
+
(localStorage that survives private mode and stays in step across tabs),
|
|
99
|
+
`modal`, `toast`, `theme-toggle`. For React: `app-shell`, `page-header`,
|
|
100
|
+
`empty-state`, `data-table`, `stat-cards`.
|
|
101
|
+
|
|
102
|
+
Call it before writing any of those by hand. Two reasons, and the second is
|
|
103
|
+
the one that gets forgotten:
|
|
104
|
+
|
|
105
|
+
- They are finished. Every state, the keyboard, small screens, the cases a
|
|
106
|
+
first draft skips.
|
|
107
|
+
- They are already typed. Typing is the slowest part of a build — a few
|
|
108
|
+
thousand tokens at forty a second — so a page assembled from blocks is done
|
|
109
|
+
minutes before the same page written out line by line.
|
|
110
|
+
|
|
111
|
+
They land as ordinary source files. Edit them to suit the app rather than
|
|
112
|
+
working around them.
|
|
113
|
+
|
|
114
|
+
## 3. Structure it like a real project
|
|
115
|
+
|
|
116
|
+
For Next.js App Router:
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
src/
|
|
120
|
+
app/
|
|
121
|
+
layout.tsx fonts, metadata, <body> shell, Toaster
|
|
122
|
+
page.tsx the screen — composes components, holds little logic
|
|
123
|
+
globals.css design tokens and the shadcn theme variables
|
|
124
|
+
api/<name>/route.ts server-only endpoints; the only place secrets live
|
|
125
|
+
components/
|
|
126
|
+
<feature>/ one folder per feature: its pieces, split by job
|
|
127
|
+
ui/ shadcn components (generated — edit via the theme)
|
|
128
|
+
lib/
|
|
129
|
+
<service>.ts calls to outside services, typed in and out
|
|
130
|
+
schemas.ts zod schemas shared by client and server
|
|
131
|
+
utils.ts
|
|
132
|
+
types/ shared TypeScript types, if lib/ does not own them
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
- **One component per file**, named for what it is (`ScoreDial.tsx`,
|
|
136
|
+
`NutrientFindings.tsx`, `LabelUpload.tsx`), not a 600-line `page.tsx`.
|
|
137
|
+
- Server components by default; `"use client"` only on the interactive parts.
|
|
138
|
+
- Types at every boundary. Parse external data with zod rather than trusting
|
|
139
|
+
its shape.
|
|
140
|
+
|
|
141
|
+
## 4. Secrets and outside services
|
|
142
|
+
|
|
143
|
+
- **A key never reaches the browser.** It lives in a server route or server
|
|
144
|
+
action. Anything imported by a `"use client"` file ships to every visitor —
|
|
145
|
+
including a "hardcoded for now" key. If the user asks to hardcode one, put it
|
|
146
|
+
in a server-only module (`lib/server/*.ts`, or `import 'server-only'`) and
|
|
147
|
+
say where it is so they can move it to `.env.local` later.
|
|
148
|
+
- Every outbound call gets: a timeout (`AbortSignal.timeout(60_000)`), a check
|
|
149
|
+
of the response status, and an error that says what failed — surfaced to the
|
|
150
|
+
UI as a real message, never a silent `catch {}`.
|
|
151
|
+
|
|
152
|
+
### Calling an AI model (any OpenAI-compatible API)
|
|
153
|
+
|
|
154
|
+
```ts
|
|
155
|
+
// src/app/api/analyze/route.ts — runs on the server only
|
|
156
|
+
export const runtime = 'nodejs';
|
|
157
|
+
export const maxDuration = 60;
|
|
158
|
+
|
|
159
|
+
const res = await fetch('https://openrouter.ai/api/v1/chat/completions', {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
headers: { Authorization: `Bearer ${KEY}`, 'Content-Type': 'application/json' },
|
|
162
|
+
body: JSON.stringify({
|
|
163
|
+
model: 'provider/model-id',
|
|
164
|
+
messages: [
|
|
165
|
+
{ role: 'system', content: 'Reply with JSON only, matching this shape: {...}' },
|
|
166
|
+
{ role: 'user', content: [
|
|
167
|
+
{ type: 'text', text: 'Analyse this nutrition label.' },
|
|
168
|
+
{ type: 'image_url', image_url: { url: dataUrl } }, // data:image/jpeg;base64,...
|
|
169
|
+
] },
|
|
170
|
+
],
|
|
171
|
+
}),
|
|
172
|
+
signal: AbortSignal.timeout(60_000),
|
|
173
|
+
});
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
- **Ask for JSON and parse it defensively.** Models wrap JSON in prose or code
|
|
177
|
+
fences: extract the first `{...}` block, `JSON.parse` it, validate with zod,
|
|
178
|
+
and on failure return a clear "could not read the result" error rather than
|
|
179
|
+
crashing. Clamp numbers to their range.
|
|
180
|
+
- **Put the judgement rules in the prompt, explicitly** — thresholds, what
|
|
181
|
+
counts as "too much", what to omit. A vague prompt gives a different answer
|
|
182
|
+
every time; a specific one gives the product its consistency.
|
|
183
|
+
- **Images:** check type and size on the client (e.g. ≤ 5 MB, jpeg/png/webp),
|
|
184
|
+
downscale large photos in a canvas before upload, send as a base64 data URL.
|
|
185
|
+
- Reasoning models may take 10–60s. Show progress, and make the route's
|
|
186
|
+
timeout longer than the model's.
|
|
187
|
+
|
|
188
|
+
## 5. Build order
|
|
189
|
+
|
|
190
|
+
1. Skeleton and design tokens, so every later piece is styled correctly first time.
|
|
191
|
+
2. The server route with the real integration, tested with `curl` before any UI.
|
|
192
|
+
3. The core loop UI, wired to the real route.
|
|
193
|
+
4. Every state: empty, loading, success, error, and invalid input.
|
|
194
|
+
5. Polish: motion, responsive, copy, favicon, page title and metadata.
|
|
195
|
+
|
|
196
|
+
Use `batch_write` for the skeleton — one call, every file.
|
|
197
|
+
|
|
198
|
+
## 6. Prove it works
|
|
199
|
+
|
|
200
|
+
- `npm run build` — it type-checks and lints; a build that fails is not done.
|
|
201
|
+
- Start it: `npm run dev` goes to the background on its own and comes back with
|
|
202
|
+
the URL once ready. Do not start it twice.
|
|
203
|
+
- Exercise it: `curl` the API route with real input, then `look_at_app` on every
|
|
204
|
+
page — it loads them in a real browser at phone and desktop width and reports
|
|
205
|
+
errors, overflow and a visual review. A clean build proves it compiles, not
|
|
206
|
+
that it works.
|
|
207
|
+
- Fix what you find and check again.
|
|
208
|
+
|
|
209
|
+
## 7. Definition of done
|
|
210
|
+
|
|
211
|
+
- The core loop works end to end against the real service.
|
|
212
|
+
- No `TODO`, no placeholder copy, no dead buttons, no console errors.
|
|
213
|
+
- Every async action has loading, success and error states.
|
|
214
|
+
- Invalid input is caught with a useful message before it reaches the server.
|
|
215
|
+
- Secrets only on the server.
|
|
216
|
+
- `npm run build` passes.
|
|
217
|
+
|
|
218
|
+
## 8. Report
|
|
219
|
+
|
|
220
|
+
What you built, the URL, how to start it again, and what you checked. If
|
|
221
|
+
anything is untested or unfinished, name it — one sentence of honesty saves the
|
|
222
|
+
user an hour of finding out on their own.
|