Skip to content

Commit 741a74f

Browse files
Merge pull request #10 from prisma/prisma-postgres-setup
Add prisma-postgres-setup skill
2 parents 720cdad + 7fa81e0 commit 741a74f

5 files changed

Lines changed: 716 additions & 0 deletions

File tree

prisma-postgres-setup/SKILL.md

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
---
2+
name: prisma-postgres-setup
3+
description: Set up a new Prisma Postgres database and connect it to a local project using the Management API. Use when asked to "set up a database", "create a Prisma Postgres project", "get a connection string", "connect my app to Prisma Postgres", or "provision a database".
4+
license: MIT
5+
metadata:
6+
author: prisma
7+
version: "1.1.0"
8+
---
9+
10+
# Prisma Postgres Setup
11+
12+
Procedural skill that guides you through provisioning a new Prisma Postgres database via the Management API and connecting it to a local project.
13+
14+
## When to Apply
15+
16+
Use this skill when:
17+
18+
- Setting up a new Prisma Postgres database for a project
19+
- Creating a Prisma Postgres project and connecting it locally
20+
- Obtaining a connection string for Prisma Postgres
21+
- Provisioning a database via the Management API (not the Console UI)
22+
23+
Do **not** use this skill when:
24+
25+
- Setting up CI/CD preview databases — use `prisma-postgres-cicd`
26+
- Building multi-tenant database provisioning into an app — use `prisma-postgres-integrator`
27+
- Working with a database that already exists and is connected (schema/migration tasks are standard Prisma CLI)
28+
29+
## Prerequisites
30+
31+
- Node.js 18+
32+
- A Prisma Postgres workspace (create one at https://console.prisma.io if needed)
33+
- A workspace service token (see `references/auth.md`)
34+
35+
## UX Guidelines
36+
37+
When presenting choices to the user (region selection, project deletion, etc.), **use your platform's interactive selection mechanism** (e.g., `ask` tool in Claude Code, structured prompts in other agents). Do not print static tables and ask the user to type a value — present selectable options so the user can pick with minimal effort.
38+
39+
## Workflow
40+
41+
Follow these steps in order. Each step includes the API call to make and how to handle the response.
42+
43+
### Step 1: Authenticate
44+
45+
You need a service token. Try these methods in order:
46+
47+
**1a. Token in the user's prompt**
48+
49+
Check if the user included a service token in their initial message (e.g., "Set up Prisma Postgres with token eyJ..."). If so, use it **exactly as provided** — do not truncate, re-encode, or round-trip it through a file. Store it in a shell variable for subsequent calls.
50+
51+
**1b. Token in the environment**
52+
53+
Check for `PRISMA_SERVICE_TOKEN` in the environment or `.env` file.
54+
55+
**1c. Ask the user to create one**
56+
57+
If no token is available, instruct the user:
58+
59+
> Create a service token in Prisma Console → Workspace Settings → Service Tokens.
60+
> Copy the token and paste it here.
61+
62+
Read `references/auth.md` for details on service token creation.
63+
64+
Once you have a token, store it in a shell variable (`PRISMA_SERVICE_TOKEN`) and use it for all subsequent API calls.
65+
66+
### Step 2: List available regions
67+
68+
Fetch the list of available Prisma Postgres regions to let the user choose where to deploy.
69+
70+
```bash
71+
curl -s -H "Authorization: Bearer $PRISMA_SERVICE_TOKEN" \
72+
https://api.prisma.io/v1/regions/postgres
73+
```
74+
75+
The response contains an array of regions with `id`, `name`, and `status`. Only present regions where `status` is `available`.
76+
77+
**Present the regions as an interactive menu** — let the user pick from options rather than typing a region ID manually.
78+
79+
Read `references/endpoints.md` for the full response shape.
80+
81+
### Step 3: Create a project with a database
82+
83+
```bash
84+
curl -s -X POST https://api.prisma.io/v1/projects \
85+
-H "Authorization: Bearer $PRISMA_SERVICE_TOKEN" \
86+
-H "Content-Type: application/json" \
87+
-d '{
88+
"name": "<project-name>",
89+
"region": "<region-id>",
90+
"createDatabase": true
91+
}'
92+
```
93+
94+
Use the current directory name as the project name by default.
95+
96+
The response is wrapped in `{ "data": { ... } }`. Extract:
97+
98+
- `data.id` — the project ID (prefixed with `proj_`)
99+
- `data.database.id` — the database ID (prefixed with `db_`)
100+
- `data.database.connections[0].endpoints.direct.connectionString` — the direct PostgreSQL connection string
101+
102+
Use the **direct** connection string (`endpoints.direct.connectionString`). Do not use the pooled or accelerate endpoints — those are for legacy Accelerate setups and not needed for new projects.
103+
104+
If the response status is `provisioning`, wait a few seconds and poll `GET /v1/databases/<database-id>` until `status` is `ready`.
105+
106+
**If creation fails due to a database limit**, list the user's existing projects and present them as an interactive menu for deletion. After the user picks one, delete it and retry.
107+
108+
Read `references/endpoints.md` for the full request/response shapes.
109+
110+
### Step 4: Create a named connection (optional)
111+
112+
If you need a dedicated connection (e.g., per-developer or per-environment), create one:
113+
114+
```bash
115+
curl -s -X POST https://api.prisma.io/v1/databases/<database-id>/connections \
116+
-H "Authorization: Bearer $PRISMA_SERVICE_TOKEN" \
117+
-H "Content-Type: application/json" \
118+
-d '{ "name": "dev" }'
119+
```
120+
121+
Extract the direct connection string from `data.endpoints.direct.connectionString`.
122+
123+
### Step 5: Configure the local project
124+
125+
1. Install dependencies:
126+
127+
```bash
128+
npm install prisma @prisma/client @prisma/adapter-pg pg dotenv
129+
```
130+
131+
All five packages are required:
132+
- `prisma` — CLI for migrations, schema push, client generation
133+
- `@prisma/client` — the generated query client
134+
- `@prisma/adapter-pg` — Prisma 7 driver adapter for direct PostgreSQL connections
135+
- `pg` — Node.js PostgreSQL driver (used by the adapter)
136+
- `dotenv` — loads `.env` variables for `prisma.config.ts`
137+
138+
2. Write the direct connection string to `.env`. **Append** to the file if it already exists — do not overwrite existing entries:
139+
140+
```
141+
DATABASE_URL="<direct-connection-string>"
142+
```
143+
144+
3. Verify `.gitignore` includes `.env`. Create `.gitignore` if it does not exist. Warn the user if `.env` is not gitignored.
145+
146+
4. Ensure `package.json` has `"type": "module"` set (Prisma 7 generates ESM output).
147+
148+
5. If `prisma/schema.prisma` does not exist, run `npx prisma init` to scaffold the project. This creates both `prisma/schema.prisma` and `prisma.config.ts`.
149+
150+
6. Ensure `schema.prisma` has the `postgresql` provider and **no** `url` or `directUrl` in the datasource block (Prisma 7 manages connection URLs in `prisma.config.ts`, not in the schema):
151+
152+
```prisma
153+
datasource db {
154+
provider = "postgresql"
155+
}
156+
```
157+
158+
7. Ensure `prisma.config.ts` loads the connection URL from the environment:
159+
160+
```typescript
161+
import path from 'node:path'
162+
import { defineConfig } from 'prisma/config'
163+
import 'dotenv/config'
164+
165+
export default defineConfig({
166+
earlyAccess: true,
167+
schema: path.join(import.meta.dirname, 'prisma', 'schema.prisma'),
168+
datasource: {
169+
url: process.env.DATABASE_URL!,
170+
},
171+
})
172+
```
173+
174+
**Important Prisma 7 notes:**
175+
- Connection URLs go in `prisma.config.ts`, never in `schema.prisma`
176+
- The provider in `schema.prisma` must be `"postgresql"` (not `"prismaPostgres"`)
177+
- `dotenv/config` must be imported in `prisma.config.ts` to load `.env` variables
178+
179+
### Step 6: Define schema and push
180+
181+
If the schema already has models, skip to pushing. Otherwise, **present these options as an interactive menu**:
182+
183+
1. **"I'll define my schema manually"** — Tell the user to edit `prisma/schema.prisma` and come back when ready. Wait for them before proceeding.
184+
2. **"Give me a starter schema"** — Add a Blog starter schema (User, Post, Comment with relations) to `prisma/schema.prisma`. Show the user what was added and ask if they want to adjust it before pushing.
185+
3. **"I'll describe what I need"** — Ask the user to describe their data model in natural language (e.g., "I'm building a task manager with projects, tasks, and team members"). Generate a schema from the description, show it, and ask for confirmation before pushing.
186+
187+
Once the schema has models and the user is ready, create a migration and generate the client:
188+
189+
```bash
190+
npx prisma migrate dev --name init
191+
```
192+
193+
This creates migration files in `prisma/migrations/` **and** generates the client in one step. Migration history is essential for CI/CD workflows (`prisma migrate deploy`) and production deployments.
194+
195+
Only use `npx prisma db push` if the user explicitly asks for prototyping-only mode (no migration history). In that case, follow it with `npx prisma generate`.
196+
197+
### Step 7: Verify the connection
198+
199+
After generating the client, create and run a quick verification script to confirm everything works end-to-end. This is **critical** — do not skip this step.
200+
201+
Create a file named `test-connection.ts`:
202+
203+
```typescript
204+
import 'dotenv/config'
205+
import pg from 'pg'
206+
import { PrismaPg } from '@prisma/adapter-pg'
207+
import { PrismaClient } from './generated/prisma/client.js'
208+
209+
const pool = new pg.Pool({ connectionString: process.env.DATABASE_URL })
210+
const adapter = new PrismaPg(pool)
211+
const prisma = new PrismaClient({ adapter })
212+
213+
const result = await prisma.$queryRawUnsafe('SELECT 1 as connected')
214+
console.log('Connected to Prisma Postgres:', result)
215+
216+
await prisma.$disconnect()
217+
await pool.end()
218+
```
219+
220+
Run it:
221+
222+
```bash
223+
npx tsx test-connection.ts
224+
```
225+
226+
**Prisma 7 client instantiation rules:**
227+
- Import from `./generated/prisma/client.js` (not `./generated/prisma`)
228+
- Create a `pg.Pool` with the `DATABASE_URL` connection string
229+
- Wrap it in a `PrismaPg` adapter
230+
- Pass `{ adapter }` to the `PrismaClient` constructor
231+
- Do **not** use `datasourceUrl` — that option does not exist in Prisma 7
232+
- Do **not** use `new PrismaClient()` with no arguments — it will throw
233+
234+
After verification succeeds, delete `test-connection.ts`.
235+
236+
Then share links for the user to explore their database:
237+
238+
- **Prisma Studio (CLI):** `npx prisma studio` — opens a visual data browser locally
239+
- **Console:** `https://console.prisma.io/<workspaceId>/<projectId>/<databaseId>/dashboard` — strip the prefixes (`wksp_`, `proj_`, `db_`) from the IDs returned in Step 3 to build this URL
240+
241+
Read `references/prisma7-client.md` for the full client instantiation reference.
242+
243+
## Error Handling
244+
245+
Read `references/api-basics.md` for the full error reference. Key self-correction patterns:
246+
247+
| HTTP Status | Error Code | Action |
248+
|---|---|---|
249+
| 401 | `authentication-failed` | Service token is invalid or expired. Ask the user to create a new one in Console → Workspace Settings → Service Tokens. |
250+
| 404 | `resource-not-found` | Check that the resource ID includes the correct prefix (`proj_`, `db_`, `con_`). |
251+
| 422 | `validation-error` | Check request body against the endpoint schema. Common: missing `name`, invalid `region`. |
252+
| 429 | `rate-limit-exceeded` | Back off and retry after a few seconds. |
253+
254+
## Reference Files
255+
256+
Detailed API and usage information is in:
257+
258+
```
259+
references/auth.md — Service token creation and usage
260+
references/api-basics.md — Base URL, envelope, IDs, errors, pagination
261+
references/endpoints.md — Endpoint details for projects, databases, connections, regions
262+
references/prisma7-client.md — Prisma 7 client instantiation and usage patterns
263+
```
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# api-basics
2+
3+
Core conventions for the Prisma Management API. All three `prisma-postgres-*` skills share these patterns.
4+
5+
## Base URL
6+
7+
```
8+
https://api.prisma.io/v1
9+
```
10+
11+
API documentation: https://api.prisma.io/v1/doc
12+
13+
## Response Envelope
14+
15+
### Single resource
16+
17+
```json
18+
{
19+
"data": {
20+
"id": "proj_clx7abc123def456",
21+
"type": "project",
22+
"name": "My Project",
23+
"createdAt": "2025-06-15T10:30:00.000Z"
24+
}
25+
}
26+
```
27+
28+
### Collection
29+
30+
```json
31+
{
32+
"data": [
33+
{ "id": "proj_aaa", "type": "project", "name": "Alpha" },
34+
{ "id": "proj_bbb", "type": "project", "name": "Beta" }
35+
],
36+
"pagination": {
37+
"hasMore": true,
38+
"nextCursor": "clx7cursor123"
39+
}
40+
}
41+
```
42+
43+
## Resource ID Prefixes
44+
45+
Every resource ID carries a type prefix:
46+
47+
| Prefix | Resource |
48+
|---|---|
49+
| `proj_` | Project |
50+
| `db_` | Database |
51+
| `con_` | Connection |
52+
| `wksp_` | Workspace |
53+
54+
Always include the prefix when sending IDs in API requests.
55+
56+
## Pagination
57+
58+
Collection endpoints use cursor-based pagination:
59+
60+
```
61+
GET /v1/projects?limit=10
62+
GET /v1/projects?cursor=clx7abc123&limit=10
63+
```
64+
65+
| Parameter | Type | Default | Description |
66+
|---|---|---|---|
67+
| `cursor` | string || Opaque cursor from `nextCursor` |
68+
| `limit` | number | 100 | Maximum items per page |
69+
70+
Continue fetching while `pagination.hasMore` is `true`, using `pagination.nextCursor` as the `cursor` parameter.
71+
72+
## Error Responses
73+
74+
All errors follow this shape:
75+
76+
```json
77+
{
78+
"error": {
79+
"code": "resource-not-found",
80+
"message": "database with id db_abc not found"
81+
}
82+
}
83+
```
84+
85+
### Error codes by HTTP status
86+
87+
| HTTP Status | Error Code | Meaning |
88+
|---|---|---|
89+
| 400 | `client-error` | Malformed request |
90+
| 401 | `authentication-failed` | Missing or invalid token |
91+
| 403 | `permission-denied` | Token lacks required access |
92+
| 404 | `resource-not-found` | Resource does not exist or is not accessible |
93+
| 422 | `validation-error` | Request body failed validation |
94+
| 429 | `rate-limit-exceeded` | Too many requests |
95+
| 500 | `internal-server-error` | Server error — retry after a delay |
96+
97+
### Self-correction patterns
98+
99+
- **401**: Token is invalid or expired. Create a new service token in Console → Workspace Settings → Service Tokens.
100+
- **404**: Verify the resource ID includes the correct prefix (`proj_`, `db_`, `con_`). Use `GET /v1/projects` or `GET /v1/databases` to list available resources.
101+
- **422**: Check the request body against the endpoint schema. Common issues: missing required fields, invalid region ID, empty `name`.
102+
- **429**: Wait 2–5 seconds and retry. If repeated, increase the backoff interval.

0 commit comments

Comments
 (0)