Sample App
There is no checked-in sample app: the scaffold commands are the living sample, and the test suite type-checks and runs their output. A scaffolded workspace looks like this:
text
myapp/
├── Taskfile.yml
├── apps/
│ ├── api/ ← Hono backend (contract entry, modules, routes)
│ └── ui/ ← Nuxt SPA (ssr: false)
└── packages/contracts/
├── generated/ ← read-only: openapi.json + schema.d.ts
└── src/index.ts ← hand-owned typed client facadeTo produce one, run either scaffold command:
bash
# Worked example module (quotes)
pnpm exec rivet-ts scaffold --out ./myapp --name myapp
# Or from your own contract
pnpm exec rivet-ts scaffold-mock --entry ./contracts.ts --out ./myappSee Getting Started for the emitted shape and the dev loop, and the 5 minute tutorial for a walkthrough.
What is scaffolded once (hand-owned afterwards)
- the workspace skeleton: root
package.json,pnpm-workspace.yaml,Taskfile.yml, lint/format configs - everything under
apps/api/src/andapps/ui/ packages/contracts/src/index.ts— the client facade
What task generate keeps regenerated (read-only)
apps/api/generated/api.contract.json— the internal IRpackages/contracts/generated/openapi.json— the OpenAPI 3.1 spec from the Rivet binarypackages/contracts/generated/schema.d.ts—openapi-typescripttypes
If a new endpoint is added to the contract, the generated client surface updates on the next task generate. The API then fails loudly at route registration until the selected contract group has exactly one handler per endpoint and no unused handlers.