This template includes a fully configured database setup with Drizzle ORM, PostgreSQL, and automated migrations.
The database system in this template uses Drizzle ORM for type-safe database operations with PostgreSQL. The setup includes migrations, schema validation, and a Docker-based development environment for easy local development.
This approach provides a robust foundation for data management with minimal configuration, while maintaining type safety throughout your application.
Define your database schema in TypeScript with full type safety and autocompletion.
Automatically generate and apply database migrations based on schema changes.
Type-safe SQL query builder with intuitive syntax and full TypeScript support.
Robust, feature-rich PostgreSQL database with JSON, full-text search, and more.
Pre-configured Docker setup for local development with persistence.
Define and query relations between tables with ease and type safety.
The database layer is implemented in the src/database
directory and consists of these main components:
Here's an example of how the database schema is defined:
// Example schema definition with Drizzle
import { pgTable, serial, text, timestamp, boolean } from "drizzle-orm/pg-core";
import { relations } from "drizzle-orm";
// Define the users table
export const users = pgTable("users", {
id: serial("id").primaryKey(),
email: text("email").notNull().unique(),
name: text("name"),
password: text("password"),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
emailVerified: boolean("email_verified").default(false),
});
// Define the posts table
export const posts = pgTable("posts", {
id: serial("id").primaryKey(),
title: text("title").notNull(),
content: text("content"),
authorId: serial("author_id").references(() => users.id),
createdAt: timestamp("created_at").defaultNow().notNull(),
updatedAt: timestamp("updated_at").defaultNow().notNull(),
});
// Define relations
export const userRelations = relations(users, ({ many }) => ({
posts: many(posts),
}));
export const postRelations = relations(posts, ({ one }) => ({
author: one(users, {
fields: [posts.authorId],
references: [users.id],
}),
}));
To query the database in your server components or API routes:
// Example: Querying the database in a server component
import { db } from "@/database";
import { users } from "@/database/schema";
import { eq } from "drizzle-orm";
// In a server component or API route
export async function getUser(userId: number) {
// Query a single user by ID
const user = await db.query.users.findFirst({
where: eq(users.id, userId),
with: {
posts: true, // Include relations
},
});
return user;
}
// Example: Creating a new record
export async function createUser(data: { email: string; name: string; password: string }) {
const result = await db.insert(users).values(data).returning();
return result[0];
}
The template includes scripts to help manage database migrations:
# Generate migrations based on schema changes
npm run db:generate
# Apply pending migrations
npm run db:migrate
# Start the development database with Docker
docker-compose up -d
Database settings can be configured in the .env
file and in drizzle.config.ts
. The following environment variables are used:
DATABASE_URL
: Connection string for your PostgreSQL databaseDATABASE_HOST
: Database host (default: localhost)DATABASE_PORT
: Database port (default: 5432)DATABASE_NAME
: Database nameDATABASE_USER
: Database userDATABASE_PASSWORD
: Database password