Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Wikedhart18/nextjs-ai-chatbot/llms.txt

Use this file to discover all available pages before exploring further.

The database layer uses Drizzle ORM with a PostgreSQL backend. Schema definitions live in lib/db/schema.ts. Each table is exported as a Drizzle table object and as a TypeScript type inferred with InferSelectModel.
Migrations are managed with drizzle-kit and live in lib/db/migrations/. Run pnpm db:migrate to apply pending migrations.

Entity relationships


User

Stores registered users. Passwords are hashed with bcrypt before insertion.
export const user = pgTable('User', {
  id: uuid('id').primaryKey().notNull().defaultRandom(),
  email: varchar('email', { length: 64 }).notNull(),
  password: varchar('password', { length: 64 }),
});

export type User = InferSelectModel<typeof user>;
id
uuid
required
Primary key. Auto-generated UUID v4. Defaults to a random value.
email
varchar(64)
required
The user’s email address. Maximum 64 characters. Must be unique per application logic.
password
varchar(64)
bcrypt-hashed password. Optional — accounts using OAuth providers will have no password stored.

Chat

Represents a single conversation thread owned by a user.
export const chat = pgTable('Chat', {
  id: uuid('id').primaryKey().notNull().defaultRandom(),
  createdAt: timestamp('createdAt').notNull(),
  title: text('title').notNull(),
  userId: uuid('userId')
    .notNull()
    .references(() => user.id),
  visibility: varchar('visibility', { enum: ['public', 'private'] })
    .notNull()
    .default('private'),
});

export type Chat = InferSelectModel<typeof chat>;
id
uuid
required
Primary key. Auto-generated UUID v4.
createdAt
timestamp
required
The time the chat was created. Set by the application at insert time.
title
text
required
Human-readable title for the conversation.
userId
uuid
required
Foreign key referencing User.id. Identifies the owning user.
visibility
'public' | 'private'
required
Controls whether the chat is accessible to others. Defaults to 'private'.

Message

An individual message within a chat, from either the user or the AI assistant.
export const message = pgTable('Message', {
  id: uuid('id').primaryKey().notNull().defaultRandom(),
  chatId: uuid('chatId')
    .notNull()
    .references(() => chat.id),
  role: varchar('role').notNull(),
  content: json('content').notNull(),
  createdAt: timestamp('createdAt').notNull(),
});

export type Message = InferSelectModel<typeof message>;
id
uuid
required
Primary key. Auto-generated UUID v4.
chatId
uuid
required
Foreign key referencing Chat.id. The conversation this message belongs to.
role
varchar
required
The sender role (e.g. 'user', 'assistant', 'system', 'tool'). Stored as a plain varchar with no enum constraint at the database level.
content
json
required
The message payload serialised as JSON. Shape matches the AI SDK CoreMessage content format and may include text parts, tool calls, or tool results.
createdAt
timestamp
required
The time the message was created.

Vote

Records a user’s up- or down-vote on a specific message. Uses a composite primary key.
export const vote = pgTable(
  'Vote',
  {
    chatId: uuid('chatId')
      .notNull()
      .references(() => chat.id),
    messageId: uuid('messageId')
      .notNull()
      .references(() => message.id),
    isUpvoted: boolean('isUpvoted').notNull(),
  },
  (table) => ({
    pk: primaryKey({ columns: [table.chatId, table.messageId] }),
  }),
);

export type Vote = InferSelectModel<typeof vote>;
chatId
uuid
required
Part of composite primary key. Foreign key referencing Chat.id.
messageId
uuid
required
Part of composite primary key. Foreign key referencing Message.id.
isUpvoted
boolean
required
true for an upvote, false for a downvote.
The composite primary key on (chatId, messageId) ensures each message can have at most one vote record per chat. voteMessage upserts by updating an existing row if one is found.

Document

An artifact (text, code, image, or sheet) created during a conversation. Uses a composite primary key on (id, createdAt) to support versioning — multiple rows can share the same id but differ by creation time.
export const document = pgTable(
  'Document',
  {
    id: uuid('id').notNull().defaultRandom(),
    createdAt: timestamp('createdAt').notNull(),
    title: text('title').notNull(),
    content: text('content'),
    kind: varchar('text', { enum: ['text', 'code', 'image', 'sheet'] })
      .notNull()
      .default('text'),
    userId: uuid('userId')
      .notNull()
      .references(() => user.id),
  },
  (table) => ({
    pk: primaryKey({ columns: [table.id, table.createdAt] }),
  }),
);

export type Document = InferSelectModel<typeof document>;
id
uuid
required
Part of composite primary key. Auto-generated UUID v4. Multiple versions of the same document share this value.
createdAt
timestamp
required
Part of composite primary key. The timestamp of this document version.
title
text
required
The document’s title.
content
text
The document body. Optional — may be null for placeholder or in-progress documents.
kind
'text' | 'code' | 'image' | 'sheet'
required
The artifact type. Defaults to 'text'.
userId
uuid
required
Foreign key referencing User.id. The owner of this document.

Suggestion

An inline edit suggestion on a document version. References the composite key (documentId, documentCreatedAt) on the Document table.
export const suggestion = pgTable(
  'Suggestion',
  {
    id: uuid('id').notNull().defaultRandom(),
    documentId: uuid('documentId').notNull(),
    documentCreatedAt: timestamp('documentCreatedAt').notNull(),
    originalText: text('originalText').notNull(),
    suggestedText: text('suggestedText').notNull(),
    description: text('description'),
    isResolved: boolean('isResolved').notNull().default(false),
    userId: uuid('userId')
      .notNull()
      .references(() => user.id),
    createdAt: timestamp('createdAt').notNull(),
  },
  (table) => ({
    pk: primaryKey({ columns: [table.id] }),
    documentRef: foreignKey({
      columns: [table.documentId, table.documentCreatedAt],
      foreignColumns: [document.id, document.createdAt],
    }),
  }),
);

export type Suggestion = InferSelectModel<typeof suggestion>;
id
uuid
required
Primary key. Auto-generated UUID v4.
documentId
uuid
required
Part of the composite foreign key referencing Document.id.
documentCreatedAt
timestamp
required
Part of the composite foreign key referencing Document.createdAt. Together with documentId this uniquely identifies the document version this suggestion targets.
originalText
text
required
The original text in the document that is being replaced.
suggestedText
text
required
The proposed replacement text.
description
text
An optional explanation of why the change is being suggested.
isResolved
boolean
required
Whether the suggestion has been accepted or dismissed. Defaults to false.
userId
uuid
required
Foreign key referencing User.id. The user who created the suggestion.
createdAt
timestamp
required
The time the suggestion was created.

Build docs developers (and LLMs) love