# Recipes

Everything in this stack that works, as programs you can run.

Every recipe here runs in the gate and asserts its own outcome, so a recipe that has gone out
of date turns the build red rather than teaching you something that is no longer true. Run any
of them directly:

```
node recipes/todo-list/main.ts
```

They are indexed two ways, and the second is the one you probably want.

## By task

Start here if you know what you are trying to build.

| Recipe | The job | Packages it crosses |
|---|---|---|
| [`full-stack/`](/docs/recipes/full-stack) | A page and a server in one directory: the page reaching the server in development through the dev server's proxy, and a sign-in that sets the cookie on that one origin | client, server, auth, store, modules, ui, build |
| [`todo-list/`](/docs/recipes/todo-list) | A list you add to, toggle, filter and reorder, with the list following each edit rather than being rebuilt | core, dom |
| [`two-clients/`](/docs/recipes/two-clients) | Two people editing one document at once, including what happens when they write the same slot and who yields | core, sync |
| [`optimistic-write/`](/docs/recipes/optimistic-write) | A write that applies locally before the server sees it, is refused, and is rolled back | core, sync, debug |
| [`debug/`](/docs/recipes/debug) | Finding a bug in a document you did not write | core, debug |
| [`ui/`](/docs/recipes/ui) | A page with themes, contexts, control flow, a popup and a suspend, built by vite and driven in a real browser | core, dom, ui, build |
| [`icons/`](/docs/recipes/icons) | Icons named three ways, and what each way puts in the bundle | ui, icons, build |
| [`routed-site/`](/docs/recipes/routed-site) | A site with real URLs: nested pages, a page with a parameter, a page that arrives later, a dialog the back button dismisses, and a title per page | core, dom, ui, build |
| [`ssg/`](/docs/recipes/ssg) | A routed site written out as files, served by anything, and taken over in place when the browser gets to it | dom, ui, build, ssg |
| [`translated-site/`](/docs/recipes/translated-site) | A site written in one language and launched in three: the build finds every string and writes the catalog an agent fills, each language is a tree of pages with the plural rules of its own, a stored act is compiled where it runs, and the Ukrainian page hydrates in place | core, modules, ui, build, ssg |
| [`static/`](/docs/recipes/static) | A generated site served by the stack's own server: one process is the whole deployment, and the page still comes alive where it stands | modules, server, ui, build, ssg, static |
| [`health/`](/docs/recipes/health) | A deploy's verification: the health endpoint polled until the shipped build is the one answering, and the two states a poll must not mistake for health | store, modules, server, auth, health |
| [`logs/`](/docs/recipes/logs) | A page recorded end to end in a browser and the visit read back: an error, a rejection, a console line, a failed call on both sides, a commit's shape with a private slot absent, a typed character never stored, sign-in mid-visit | store, modules, server, auth, logs, ui, client |
| [`uploads/`](/docs/recipes/uploads) | A page uploads pictures under the gate and they paint from `/files/<id>`; each refusal reaches the page with its reason, a module makes a file of its own, and the static battery behind it never sees a file | store, modules, server, auth, static, uploads, ui, client |
| [`notify/`](/docs/recipes/notify) | Two pages of one user hear a send live and mark it read for each other, a device registered from the page, email and push against two fakes, a failed mail kept, a forged write refused, a restart, and a server with no store sending a contact form's mail | store, modules, server, auth, notify, ui, client |
| [`room/`](/docs/recipes/room) | An act module stored on the server, run in a frame on the page: the board it shares reaches the server, its ask carries the page's identity, its own stage navigates on the page's URL under the host act, an error inside reaches the page's logs, and the frame paints but cannot fetch | sandbox, server, auth, logs, ui, client, build |
| [`documents-on-postgres/`](/docs/recipes/documents-on-postgres) | Documents kept in Postgres: a writer killed mid-edit, eight processes opening one name at once, and a path declared after the data was there | store |
| [`posts-to-pages/`](/docs/recipes/posts-to-pages) | Pages written while the application runs: a post published over a socket becomes a page, and a scheduled full write refreshes the sitemap | store, modules, server, jobs, ui, ssg |
| [`accessible-page/`](/docs/recipes/accessible-page) | A page everyone can use, driven by keyboard and audited in both modes, and each guardrail catching one page written wrong: the build refusing an element no one can read, the mount throwing on a nameless button and a page with no language, `audit` and `walk` reading what only the rendered page shows | build, ui, testing |
| [`backend/`](/docs/recipes/backend) | The boot pattern to copy: a twelve-line boot file and a folder of modules, one holding a document, one the rules, one a scheduler, one the gate, and one configuring a battery module | store, modules, server, auth, jobs, client |

## By package

Start here if you know which package you need and want to see it do its hardest thing. What
each of these has to demonstrate is the table in [`docs/architecture.md`](https://github.com/torrinworx/aweft/blob/9a5bb24770dc7555257f8a307d79917efc58df70/docs/architecture.md).

[`codec/`](/docs/recipes/codec), [`core/`](/docs/recipes/core), [`schema/`](/docs/recipes/schema), [`sync/`](/docs/recipes/sync), [`store/`](/docs/recipes/store), [`modules/`](/docs/recipes/modules), [`sandbox/`](/docs/recipes/sandbox), [`server/`](/docs/recipes/server), [`jobs/`](/docs/recipes/jobs),
[`dom/`](/docs/recipes/dom), [`ui/`](/docs/recipes/ui), [`icons/`](/docs/recipes/icons), [`build/`](/docs/recipes/build), [`ssg/`](/docs/recipes/ssg), [`static/`](/docs/recipes/static), [`health/`](/docs/recipes/health), [`logs/`](/docs/recipes/logs), [`uploads/`](/docs/recipes/uploads), [`notify/`](/docs/recipes/notify), [`debug/`](/docs/recipes/debug).

## What a recipe is

A small real program that does a job someone would actually have. It uses public exports only,
exactly as you would from outside this repo. It asserts what it expects and exits nonzero when
an assertion fails.

A recipe that restates a unit test does not count, and neither does one that works around a
rough edge: friction found while writing one is a defect in the package, fixed there.

Each ends by saying what it does **not** do for you, because the thing you are about to assume
is usually the thing that will cost you an afternoon.

## Adding one

A package is not finished until it has a recipe ([`AGENTS.md`](https://github.com/torrinworx/aweft/blob/9a5bb24770dc7555257f8a307d79917efc58df70/AGENTS.md), definition of done, item 6). A
task recipe needs no permission: if you had a question and the answer took you more than a few
minutes to work out, that is a recipe.

Register it in the [`recipes`](/docs/recipes) script in the root `package.json`, and add its directory to a
`tsconfig.json` that can see the packages it uses, so it is typechecked as well as run.
