generator client { provider = "prisma-client-js" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model User { id String @id @default(uuid()) pubkey String @unique role String @default("USER") // USER, MODERATOR, ADMIN displayName String? username String? @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Organizer { id String @id @default(uuid()) name String slug String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt meetups Meetup[] } model Meetup { id String @id @default(uuid()) title String description String date String time String location String link String? imageId String? status String @default("DRAFT") // DRAFT, PUBLISHED, CANCELLED (Upcoming/Past derived from date) featured Boolean @default(false) visibility String @default("PUBLIC") // PUBLIC, HIDDEN organizerId String organizer Organizer @relation(fields: [organizerId], references: [id], onDelete: Restrict) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Media { id String @id // ULID, not auto-generated slug String type String // "image" | "video" mimeType String size Int originalFilename String uploadedBy String title String? description String? altText String? createdAt DateTime @default(now()) } model Post { id String @id @default(uuid()) nostrEventId String @unique title String slug String @unique content String excerpt String? authorPubkey String authorName String? featured Boolean @default(false) visible Boolean @default(true) publishedAt DateTime createdAt DateTime @default(now()) updatedAt DateTime @updatedAt categories PostCategory[] } model Category { id String @id @default(uuid()) name String slug String @unique sortOrder Int @default(0) createdAt DateTime @default(now()) posts PostCategory[] } model PostCategory { postId String categoryId String post Post @relation(fields: [postId], references: [id], onDelete: Cascade) category Category @relation(fields: [categoryId], references: [id], onDelete: Cascade) @@id([postId, categoryId]) } model HiddenContent { id String @id @default(uuid()) nostrEventId String reason String? hiddenBy String createdAt DateTime @default(now()) } model BlockedPubkey { id String @id @default(uuid()) pubkey String reason String? blockedBy String createdAt DateTime @default(now()) } model Relay { id String @id @default(uuid()) url String @unique priority Int @default(0) active Boolean @default(true) createdAt DateTime @default(now()) } model Setting { id String @id @default(uuid()) key String @unique value String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model NostrEventCache { id String @id @default(uuid()) eventId String @unique kind Int pubkey String content String tags String // JSON string createdAt Int // event timestamp cachedAt DateTime @default(now()) } model Submission { id String @id @default(uuid()) eventId String? naddr String? title String authorPubkey String status String @default("PENDING") // PENDING, APPROVED, REJECTED reviewedBy String? reviewNote String? createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } model Faq { id String @id @default(uuid()) question String answer String order Int @default(0) showOnHomepage Boolean @default(true) createdAt DateTime @default(now()) updatedAt DateTime @updatedAt } /// Pending Lightning invoice metadata (message is created only after payment via webhook). model BoardInvoicePending { paymentHash String @id content String guestName String? pubkey String? profilePic String? createdAt DateTime @default(now()) } /// Paid board message (LNbits payment confirmed). model BoardMessage { id String @id @default(uuid()) paymentHash String @unique content String authorName String pubkey String? profilePic String? satsPaid Int status String @default("active") // active, hidden, deleted likeCount Int @default(0) createdAt DateTime @default(now()) }