BoilerPrompt
v0

v0 prompt to build a REST API

This spec makes v0 generate a complete CRUD backend as Next.js route handlers: paginated list, create, read, update, delete, and a health check. You end up with one zod schema driving both validators, a consistent JSON error contract, and a lib/db.ts seam so swapping database clients later means touching one file.

Last updated

Prompt
Build a REST API for {{resource}} records as Next.js route handlers under app/api, backed by {{database}}. No pages or UI, route handlers only.

Endpoints:
- GET /api/{{resource}}: paginated list. Accept page and limit query params (default 20, max 100) plus sort=createdAt:desc. Respond with { data, page, total }.
- POST /api/{{resource}}: create from a JSON body. Return 201 and the created record.
- GET /api/{{resource}}/[id]: one record, or 404 with { error: "not_found" }.
- PATCH /api/{{resource}}/[id]: partial update. Unknown fields are a 400, not silently dropped.
- DELETE /api/{{resource}}/[id]: 204 on success, 404 if the id does not exist.
- GET /api/health: { ok: true } for smoke checks.

Data model: id (uuid), name (string, 1 to 120 chars), status ("active" | "archived"), createdAt, updatedAt. Define one zod schema and derive the POST and PATCH validators from it so the rules never drift apart.

Error contract: every failure is JSON { error, message } with the correct status code. Validation failures return 400 with zod's field-level issues. A malformed JSON body must also be a 400, never an unhandled 500.

Put all {{database}} access in lib/db.ts behind list, get, create, update, and remove functions; handlers never import the client directly. Finish with a README block showing one sample curl per endpoint so I can verify each route from a terminal.

Customize it

Runs in your browser. Nothing you type here is sent anywhere.

Your customized prompt
Build a REST API for users records as Next.js route handlers under app/api, backed by PostgreSQL. No pages or UI, route handlers only.

Endpoints:
- GET /api/users: paginated list. Accept page and limit query params (default 20, max 100) plus sort=createdAt:desc. Respond with { data, page, total }.
- POST /api/users: create from a JSON body. Return 201 and the created record.
- GET /api/users/[id]: one record, or 404 with { error: "not_found" }.
- PATCH /api/users/[id]: partial update. Unknown fields are a 400, not silently dropped.
- DELETE /api/users/[id]: 204 on success, 404 if the id does not exist.
- GET /api/health: { ok: true } for smoke checks.

Data model: id (uuid), name (string, 1 to 120 chars), status ("active" | "archived"), createdAt, updatedAt. Define one zod schema and derive the POST and PATCH validators from it so the rules never drift apart.

Error contract: every failure is JSON { error, message } with the correct status code. Validation failures return 400 with zod's field-level issues. A malformed JSON body must also be a 400, never an unhandled 500.

Put all PostgreSQL access in lib/db.ts behind list, get, create, update, and remove functions; handlers never import the client directly. Finish with a README block showing one sample curl per endpoint so I can verify each route from a terminal.

Same task in other tools

Questions about this prompt

Will v0 build an API without any UI?

Yes, but it defaults to interfaces, which is why the prompt says route handlers only up front. If a demo page appears anyway, reply with "remove the page, keep app/api only" and it will drop the UI without disturbing the handlers.

Can the v0 preview actually hit my database?

Only if credentials exist. Add your connection string as an environment variable in the project settings, or tell v0 to back lib/db.ts with an in-memory array while you iterate and swap in the real client after export.

The handlers return HTML error pages for bad input. What went wrong?

The body parse threw before validation ran. Reply asking v0 to wrap each handler in a shared try/catch that returns the JSON error contract, and to treat a failed request.json() call as a 400 rather than letting it bubble into a 500.

Related prompts