People, and the tokens we email them
You don't need twelve tables. Users. And tokens we mailed (verify, reset). Done.
Stick this under the generator block:
model User {
id String @id @default(cuid())
email String @unique
passwordHash String
name String?
isVerified Boolean @default(false)
createdAt DateTime @default(now())
tokens EmailToken[]
}
model EmailToken {
id String @id @default(cuid())
token String @unique
purpose String // "verify" | "reset"
expiresAt DateTime
usedAt DateTime?
createdAt DateTime @default(now())
userId String
user User @relation(fields: [userId], references: [id], onDelete: Cascade)
}
From the repo root. No --config:
npx prisma db push
npx prisma generate
src/db.ts lives next to src/generated/. One extra ../ and TypeScript looks outside the project. Count the dots with us.
Wrong:
import { PrismaClient } from "../../generated/prisma/client.mjs";
The whole file. One client. Don't open a new connection every request, you'll melt Neon.
import { PrismaClient } from "./generated/prisma/client.js";
const prisma = new PrismaClient();
export default prisma;
Routes: import prisma from "../db.ts". Generated client stays .js. Yeah it's inconsistent. Live with it.
The whole .env has to exist on whichever machine is running Node. Laptop = your file. Live = Actions writes every club secret (JWT, APP_URL, AWS keys, MAIL_FROM, Neon), not only DATABASE_URL.