benjivers/val Public Public: anyone can read this; the crew can change it.
Files 03302de7b925b15e6e7d266e9a2ca7c5b4a55296
Working on this app
You are one of the crew on this repository. The forge runs the app for you: production follows the default branch, and every pull you open gets a preview at its own address, deployed from your branch as you push.
The rules
- Work on the branch you were given. You cannot move the default branch;
a person merges your pull once it is reviewed.
- Keep state under
FORGE_APP_DATA. Never write elsewhere at runtime. - Run
bun testbefore you push. It is the check the pull shows, and every
behaviour you add gets a test that would fail without it.
src/tty.tsis the app's terminal interface. The exact command that
reaches it is FORGE_APP_SSH at runtime; print that verbatim wherever the
app tells people how to connect. Keep it working and keep it useful: what
a person can do on the web page they should be able to do here too.
- Keep it dependency-free unless a dependency is clearly worth it, and say
why in the pull. A dependency is code you now maintain.
- When you are done, push and stop. Your last message becomes the pull's
description: say what changed, what you chose not to do, and what to look at in the preview.
The bar
- Shape: small modules named after one concept, plain data in and out. When
src/server.ts stops fitting in one read, split it — src/db.ts for
the schema and queries, src/pages/<page>.ts for rendering,
src/routes.ts for the table of paths — and keep the pattern you find.
- Security: every input is validated at the boundary and every output is
escaped; every response carries the security floor in src/server.ts
(keep it, extend it); a POST that is not same-origin is refused; secrets
come from the environment, never the repository; no eval, no shell
built from user text; a private thing needs a session in an HttpOnly cookie.
Every request body is capped by the bytes actually read (readBody in
src/server.ts) — never by a Content-Length, which a chunked request does
not have and a lie does not honour. HEAD answers like GET.
An app with an owner or admin is never claimed by whoever visits first:
the first sign-in needs a secret only the operator holds — a password from
the environment, or a one-time token printed to the run log and the app's
terminal — and a generated password is shown there once, never on a page.
- Secrets come from the environment: the app's Settings → Environment
(write-only), read at start-up; never the repository.
- Speed: the first paint is server-rendered HTML; JavaScript is small, in
files under static/ named by content and cached for a year; no layout
shift; the common request answers in milliseconds; work that can wait is
done after the response.
- A phone is a first-class client: the page works at 360px wide with no
horizontal scroll, every control is at least 44px on a side, and the keyboard reaches everything a mouse does.
- Finish: the app boots,
/answers, the README says how to use it and
what is real versus simulated, forge.json says how to run it.