This guide is for setting up a new app with Nuxt 3 and adding a Postgres Database with Drizzle ORM + Kit for migrations to it. Highly opinionated – that's just the setup I find working for multiple projects. Let me know if you miss something!
TLDR: GitHub Example Repo
Let's start by installing
Nuxt 3
Drizzle ORM + Drizzle Kit
Postgres.js
(notpg
)
Install Nuxt
pnpm dlx nuxi@latest init my-nuxt-drizzle-project
Install Packages
pnpm add drizzle-orm postgres @paralleldrive/cuid2
pnpm add -D drizzle-kit
Create .env file
Create a .env
file in project root with the following content. The url may vary.
DATABASE_URL="postgres://username:password@ip:port/postgres"
Add Drizzle ORM config
Create the directory /server/db
and add the following files:
/server/db/schema.ts
, this is just an example schema to get started. You can modify this to your needs before continuing.
import { pgTable, timestamp, text } from 'drizzle-orm/pg-core'
import { createId } from '@paralleldrive/cuid2'
export const post = pgTable('post', {
id: text().primaryKey().$defaultFn(createId),
title: text().notNull(),
slug: text().notNull(),
content: text(),
createdAt: timestamp({ withTimezone: true }).defaultNow().notNull(),
updatedAt: timestamp({ withTimezone: true }).defaultNow().notNull(),
})
Add Drizzle Server Utility
Create a new file for the Drizzle DB utility which is used to query your database inside API endpoints. Create the file /server/utils/db.ts
import { drizzle } from 'drizzle-orm/postgres-js'
import postgres from 'postgres'
import * as schema from '../db/schema'
const queryClient = postgres(process.env.DATABASE_URL || '', {
prepare: false,
})
export const db = drizzle(queryClient, { schema })
Add Drizzle-Kit config
Add the drizzle.config.ts
file to your project root.
import { defineConfig } from 'drizzle-kit'
export default defineConfig({
dialect: 'postgresql',
schema: './server/db/schema.ts',
out: './server/db/migrations',
dbCredentials: {
url: process.env.DATABASE_URL || '',
},
})
Add script to package.json
Add two new scripts.
db:generate
is to generate migration files for youdb:migrate
is to migrate newly generated migration files to your database (optional)
{
"name": "nuxt-app",
"private": true,
"type": "module",
"scripts": {
// ...
"db:generate": "drizzle-kit generate",
"db:migrate": "drizzle-kit migrate"
},
}
If you want another strategy, check out Drizzle Migration Docs. For example, if you want to apply a migration as soon as your Dev Server/App starts:
/server/plugins/migrations.ts
import { migrate } from 'drizzle-orm/postgres-js/migrator'
import { db } from '../utils/db'
export default defineNitroPlugin(async () => {
try {
await migrate(db, {
migrationsFolder: './db/migrations',
})
console.info('[server/plugins/migrations.ts] Migration done ✨')
} catch (error) {
console.error('[server/plugins/migrations.ts] Migration failed')
console.error(error)
}
})
Migrate first time
Now hit pnpm db:generate
, you should see a migration file alongside with some others being generated in your /server/db/migrations
folder.
Hit pnpm db:migrate
(or use your migration strategy) to apply your new schema to the database.
Congrats! 🚀 You now have a very simple Drizzle ORM + Kit setup with Nuxt 3. If you now want to install Better-Auth as a next step, check out my blog post about that.