v0 prompt to set up a Postgres database schema
Schema work in v0 goes through the Neon integration and Drizzle, and this prompt keeps all of it in reviewable files: schema.ts, a seed with deliberately awkward rows, and constraints enforced by Postgres itself. You get a typed data layer with cascades, enums, and indexes chosen for the queries the app will run.
Last updated
Set up a Postgres schema for a project tracker using the Neon integration and Drizzle ORM, with everything in code so the schema is reviewable. Files: db/schema.ts defines the tables, db/index.ts exports a client reading DATABASE_URL from env, and db/seed.ts inserts believable sample rows so the v0 preview has data immediately. Tables: users (id uuid defaulting to gen_random_uuid, email unique not null, created_at timestamptz defaulting to now), projects (id, owner_id referencing users with on delete cascade, name not null, archived boolean default false), and tasks (id, project_id referencing projects with on delete cascade, title not null, status as a Postgres enum of todo, doing, done, position integer for manual ordering, due_date nullable). Indexes: tasks on (project_id, status) because the board view filters on both, plus a partial index on projects where archived is false. Constraints live in the database, not only the app: a check that position is non-negative, and email uniqueness enforced by Postgres rather than a lookup before insert. Generate Drizzle relations so joined queries come back typed, and add db/queries.ts with one example, getProjectWithTasks ordered by position. Seed the awkward rows deliberately: one archived project, one task with a null due_date, and one project with zero tasks, so later UI work hits them early. Never store timestamps as text, and never expose serial ids across an API boundary where a uuid belongs. Acceptance: the seed runs cleanly twice thanks to onConflictDoNothing, and getProjectWithTasks returns typed rows in the preview.
Same task in other tools
Questions about this prompt
How do these files reach an actual database?
Attach the Neon integration in v0 project settings, which exposes DATABASE_URL, then push the schema with Drizzle and run the seed. Until a database is attached, ask v0 to stub the db helper with in-memory rows so screens still render in the preview.
How do I adapt the tables to my own domain?
Keep the patterns and rename the nouns: uuid primary keys, cascading foreign keys, an enum for any status field, and a composite index matching whatever your main list view filters on. Recreate the awkward seed rows for your domain too, they surface UI bugs early.
The seed fails on its second run. What broke?
Either onConflictDoNothing got dropped from an insert or the seed keys off generated ids that differ per run. Make it idempotent by conflicting on stable natural keys, emails for users and names within a project, then rerunning is always safe.