NuxtHub Database provides a type-safe SQL database powered by Drizzle ORM, supporting PostgreSQL, MySQL, and SQLite with smart detection and automatic migrations at build time.
Install Drizzle ORM, Drizzle Kit, and the appropriate driver(s) for the database you are using:
pnpm add drizzle-orm drizzle-kit postgres @electric-sql/pglite
yarn add drizzle-orm drizzle-kit postgres @electric-sql/pglite
npm install drizzle-orm drizzle-kit postgres @electric-sql/pglite
bun add drizzle-orm drizzle-kit postgres @electric-sql/pglite
deno add npm:drizzle-orm drizzle-kit postgres @electric-sql/pglite
npx nypm add drizzle-orm drizzle-kit postgres @electric-sql/pglite
PGlite (embedded PostgreSQL) if no environment variables are set.postgres-js driver if you set DATABASE_URL, POSTGRES_URL, or POSTGRESQL_URL environment variable.neon-http driver with @neondatabase/serverless for Neon serverless PostgreSQL.pnpm add drizzle-orm drizzle-kit mysql2
yarn add drizzle-orm drizzle-kit mysql2
npm install drizzle-orm drizzle-kit mysql2
bun add drizzle-orm drizzle-kit mysql2
deno add npm:drizzle-orm drizzle-kit mysql2
npx nypm add drizzle-orm drizzle-kit mysql2
mysql2 driver if you set DATABASE_URL or MYSQL_URL environment variable.pnpm add drizzle-orm drizzle-kit @libsql/client
yarn add drizzle-orm drizzle-kit @libsql/client
npm install drizzle-orm drizzle-kit @libsql/client
bun add drizzle-orm drizzle-kit @libsql/client
deno add npm:drizzle-orm drizzle-kit @libsql/client
npx nypm add drizzle-orm drizzle-kit @libsql/client
libsql driver for Turso if you set TURSO_DATABASE_URL and TURSO_AUTH_TOKEN environment variables.libsql locally with file at .data/db/sqlite.db if no environment variables are set.Enable the database in your nuxt.config.ts by setting the db property to your desired SQL dialect:
export default defineNuxtConfig({
hub: {
db: 'postgresql'
}
})
export default defineNuxtConfig({
hub: {
db: 'mysql'
}
})
export default defineNuxtConfig({
hub: {
db: 'sqlite'
}
})
Create your database schema with full TypeScript support using Drizzle ORM:
import { pgTable, text, serial, timestamp } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial().primaryKey(),
name: text().notNull(),
email: text().notNull().unique(),
password: text().notNull(),
avatar: text().notNull(),
createdAt: timestamp().notNull().defaultNow(),
})
import { mysqlTable, text, serial, timestamp } from 'drizzle-orm/mysql-core'
export const users = mysqlTable('users', {
id: serial().primaryKey(),
name: text().notNull(),
email: text().notNull().unique(),
password: text().notNull(),
avatar: text().notNull(),
createdAt: timestamp().notNull().defaultNow(),
})
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core'
export const users = sqliteTable('users', {
id: integer().primaryKey({ autoIncrement: true }),
name: text().notNull(),
email: text().notNull().unique(),
password: text().notNull(),
avatar: text().notNull(),
createdAt: integer({ mode: 'timestamp' }).notNull(),
})
Generate the database migrations from your schema:
npx nuxt db generate
This creates SQL migration files in server/db/migrations/{dialect}/ which are automatically applied during deployment and development.
db instance from hub:db.npx nuxt db generate to generate the database migrations each time you change your database schema and restart the development server.During local development, view and edit your database from Nuxt DevTools using the Drizzle Studio:

export default defineNuxtConfig({
hooks: {
'hub:db:migrations:dirs': (dirs) => {
dirs.push('my-module/db/migrations')
}
}
})
_hub_migrations table which are applied after the database migrations complete.export default defineNuxtConfig({
hooks: {
'hub:db:queries:paths': (queries, dialect) => {
queries.push('my-module/db/queries')
}
}
})
import { createResolver, defineNuxtModule } from '@nuxt/kit'
export default defineNuxtModule({
setup(options, nuxt) {
const { resolve } = createResolver(import.meta.url)
nuxt.hook('hub:db:schema:extend', ({ paths, dialect }) => {
paths.push(resolve(`./db/schema/pages.${dialect}.ts`))
})
}
})
For advanced use cases, you can explicitly configure the database connection:
export default defineNuxtConfig({
hub: {
db: {
dialect: 'postgresql',
driver: 'postgres-js', // Optional: explicitly choose driver
connection: {
connectionString: process.env.DATABASE_URL
}
}
}
})
Database model names often use snake_case conventions, while in TypeScript, it is common to use camelCase for naming models. To address this, you can use the casing option to automatically map camelCase JavaScript keys to snake_case in the database:
export default defineNuxtConfig({
hub: {
db: {
dialect: 'postgresql',
casing: 'snake_case'
}
}
})
This allows you to use camelCase in your TypeScript schema while Drizzle automatically maps them to snake_case in the database:
import { pgTable, text, serial, timestamp } from 'drizzle-orm/pg-core'
export const users = pgTable('users', {
id: serial().primaryKey(),
firstName: text().notNull(), // Maps to first_name in the database
lastName: text().notNull(), // Maps to last_name in the database
createdAt: timestamp().notNull().defaultNow() // Maps to created_at
})
Use the d1-http driver to access a Cloudflare D1 database over HTTP. This is useful when you want to query your D1 database when hosting on other platforms.
export default defineNuxtConfig({
hub: {
db: {
dialect: 'sqlite',
driver: 'd1-http'
}
}
})
This driver requires the following environment variables:
| Variable | Description |
|---|---|
NUXT_HUB_CLOUDFLARE_ACCOUNT_ID | Your Cloudflare account ID |
NUXT_HUB_CLOUDFLARE_API_TOKEN | A Cloudflare API token with D1 permissions |
NUXT_HUB_CLOUDFLARE_DATABASE_ID | The ID of your D1 database |
D1:Edit permissions.Use the neon-http driver to connect to Neon serverless PostgreSQL. This driver uses HTTP protocol optimized for serverless environments.
export default defineNuxtConfig({
hub: {
db: {
dialect: 'postgresql',
driver: 'neon-http'
}
}
})
Install the required dependency:
pnpm add @neondatabase/serverless
This driver requires the following environment variable:
| Variable | Description |
|---|---|
DATABASE_URL | Your Neon database connection string (or POSTGRES_URL / POSTGRESQL_URL) |
postgresql://user:password@hostname/database.If you work with an IDE that supports AI agents, you can add the following text in your Agents.md or .cursor/rules file:
# Agent Instructions
/** ... your agent instructions ... */
## Database
- **Database Dialect**: The database dialect is set in the `nuxt.config.ts` file, within the `hub.db` option or `hub.db.dialect` property.
- **Drizzle Config**: Don't generate the `drizzle.config.ts` file manually, it is generated automatically by NuxtHub.
- **Generate Migrations**: Use `npx nuxt db generate` to automatically generate database migrations from schema changes
- **Never Write Manual Migrations**: Do not manually create SQL migration files in the `server/db/migrations/` directory
- **Workflow**:
1. Create or modify the database schema in `server/db/schema.ts` or any other schema file in the `server/db/schema/` directory
2. Run `npx nuxt db generate` to generate the migration
3. Run `npx nuxt db migrate` to apply the migration to the database, or run `npx nuxt dev` to apply the migration during development
- **Access the database**: Use the `db` instance from `hub:db` to query the database, it is a Drizzle ORM instance.
hubDatabase(), follow this migration guide.The database option has been renamed to db and now accepts a SQL dialect instead of a boolean.
export default defineNuxtConfig({
hub: {
- database: true
+ db: 'sqlite'
}
})
Valid dialects are sqlite, postgresql and mysql.
The database directory has been renamed from server/database/ to server/db/:
- server/database/schema.ts
+ server/db/schema.ts
- server/database/migrations/
+ server/db/migrations/
Make sure to move your schema and migration files to the new location.
The old hubDatabase() function has been removed. You must now use Drizzle ORM.
Before:
const db = hubDatabase()
const result = await db.prepare('SELECT * FROM users').all()
After:
const result = await db.select().from(tables.users)
Your existing SQL migration files continue to work! Just move them to server/db/migrations/.