Keep capabilities server-side
A database URL is a bearer secret. Browser code should call your app API, not TmpState directly.
These examples show how to use TmpState behind real app boundaries: server routes, workflow collections, audit trails, webhook capture, QA repros, and expiry checks.
A database URL is a bearer secret. Browser code should call your app API, not TmpState directly.
Use collections that match real workflows: leads, tasks, votes, runs, artifacts, events.
When a prototype becomes a product, GET $DB/__export and migrate intentionally.
Copy the shape, not just the code. Each recipe includes the reason behind the pattern so you can decide when to keep it, extend it, or replace it.
Your browser UI needs persistence, but the TmpState database URL must stay server-side.
This is the default production-shaped pattern. The client talks to your app API; only the server calls TmpState.
// app/api/leads/route.ts
const DB = process.env.TMPSTATE_DB!
export async function POST(request: Request) {
const lead = await request.json()
const response = await fetch(`${DB}/leads`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
name: String(lead.name ?? ""),
email: String(lead.email ?? ""),
source: "landing-page",
}),
})
return Response.json(await response.json(), { status: response.status })
}
export async function GET() {
const response = await fetch(`${DB}/leads?limit=25`, {
cache: "no-store",
})
return Response.json(await response.json(), { status: response.status })
}A team needs shared todos, demo blockers, ownership, and judging-day polish without spending time on auth.
A small task board is valuable during the event and usually disposable afterward.
# Create tasks
curl -X POST "$TMPSTATE_DB/tasks" \
-H "Content-Type: application/json" \
-d '{"title":"Connect checkout demo","owner":"Mina","status":"doing"}'
curl -X POST "$TMPSTATE_DB/tasks" \
-H "Content-Type: application/json" \
-d '{"title":"Write judge script","owner":"Ravi","status":"todo"}'
# List tasks
curl "$TMPSTATE_DB/tasks?limit=50"
# Update a task
curl -X PATCH "$TMPSTATE_DB/tasks/doc_abc123" \
-H "Content-Type: application/json" \
-d '{"status":"done"}'A coding agent needs to remember choices, generated artifacts, checks, and follow-up tasks across tool calls.
Separate append-only collections make the run inspectable and reduce the risk of overwriting useful history.
# Decision log
curl -X POST "$TMPSTATE_DB/decisions" \
-H "Content-Type: application/json" \
-d '{"topic":"storage","decision":"use TmpState behind app API","reason":"prototype expires by default"}'
# Verification record
curl -X POST "$TMPSTATE_DB/checks" \
-H "Content-Type: application/json" \
-d '{"name":"lead form","command":"pnpm test","status":"passed"}'
# Artifact index
curl -X POST "$TMPSTATE_DB/artifacts" \
-H "Content-Type: application/json" \
-d '{"path":"app/api/leads/route.ts","kind":"source","summary":"server-only TmpState proxy"}'You need to inspect webhook payloads from Stripe, GitHub, Linear, or a form tool before deciding the real schema.
Raw payload capture is useful for discovery, but it should not become permanent storage by accident.
// app/api/webhook-inbox/route.ts
const DB = process.env.TMPSTATE_DB!
export async function POST(request: Request) {
const payload = await request.json()
await fetch(`${DB}/webhook_events`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
received_at: new Date().toISOString(),
event_type: payload.type ?? payload.action ?? "unknown",
payload,
}),
})
return Response.json({ ok: true })
}A bug report needs structured state: environment, steps, logs, expected result, actual result, and current triage status.
One database per repro gives engineering a private, inspectable bundle that expires if the bug stops mattering.
curl -X POST "$TMPSTATE_DB/reports" \
-H "Content-Type: application/json" \
-d '{
"title":"Checkout total changes after refresh",
"browser":"Chrome 126",
"severity":"high",
"status":"new"
}'
curl -X POST "$TMPSTATE_DB/steps" \
-H "Content-Type: application/json" \
-d '{"order":1,"text":"Add monthly Pro plan to cart"}'
curl -X POST "$TMPSTATE_DB/logs" \
-H "Content-Type: application/json" \
-d '{"level":"error","message":"price mismatch","source":"client"}'The app is still useful after day one, and you need a simple way to decide whether to extend or migrate.
Checking __meta makes lifecycle visible without adding end-user expiry banners to the product UI.
curl "$TMPSTATE_DB/__meta"
# Example policy for an agent or maintenance script:
# - if expires_in < 6 hours and demo is scheduled, ask whether to extend
# - if tier is free and real users entered data, export before expiry
# - if prototype becomes daily-use software, propose Pro or migration