Initial commit
This commit is contained in:
312
skills/neon-drizzle/guides/new-project.md
Normal file
312
skills/neon-drizzle/guides/new-project.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# New Project Setup
|
||||
|
||||
> **Complete Walkthrough**: This is a self-contained, step-by-step guide with its own numbered phases (Phase 1-6).
|
||||
> Follow each phase in order for a full Drizzle + Neon setup from scratch.
|
||||
|
||||
Complete guide for setting up Drizzle ORM with Neon from scratch.
|
||||
|
||||
### Important:
|
||||
- Remember to run the neon-plugin:add-neon-docs skill with the parameter SKILL_NAME="neon-drizzle" after completing the guide.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
- [New Project Setup](#new-project-setup)
|
||||
- [Important:](#important)
|
||||
- [Table of Contents](#table-of-contents)
|
||||
- [Workflow Checklist](#workflow-checklist)
|
||||
- [Phase 1: Context Detection](#phase-1-context-detection)
|
||||
- [Phase 2: Installation](#phase-2-installation)
|
||||
- [Phase 3: Configuration](#phase-3-configuration)
|
||||
- [3.1. Neon Database Provisioning \& Environment File](#31-neon-database-provisioning--environment-file)
|
||||
- [3.2. Drizzle Config](#32-drizzle-config)
|
||||
- [3.3. Database Connection](#33-database-connection)
|
||||
- [Phase 4: Schema Generation](#phase-4-schema-generation)
|
||||
- [4.1. Common Patterns](#41-common-patterns)
|
||||
- [Phase 5: Migrations](#phase-5-migrations)
|
||||
- [5.1. Generate Migration](#51-generate-migration)
|
||||
- [5.2. Apply Migration](#52-apply-migration)
|
||||
- [5.3. Add Migration Scripts](#53-add-migration-scripts)
|
||||
- [5.4. If Migration Fails](#54-if-migration-fails)
|
||||
- [Phase 6: Add Best Practices References](#phase-6-add-best-practices-references)
|
||||
- [✅ Setup Complete!](#-setup-complete)
|
||||
|
||||
---
|
||||
|
||||
## Workflow Checklist
|
||||
|
||||
When following this guide, I will track these high-level tasks:
|
||||
|
||||
- [ ] Detect project context (package manager, framework, existing setup)
|
||||
- [ ] Install Drizzle dependencies based on deployment target
|
||||
- [ ] Provision Neon database (list projects, create if needed, get connection string)
|
||||
- [ ] Write connection string to environment file and verify
|
||||
- [ ] Create Drizzle configuration files (drizzle.config.ts, db connection)
|
||||
- [ ] Generate schema based on app type
|
||||
- [ ] Run and verify migrations
|
||||
- [ ] Add Neon Drizzle best practices to project docs
|
||||
|
||||
---
|
||||
|
||||
## Phase 1: Context Detection
|
||||
|
||||
Auto-detect project context:
|
||||
|
||||
**Check Package Manager:**
|
||||
```bash
|
||||
ls package-lock.json # → npm
|
||||
ls bun.lockb # → bun
|
||||
ls pnpm-lock.yaml # → pnpm
|
||||
ls yarn.lock # → yarn
|
||||
```
|
||||
|
||||
**Check Framework:**
|
||||
```bash
|
||||
grep '"next"' package.json # → Next.js
|
||||
grep '"express"' package.json # → Express
|
||||
grep '"vite"' package.json # → Vite
|
||||
```
|
||||
|
||||
**Check Existing Setup:**
|
||||
```bash
|
||||
ls drizzle.config.ts # Already configured?
|
||||
ls src/db/schema.ts # Schema exists?
|
||||
```
|
||||
|
||||
**Check Environment Files:**
|
||||
```bash
|
||||
ls .env .env.local .env.production
|
||||
```
|
||||
|
||||
## Phase 2: Installation
|
||||
|
||||
Based on detection, install dependencies:
|
||||
|
||||
**For Vercel/Edge Environments (Next.js, Vite on Vercel):**
|
||||
```bash
|
||||
[package-manager] add drizzle-orm @neondatabase/serverless
|
||||
[package-manager] add -D drizzle-kit dotenv @vercel/node
|
||||
```
|
||||
|
||||
**For Node.js Servers (Express, Fastify, standard Node):**
|
||||
```bash
|
||||
[package-manager] add drizzle-orm @neondatabase/serverless ws
|
||||
[package-manager] add -D drizzle-kit dotenv @types/ws
|
||||
```
|
||||
|
||||
## Phase 3: Configuration
|
||||
|
||||
Create configuration files in dependency order:
|
||||
|
||||
### 3.1. Neon Database Provisioning & Environment File
|
||||
|
||||
**Outcome**: A working `.env` or `.env.local` file with a real Neon connection string that the application can use immediately.
|
||||
|
||||
Use MCP tools to list or create a Neon project and get its connection string. Write the actual credentials to the environment file (`.env.local` for Next.js, `.env` for other projects). Add the file to `.gitignore`.
|
||||
|
||||
**Environment file format:**
|
||||
```bash
|
||||
DATABASE_URL=postgresql://user:password@host/database?sslmode=require
|
||||
```
|
||||
|
||||
### 3.2. Drizzle Config
|
||||
|
||||
Create `drizzle.config.ts` with explicit environment loading:
|
||||
|
||||
**CRITICAL:** The `config({ path: '...' })` line must match the environment file from Step 3.1.
|
||||
|
||||
**For Next.js (using .env.local):**
|
||||
```typescript
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
import { config } from 'dotenv';
|
||||
|
||||
// Load .env.local explicitly
|
||||
config({ path: '.env.local' });
|
||||
|
||||
export default defineConfig({
|
||||
schema: './src/db/schema.ts',
|
||||
out: './src/db/migrations',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**For other projects (using .env):**
|
||||
```typescript
|
||||
import { defineConfig } from 'drizzle-kit';
|
||||
import { config } from 'dotenv';
|
||||
|
||||
// Load .env explicitly
|
||||
config({ path: '.env' });
|
||||
|
||||
export default defineConfig({
|
||||
schema: './src/db/schema.ts',
|
||||
out: './src/db/migrations',
|
||||
dialect: 'postgresql',
|
||||
dbCredentials: {
|
||||
url: process.env.DATABASE_URL!,
|
||||
},
|
||||
});
|
||||
```
|
||||
|
||||
**Why this matters:**
|
||||
- Without explicit `config({ path: '...' })`, drizzle-kit may not load environment variables
|
||||
- This prevents "url: undefined" errors during migrations
|
||||
- The path must match your environment file name from Phase 3.1
|
||||
|
||||
### 3.3. Database Connection
|
||||
|
||||
Create `src/db/index.ts` with appropriate adapter (see `references/adapters.md` for decision guide):
|
||||
|
||||
**For Vercel/Edge:**
|
||||
```typescript
|
||||
import { drizzle } from 'drizzle-orm/neon-http';
|
||||
import { neon } from '@neondatabase/serverless';
|
||||
|
||||
const sql = neon(process.env.DATABASE_URL!);
|
||||
export const db = drizzle(sql);
|
||||
```
|
||||
|
||||
**For Node.js:**
|
||||
```typescript
|
||||
import { drizzle } from 'drizzle-orm/neon-serverless';
|
||||
import { Pool, neonConfig } from '@neondatabase/serverless';
|
||||
import ws from 'ws';
|
||||
|
||||
neonConfig.webSocketConstructor = ws;
|
||||
const pool = new Pool({ connectionString: process.env.DATABASE_URL! });
|
||||
export const db = drizzle(pool);
|
||||
```
|
||||
|
||||
See `templates/db-http.ts` and `templates/db-websocket.ts` for complete examples.
|
||||
|
||||
## Phase 4: Schema Generation
|
||||
|
||||
Based on app type, create appropriate schema:
|
||||
|
||||
### 4.1. Common Patterns
|
||||
|
||||
**Todo App:**
|
||||
```typescript
|
||||
import { pgTable, serial, text, boolean, timestamp, varchar } from 'drizzle-orm/pg-core';
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: serial('id').primaryKey(),
|
||||
email: varchar('email', { length: 255 }).notNull().unique(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
});
|
||||
|
||||
export const todos = pgTable('todos', {
|
||||
id: serial('id').primaryKey(),
|
||||
userId: serial('user_id').notNull().references(() => users.id),
|
||||
title: text('title').notNull(),
|
||||
completed: boolean('completed').default(false),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
});
|
||||
```
|
||||
|
||||
**Blog App:**
|
||||
```typescript
|
||||
import { pgTable, serial, text, timestamp, varchar, index } from 'drizzle-orm/pg-core';
|
||||
import { relations } from 'drizzle-orm';
|
||||
|
||||
export const users = pgTable('users', {
|
||||
id: serial('id').primaryKey(),
|
||||
email: varchar('email', { length: 255 }).notNull().unique(),
|
||||
name: varchar('name', { length: 255 }).notNull(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
});
|
||||
|
||||
export const posts = pgTable('posts', {
|
||||
id: serial('id').primaryKey(),
|
||||
userId: serial('user_id').notNull().references(() => users.id),
|
||||
title: text('title').notNull(),
|
||||
content: text('content').notNull(),
|
||||
createdAt: timestamp('created_at').defaultNow(),
|
||||
}, (table) => ({
|
||||
userIdIdx: index('posts_user_id_idx').on(table.userId),
|
||||
}));
|
||||
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
posts: many(posts),
|
||||
}));
|
||||
|
||||
export const postsRelations = relations(posts, ({ one }) => ({
|
||||
author: one(users, {
|
||||
fields: [posts.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
}));
|
||||
```
|
||||
|
||||
See `templates/schema-example.ts` for more complex examples.
|
||||
|
||||
## Phase 5: Migrations
|
||||
|
||||
Run migrations with proper error handling:
|
||||
|
||||
### 5.1. Generate Migration
|
||||
|
||||
```bash
|
||||
[package-manager] drizzle-kit generate
|
||||
```
|
||||
|
||||
This creates SQL files in `src/db/migrations/`.
|
||||
|
||||
### 5.2. Apply Migration
|
||||
|
||||
**Recommended approach (explicit env loading):**
|
||||
```bash
|
||||
export DATABASE_URL="$(grep DATABASE_URL .env.local | cut -d '=' -f2)" && \
|
||||
[package-manager] drizzle-kit migrate
|
||||
```
|
||||
|
||||
**Why this works:** Ensures `DATABASE_URL` is available, preventing "url: undefined" errors.
|
||||
|
||||
### 5.3. Add Migration Scripts
|
||||
|
||||
Add these convenience scripts to your `package.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"db:generate": "drizzle-kit generate",
|
||||
"db:migrate": "drizzle-kit migrate",
|
||||
"db:push": "drizzle-kit push",
|
||||
"db:studio": "drizzle-kit studio"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
npm run db:generate # Generate migrations from schema changes
|
||||
npm run db:migrate # Apply pending migrations
|
||||
npm run db:push # Push schema directly (dev only)
|
||||
npm run db:studio # Open Drizzle Studio
|
||||
```
|
||||
|
||||
**Note:** Replace `npm run` with your package manager's equivalent (`pnpm`, `yarn`, `bun`).
|
||||
|
||||
### 5.4. If Migration Fails
|
||||
|
||||
See `guides/troubleshooting.md` for common issues and fixes.
|
||||
|
||||
Also reference `references/migrations.md` for deep dive on migration patterns.
|
||||
|
||||
## Phase 6: Add Best Practices References
|
||||
|
||||
Before executing the add-neon-docs skill, provide a summary of everything that has been done:
|
||||
|
||||
"✅ ... Drizzle integration is complete! Now adding documentation references..."
|
||||
|
||||
Then execute the neon-plugin:add-neon-docs skill with the parameter SKILL_NAME="neon-drizzle"
|
||||
|
||||
This will add reference links to Neon + Drizzle best practices documentation in your project's AI documentation file, helping AI assistants provide better guidance in future conversations.
|
||||
|
||||
## ✅ Setup Complete!
|
||||
|
||||
Your Drizzle + Neon integration is ready to use.
|
||||
|
||||
Reference in New Issue
Block a user