Imported from PaDreyer/boring-api (
examples/fullstack/AGENTS.md). Install upstream withnpx skills add PaDreyer/boring-api --skill fullstack. Copyright stays with the author.
Working on the fullstack reference
Read the shared Agent guide before changing this application. The repository AGENTS.md also applies. This is one consumer with one PostgreSQL database, React SPA, server-rendered order pages and a durable worker. The specifics below supplement the shared workflow.
- Build all packages with
pnpm build, then inspect withpnpm example:fullstack:inspectbefore adding functionality. Reuseorders.createandorders.get; do not add another orders service, database pool or request helper. - Keep the PostgreSQL schema in
infra/db/migrations.ts. Append migrations; never edit applied SQL. Parameterize SQL and validate rows with shared schemas. The facade selects the transaction boundary; the private orders service writes the order and audit event through the storage port in one transaction. - Root
+configvalidates application configuration. Setup owns dependency construction and registers the PostgreSQL pool withctx.onCloseimmediately. Infrastructure never calls business operations. Add external SDKs behind this same boundary, not in routes or pages. Import adapters/configuration via$infra/<path>and public module entries via$modules/<name>/.... The migration script preloadsregister-source.tsso its own imports use the same source compiler as the API. - Use
web/client/api.tsfor browser requests,ApiErrorfor HTTP failures and public schemas for form validation. Import generatedApiRouteswithimport type { ApiRoutes } from "$client"; never import the server entry point or a facade into browser source. - Keep presentation under
web/server. Pages take injected facades and the current execution context; they validate inputs and escape HTML. They do not access storage. - Reuse
executions/create-order.tsfor controlled non-HTTP orders. HTTP, pages and controlled executions pass the framework-created context to the same facade. The application owns listeners and shutdown; call itsclose()to drain work before disposing resources. - Permissions belong in both route declarations and business operations. The environment-controlled bearer-token provider is a demo, not production login.
- Jobs in
jobs/orders/create/job.tsreuseorders.create. Queued payloads require requestId; preserve the order/audit/idempotency transaction and explicit worker grants. Run migrations explicitly, then use separate HTTP and worker processes. See the shared job reference. - Run the fullstack check/build scripts and repository checks. Set
BORING_TEST_DATABASE_URLto an isolated test database to include the real PostgreSQL test inpnpm test; it creates and removes its own random schema.