Populate your development database with realistic test data using the seed script.
The seed script creates a predictable set of test data so you can develop against a realistic database without manually creating users, orgs, and subscriptions every time you reset.
Running the seed
pnpm db:seed
Or reset the entire database and re-seed in one command:
pnpm db:reset # drops DB + pushes schema + runs seed
What gets seeded
The default seed creates:
| Entity | Details |
|---|---|
| 2 users | admin@example.com / user@example.com, both with password password |
| 1 organization | "Acme Inc" with the admin as owner and the user as member |
| 1 subscription | Active Stripe subscription for the admin user (mocked) |
The seed script
import { prisma } from "@/lib/prisma";
import { auth } from "@/lib/auth";
async function main() {
console.log("Seeding database...");
// Create users via Better Auth so passwords are hashed correctly
const adminResult = await auth.api.signUpEmail({
body: {
name: "Admin User",
email: "admin@example.com",
password: "password",
},
});
const userResult = await auth.api.signUpEmail({
body: {
name: "Regular User",
email: "user@example.com",
password: "password",
},
});
const adminId = adminResult.user.id;
const userId = userResult.user.id;
// Create an organization
const org = await prisma.organization.create({
data: {
name: "Acme Inc",
slug: "acme",
members: {
create: [
{ userId: adminId, role: "OWNER" },
{ userId: userId, role: "MEMBER" },
],
},
},
});
// Create a mock subscription for the admin
await prisma.subscription.create({
data: {
userId: adminId,
stripeCustomerId: "cus_seed_admin",
stripeSubscriptionId: "sub_seed_admin",
stripePriceId: "price_seed_pro",
status: "active",
currentPeriodStart: new Date(),
currentPeriodEnd: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000),
},
});
console.log("✓ Seed complete");
console.log(
" admin@example.com / password (owner of Acme Inc, active subscription)",
);
console.log(" user@example.com / password (member of Acme Inc)");
}
main()
.catch((e) => {
console.error(e);
process.exit(1);
})
.finally(() => prisma.$disconnect());
Register the script in package.json so pnpm db:seed finds it:
{
"prisma": {
"seed": "ts-node --compiler-options '{\"module\":\"CommonJS\"}' prisma/seed.ts"
}
}
Always create users through auth.api.signUpEmail in the seed — never insert
passwords directly into the database. The auth API hashes passwords with
Argon2 correctly.
Adding your own seed data
Add whatever your app needs after the base data. Keep it idempotent — use upsert instead of create so the seed can run multiple times without failing:
await prisma.organization.upsert({
where: { slug: "acme" },
update: {},
create: {
name: "Acme Inc",
slug: "acme",
},
});Auth, billing, orgs, and emails — all wired up. Clone and deploy in minutes.
Get launch.now