First feature in 10 minutes
Build your first feature end-to-end: database table, API route, typed UI page, tests on both sides, all passing bun run validate. The agent writes most of the code. You read diffs and check output.
Clone a fresh fork from boringstack-xyz/boringstack, then:
./setup.sh --upThis copies .env, generates the GlitchTip secret, and brings up the full Compose stack: Postgres, Valkey, api-dev with migrations, ui-dev on localhost:7331. No local Bun or Postgres needed.
Open http://localhost:7331 and create an account — signup is open in dev, and because the dev stack sends mail through Mailpit the verification email lands in the local inbox at http://localhost:8025. Click the link there to finish signing in.
Two paths
Section titled “Two paths”Fast path - use /add-full-feature directly. The agent drafts a spec, you approve, it builds. Best for small slices and exploratory work.
Spec-loop path - run bun run spec:init once, then use /spec explore, /spec slice, /spec approve, /spec build. The agent cannot write source files until you set status: approved in .specs/next.md. Best for anything touching auth, billing, multi-tenant data, or cross-app contracts.
Both paths land identical code. The spec loop adds one explicit approval gate. This page uses the fast path.
1. Pick something to build
Section titled “1. Pick something to build”Say you want support tickets. Each account lists tickets, creates them, closes them. Backend: table + service + routes. Frontend: list page + create form.
2. Run the skill
Section titled “2. Run the skill”In your agent, type:
/add-full-feature
Resource: ticketsAccount-scoped: yesFields: subject (text, required), body (text, optional), status (open/closed, default open)UI: list page + create formThe agent writes a spec and asks you to confirm. Read it before saying yes.
3. Approve and watch
Section titled “3. Approve and watch”On the API side the agent:
- Adds the
ticketstable toapps/api/src/clients/postgres/schema/app.schema.tswithaccountIdFK, indexes, and the@account-scopedmarker. - Runs
bun run db:generateto create a migration. - Writes the five-file resource pattern: service, routes, utils, constants, types, schemas. Each file gets a sibling test.
- Wires
auditLogService.record(...)on every mutation. - Runs
bun run validate. If anything fails, it loops back and fixes.
Then it regenerates the OpenAPI types in apps/ui/ so apiClient.GET("/api/v1/tickets") is typed.
On the UI side:
- New feature folder:
apps/ui/src/features/tickets/with components, queries, mutations, schemas. - TanStack Query + typed apiClient.
- shadcn components for the list and create form.
- Every JSX string lifted to i18n (English and German).
- RTL tests for the page.
bun run validateagain.
4. See it work
Section titled “4. See it work”Open http://localhost:7331/tickets. The page renders, the form posts, the list updates.
From the terminal:
curl http://localhost:7330/api/v1/tickets5. Ship it
Section titled “5. Ship it”git checkout -b feat/ticketsgit add -Agit commit -m "feat: tickets resource end-to-end"git push -u origin feat/ticketsgh pr create --fillCI runs the same bun run validate. Local green means CI green. Squash-merge.
Why this works
Section titled “Why this works”Building a feature usually means holding the project’s conventions in your head: which files, which order, which sibling tests lint:meta demands, which lint rules block which patterns. The skill holds all that.
The merge gate is bun run validate, the same script in CI. The OpenAPI client is generated from the running API, so a missing field on one side is a type error on the other. Nothing is hand-wired.
Next steps
Section titled “Next steps”/add-audit-eventto instrument something the agent missed./add-notification-eventto fire a notification when a ticket closes./security-reviewbefore opening the PR.- Spec loop when the next slice deserves an explicit approval gate.
- Add Stripe Checkout to put the feature behind a paid plan.