Skip to main content
SlugShare uses PostgreSQL with Prisma ORM. The schema includes NextAuth.js authentication tables and custom models for points tracking and request management.

Database Provider

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

Models Overview

The database consists of 7 models:
  • NextAuth.js Models: User, Account, Session, VerificationToken
  • Application Models: Points, Request, Notification

User

Stores user account information and serves as the central model connecting all other entities.
model User {
  id            String         @id @default(cuid())
  name          String?
  email         String         @unique
  emailVerified DateTime?
  phone         String?
  image         String?
  createdAt     DateTime       @default(now())
  updatedAt     DateTime       @updatedAt
  accounts      Account[]
  sessions      Session[]
  points        Points?
  requests      Request[]      @relation("Requester")
  donations     Request[]      @relation("Donor")
  notifications Notification[]
}

Fields

id
string
required
Unique identifier (CUID format)
name
string
User’s display name
email
string
required
User’s email address (unique)
emailVerified
DateTime
Timestamp when email was verified
phone
string
User’s phone number
image
string
Profile image URL
createdAt
DateTime
required
Account creation timestamp (auto-generated)
updatedAt
DateTime
required
Last update timestamp (auto-updated)

Relations

  • accounts: OAuth accounts linked to this user
  • sessions: Active sessions for this user
  • points: One-to-one relationship with Points model
  • requests: Requests created by this user (as requester)
  • donations: Requests where this user is the donor
  • notifications: Notifications for this user

Account

Stores OAuth provider account information for NextAuth.js authentication.
model Account {
  id                String  @id @default(cuid())
  userId            String
  type              String
  provider          String
  providerAccountId String
  refresh_token     String? @db.Text
  access_token      String? @db.Text
  expires_at        Int?
  token_type        String?
  scope             String?
  id_token          String? @db.Text
  session_state     String?
  user              User    @relation(fields: [userId], references: [id], onDelete: Cascade)

  @@unique([provider, providerAccountId])
}

Fields

id
string
required
Unique identifier
userId
string
required
Foreign key to User model
provider
string
required
OAuth provider name (e.g., “google”)
providerAccountId
string
required
User’s ID from the OAuth provider

Constraints

  • Cascade Delete: When a user is deleted, all their accounts are deleted
  • Unique: Combination of provider and providerAccountId must be unique

Session

Stores active user sessions for NextAuth.js.
model Session {
  id           String   @id @default(cuid())
  sessionToken String   @unique
  userId       String
  expires      DateTime
  user         User     @relation(fields: [userId], references: [id], onDelete: Cascade)
}

Fields

id
string
required
Unique identifier
sessionToken
string
required
Unique session token (used in cookies)
userId
string
required
Foreign key to User model
expires
DateTime
required
Session expiration timestamp

VerificationToken

Stores email verification tokens for NextAuth.js.
model VerificationToken {
  identifier String
  token      String   @unique
  expires    DateTime

  @@unique([identifier, token])
}

Fields

identifier
string
required
Email address or user identifier
token
string
required
Unique verification token
expires
DateTime
required
Token expiration timestamp

Points

Tracks dining hall points balance for each user. One-to-one relationship with User.
model Points {
  id        String   @id @default(cuid())
  userId    String   @unique
  balance   Int      @default(0)
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  updatedAt DateTime @updatedAt
}

Fields

id
string
required
Unique identifier
userId
string
required
Foreign key to User model (unique)
balance
integer
required
Current points balance (default: 0)
updatedAt
DateTime
required
Last update timestamp (auto-updated)

Important Notes

Points records don’t exist by default. Always use upsert to handle first access:
const points = await prisma.points.upsert({
  where: { userId: user.id },
  update: {},
  create: { userId: user.id, balance: 0 },
});

Request

Tracks point-sharing requests between users.
model Request {
  id             String   @id @default(cuid())
  requesterId    String
  donorId        String?
  location       String
  pointsRequested Int
  status         String   @default("pending")
  message        String?
  requester      User     @relation("Requester", fields: [requesterId], references: [id])
  donor          User?    @relation("Donor", fields: [donorId], references: [id])
  createdAt      DateTime @default(now())
  updatedAt      DateTime @updatedAt
}

Fields

id
string
required
Unique identifier
requesterId
string
required
Foreign key to User model (user requesting points)
donorId
string
Foreign key to User model (user donating points, null until accepted/declined)
location
string
required
UCSC dining hall location (e.g., “Cowell/Stevenson”, “Crown/Merrill”)
pointsRequested
integer
required
Number of points requested
status
string
required
Request status: pending, accepted, or declined (default: pending)
message
string
Optional message from requester
createdAt
DateTime
required
Request creation timestamp (auto-generated)
updatedAt
DateTime
required
Last update timestamp (auto-updated)

Relations

  • requester: User who created the request
  • donor: User who accepted/declined the request (nullable)

Status Values


Notification

Stores notifications for users about request actions.
model Notification {
  id        String   @id @default(cuid())
  userId    String
  type      String
  message   String
  read      Boolean  @default(false)
  user      User     @relation(fields: [userId], references: [id], onDelete: Cascade)
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

Fields

id
string
required
Unique identifier
userId
string
required
Foreign key to User model
type
string
required
Notification type (e.g., request_accepted, request_declined, request_accepted_by_you)
message
string
required
Human-readable notification message
read
boolean
required
Whether notification has been read (default: false)
createdAt
DateTime
required
Notification creation timestamp (auto-generated)
updatedAt
DateTime
required
Last update timestamp (auto-updated)

Notification Types


Relationships Diagram

User
├── accounts (1:N) → Account
├── sessions (1:N) → Session
├── points (1:1) → Points
├── requests (1:N) → Request (as requester)
├── donations (1:N) → Request (as donor)
└── notifications (1:N) → Notification

Request
├── requester (N:1) → User
└── donor (N:1) → User (nullable)

Database Commands

Run Migrations

npx prisma migrate dev

Generate Prisma Client

npx prisma generate

Open Prisma Studio

npx prisma studio

Push Schema (without migration)

npx prisma db push
Always run npx prisma generate after modifying prisma/schema.prisma to update TypeScript types.

Build docs developers (and LLMs) love