Lesson 9 of 12 · Build the app
Add Prisma and create the clients table
Describe what a client is once, let Prisma turn it into a real table in your Postgres database, and look at your data in Prisma Studio.
Right now you have a screen that holds clients in memory, and a database that holds nothing. Prisma is the piece in between. You describe what a client looks like in one file, and Prisma creates the table, keeps it in sync when you change your mind, and gives the app a simple way to read and write rows.
Everything running (Lesson 6, “Stopping and coming back”): docker compose ps shows db, dev server in Terminal 1, Claude Code in Terminal 2.
Three words
- Schema. The file where you describe your data. “A client has a name, a company, an email, a status, notes.” Prisma’s schema file is the source of truth for the shape of your database.
- Migration. A recorded change to the database structure. The first one creates the
clientstable. Later ones add columns, and each is saved in your project so the same change can be replayed on the production database. - Prisma Studio. A spreadsheet-like window onto your database. You can see rows, add them, edit them. It is how you check that the app is actually saving things.
A note on versions. Prisma has changed how its setup works more than once, and the exact file names and commands depend on the version Claude Code installs today. That is fine. This lesson tells you what to ask for and what to check. Let Claude Code pick the current, stable setup, and judge the result by the checks at the end, not by whether the file names match a screenshot.
Step 1: Ask for the setup, in plan mode
Shift + Tab into plan mode. Paste:
Add Prisma ORM to this project, using the current stable release and its documented setup for PostgreSQL. Read the connection string from DATABASE_URL in .env.
Create one model called Client with these fields:
- id: a unique generated ID
- name: text, required
- company: text, optional
- email: text, optional
- status: one of LEAD, ACTIVE, PAUSED, CLOSED, default LEAD
- notes: longer text, optional
- createdAt: set automatically when the row is created
- updatedAt: updated automatically on every change
Then create and apply the first migration against the local Docker database, named "init", and generate the Prisma client. Also add a small module that exports a single shared Prisma client instance, following Prisma's recommended pattern for Next.js so we do not open too many connections in development.
Do not change any screen code yet. Tell me the plan first, including which packages you will install and which files you will create.
Read the plan. Things to check:
- It installs Prisma packages and nothing unrelated.
- It creates a schema with a
Clientmodel and the fields above. - It runs a migration named
init. - It says nothing about editing
app/page.tsxor your components.
Approve the plan with manually approve edits. It will run commands and may ask permission for each; approve them. This step can take a couple of minutes.
The model it writes should look roughly like this. Read it once; it is the most readable file in the whole project.
enum Status {
LEAD
ACTIVE
PAUSED
CLOSED
}
model Client {
id String @id @default(cuid())
name String
company String?
email String?
status Status @default(LEAD)
notes String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
The question mark means optional. @default means “if nobody says otherwise, use this.” That is the whole language.
Step 2: Confirm the migration actually happened
Confirm the migration ran against the local database: list the tables in the database and show me the columns of the Client table, in plain English. Also show me the migration files you created.
You want two things: a table for clients with the eight columns above, and a folder in the project containing the migration with init in its name. That folder gets committed. It is how production gets the same table in Lesson 12.
Step 3: Open Prisma Studio and look at your database
How do I open Prisma Studio for this project? Give me the exact command to run in a separate terminal.
It will give you a command, most likely npx prisma studio. Run it in your third terminal window (the one you used for Docker). A browser tab opens, usually at localhost:5555, showing a Client table with zero rows.
Now add one by hand. Click into the Client table, find the button to add a record, fill in a name and a company, leave the rest, and save. You have just put a row in a real Postgres database, running in Docker, on your laptop, through a translator called Prisma. This is how most production apps store their data.
Leave Prisma Studio open. You will use it in Lesson 10 to prove the app is saving things.
Step 4: Check Git before committing
Same drill as Lesson 8:
Show me which files would be included in a commit. Confirm .env is not in the list.
Then:
Commit with the message "Add Prisma and Client model with init migration" and push.
What you should notice
The screen still works exactly as before, on fake data. Refresh localhost:3000 and nothing has changed. The database exists, the table exists, and one row is in it, but the app does not know about any of it yet. That is Lesson 10, and it is one prompt.
Check your work
- A Prisma schema file exists with a
Clientmodel and aStatuslist. - A migration folder with
initin its name exists in the project. - Prisma Studio opens and shows a
Clienttable with the row you added by hand. .envis still not in Git.- Committed and pushed.
If something went wrong
“Can’t reach database server” or “connection refused.” Docker is not running the database. docker compose up -d in the project folder, then ask Claude Code to run the migration again.
“Authentication failed” during the migration. The DATABASE_URL in .env does not match the compose file. Ask: “Compare the credentials in .env with docker-compose.yml and fix whichever is wrong.” If they match and it still fails, docker compose down -v then up -d, then re-run the migration.
Prisma Studio shows no Client table. The migration did not apply. Ask Claude Code: “The Client table does not exist in the database. Show me the migration status and apply any pending migrations.”
Claude Code installed something surprising or changed screen files. “Undo the changes to files under app/ and remove any package not needed for Prisma with PostgreSQL. Show me what changed.” If it gets tangled: Ask Claude Code to “throw away every change since the last commit and take me back to it.” This deletes everything you did since that commit, which is what you want here. That takes you back to the Lesson 8 commit, which is the whole reason you made it.
It picked a Prisma setup that does not match this lesson’s file names. That is expected; see the note near the top. Judge by the checks above.
Next
Lesson 10 swaps the fake data for the real database. The screen stays the same. The data starts surviving refreshes.
Did this lesson not go to plan?
A CTO can help you starting today.
Screenshot the error, note which step you were on, and request a call. Every member starts with a call: bring what you built and where it stopped, and that is where we work out whether we can help and what to do first. No card. No sales deck.
Request a call with your CTO