Skip to main content
ForgeAI stores projects, conversation messages, and generated code using PostgreSQL with Prisma ORM. The Prisma client is generated into lib/generated/prisma and uses the @prisma/adapter-pg driver for a serverless-compatible connection.

Setting up the database

1

Provision a PostgreSQL database

ForgeAI recommends Neon for serverless PostgreSQL. Create a project in the Neon dashboard and copy the connection string.
Neon’s free tier is sufficient for development. For production, use a connection pooler endpoint (Neon provides one automatically).
2

Set DATABASE_URL

Add the connection string to your .env.local file:
.env.local
DATABASE_URL="postgresql://user:password@host/dbname?sslmode=require"
3

Run migrations

Apply all pending migrations to your database.Development:
pnpm prisma migrate dev
Production:
pnpm prisma migrate deploy
prisma migrate dev also regenerates the Prisma client. Use prisma migrate deploy in CI/CD pipelines and production environments — it applies migrations without regenerating the client or prompting for input.

Data models

The schema defines three models: Project, Message, and CodeFragment. Each project contains messages, and each message may have an associated code fragment produced by the AI.

Project

Represents a single app-building session owned by a user.
FieldTypeDescription
idString (uuid)Primary key, auto-generated.
nameStringHuman-readable project name.
sandboxIdString?E2B sandbox ID associated with this project (optional, max 64 chars).
imageUrlString?Optional cover image URL.
userIdStringClerk user ID of the project owner.
createdAtDateTimeTimestamp of creation.
updatedAtDateTimeTimestamp of last update.
A Project has many Message records. Deleting a project cascades and deletes all its messages.

Message

Represents a single turn in the conversation — either a user prompt or an AI response.
FieldTypeDescription
idString (uuid)Primary key, auto-generated.
contentStringText content of the message.
roleMessageRoleUSER or ASSISTANT.
typeMessageTypeRESULT (successful AI output) or ERROR (failed generation).
userIdStringClerk user ID associated with this message.
imageUrlString?Optional image attached to the message (e.g. a design screenshot).
projectIdStringForeign key linking to the parent Project.
createdAtDateTimeTimestamp of creation.
updatedAtDateTimeTimestamp of last update.
A Message optionally has one CodeFragment. Deleting a message cascades and deletes its code fragment.

CodeFragment

Stores the generated code and sandbox details produced by an AI response.
FieldTypeDescription
idString (uuid)Primary key, auto-generated.
messageIdString (unique)Foreign key linking to the parent Message. One-to-one relationship.
sandboxUrlStringURL of the live E2B sandbox preview.
sandboxIdString?E2B sandbox ID (optional, max 64 chars).
titleStringTitle of the generated app.
filesJsonMap of file paths to file contents for the generated app.
imageUrlString?Optional screenshot of the generated app.
designSpecJson?Optional design specification extracted from an uploaded screenshot.
createdAtDateTimeTimestamp of creation.
updatedAtDateTimeTimestamp of last update.

Schema overview

schema.prisma
generator client {
  provider = "prisma-client"
  output   = "../lib/generated/prisma"
}

datasource db {
  provider = "postgresql"
}

enum MessageRole {
  USER
  ASSISTANT
}

enum MessageType {
  RESULT
  ERROR
}

model Project {
  id        String    @id @default(uuid())
  name      String
  messages  Message[]
  sandboxId String?   @db.VarChar(64)
  imageUrl  String?
  userId    String
  createdAt DateTime  @default(now())
  updatedAt DateTime  @updatedAt
}

model Message {
  id           String        @id @default(uuid())
  content      String
  role         MessageRole
  type         MessageType
  codeFragment CodeFragment?
  userId       String
  imageUrl     String?
  projectId    String
  project      Project       @relation(references: [id], fields: [projectId], onDelete: Cascade)
  createdAt    DateTime      @default(now())
  updatedAt    DateTime      @updatedAt
}

model CodeFragment {
  id         String   @id @default(uuid())
  messageId  String   @unique
  message    Message  @relation(references: [id], fields: [messageId], onDelete: Cascade)
  sandboxUrl String
  sandboxId  String?  @db.VarChar(64)
  title      String
  files      Json
  imageUrl   String?
  designSpec Json?
  createdAt  DateTime @default(now())
  updatedAt  DateTime @updatedAt
}

Environment Variables

Set DATABASE_URL and other required secrets.

E2B Sandbox

Learn how sandboxes are created and managed for live previews.

Build docs developers (and LLMs) love