Skip to main content

Installation

This guide walks you through setting up DelightBridge from scratch, including database setup, Google OAuth configuration, environment variables, and deployment options.

Prerequisites

Before you begin, ensure you have:
  • Node.js 20+ and pnpm installed
  • A Neon DB account (or any PostgreSQL database)
  • A Google Cloud Platform project with OAuth credentials
  • An Anthropic API key
  • (Optional) A Vercel account for deployment

Step 1: Clone and install dependencies

1

Clone the repository

git clone https://github.com/your-org/delightbridge.git
cd delightbridge
2

Install dependencies

DelightBridge uses pnpm as the package manager:
pnpm install

Step 2: Set up the database

DelightBridge uses Neon DB (serverless PostgreSQL) with Drizzle ORM.
1

Create a Neon DB project

  1. Go to console.neon.tech
  2. Click “New Project”
  3. Choose a region close to your users
  4. Copy the connection string (starts with postgresql://)
2

Add DATABASE_URL to environment

Create a .env.local file in the project root:
.env.local
DATABASE_URL=postgresql://user:[email protected]/dbname?sslmode=require
Keep this file secret! Add .env.local to .gitignore (already included by default).
3

Push the database schema

Drizzle will create all tables automatically:
pnpm db:push
This creates the following tables:
  • users — Workspace members with authentication info
  • workspace_members — Email allowlist for login
  • gmail_accounts — Services (Gmail accounts) with OAuth tokens
  • categories — Service-specific email categories
  • email_threads — Email conversations
  • emails — Individual messages within threads
  • drafts — AI-generated reply drafts
You can view and edit your database using Drizzle Studio:
pnpm db:studio
This opens a web UI at https://local.drizzle.studio.

Step 3: Configure Google OAuth

DelightBridge uses Google OAuth for two purposes:
  1. App authentication (NextAuth): Who can log in to the workspace
  2. Service Gmail connection: Which Gmail accounts to sync
1

Create OAuth credentials

  1. Go to Google Cloud Console
  2. Create a new project or select an existing one
  3. Navigate to APIs & Services > Credentials
  4. Click “Create Credentials” > “OAuth 2.0 Client ID”
  5. Choose “Web application”
2

Configure authorized redirect URIs

Add the following redirect URIs:For local development:
http://localhost:3000/api/auth/callback/google
http://localhost:3000/api/services/oauth/callback
For production (replace with your domain):
https://your-app.vercel.app/api/auth/callback/google
https://your-app.vercel.app/api/services/oauth/callback
3

Enable Gmail API

  1. In Google Cloud Console, go to APIs & Services > Library
  2. Search for “Gmail API”
  3. Click “Enable”
4

Copy credentials to environment

After creating OAuth credentials, copy the Client ID and Client Secret:
.env.local
GOOGLE_CLIENT_ID=123456789-abcdefghijklmnop.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-abcdefghijklmnopqrstuvwxyz
Make sure your OAuth consent screen is configured. During development, you can use “Testing” mode and add test users manually.

Step 4: Configure NextAuth

NextAuth handles user authentication and sessions.
1

Generate AUTH_SECRET

Generate a random secret for session encryption:
openssl rand -base64 32
Add it to .env.local:
.env.local
AUTH_SECRET=your-generated-secret-here
2

Set admin emails

Define who has admin access (comma-separated list):
.env.local
Users in ADMIN_EMAILS can always log in and have full Admin permissions. Other users must be added via the “권한 관리” (Permissions) tab in Settings.

Step 5: Configure Anthropic API

DelightBridge uses Claude Sonnet 4 for draft generation.
1

Get an Anthropic API key

  1. Go to console.anthropic.com
  2. Sign up or log in
  3. Navigate to API Keys
  4. Click “Create Key”
  5. Copy the key (starts with sk-ant-)
2

Add to environment

.env.local
ANTHROPIC_API_KEY=sk-ant-api03-your-key-here
Anthropic API has rate limits. For high-volume usage, consider requesting a rate limit increase or implementing request queuing.

Step 6: Configure Vercel Cron (optional)

For automatic Gmail sync every 5 minutes, set up Vercel Cron.
1

Generate a cron secret

openssl rand -base64 32
Add to .env.local:
.env.local
CRON_SECRET=your-cron-secret-here
CRON_SYNC_MAX_ACCOUNTS=20
CRON_SYNC_MAX_ACCOUNTS limits how many services are synced per cron run (prevents timeout).
2

Verify vercel.json configuration

DelightBridge includes a vercel.json file with cron configuration:
vercel.json
{
  "crons": [
    {
      "path": "/api/cron/sync-gmail",
      "schedule": "*/5 * * * *"
    }
  ]
}
This runs incremental Gmail sync every 5 minutes.

Step 7: Complete environment configuration

Your final .env.local should include all of these variables:
.env.local
# Database
DATABASE_URL=postgresql://user:[email protected]/dbname?sslmode=require

# Google OAuth
GOOGLE_CLIENT_ID=123456789-abcdefghijklmnop.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-abcdefghijklmnopqrstuvwxyz

# NextAuth
AUTH_SECRET=your-generated-secret-here
ADMIN_EMAILS=[email protected],[email protected]

# AI
ANTHROPIC_API_KEY=sk-ant-api03-your-key-here

# Cron (optional, for Vercel deployment)
CRON_SECRET=your-cron-secret-here
CRON_SYNC_MAX_ACCOUNTS=20
Never commit .env.local to version control. Use environment variables in your deployment platform (Vercel, Railway, etc.).

Step 8: Run locally

1

Start the development server

pnpm dev
DelightBridge will start at http://localhost:3000.
2

Verify the setup

  1. Open http://localhost:3000 in your browser
  2. You should be redirected to /login
  3. Click “Google로 로그인” and authenticate
  4. After login, you should see the main interface (or a “No services” prompt)

Step 9: Deploy to Vercel (optional)

1

Install Vercel CLI

pnpm add -g vercel
2

Deploy

vercel
Follow the prompts to link your project.
3

Add environment variables

In the Vercel dashboard:
  1. Go to Settings > Environment Variables
  2. Add all variables from .env.local
  3. Make sure to add them for Production, Preview, and Development environments
4

Update OAuth redirect URIs

Go back to Google Cloud Console and add your Vercel domain to the authorized redirect URIs:
https://your-app.vercel.app/api/auth/callback/google
https://your-app.vercel.app/api/services/oauth/callback
5

Deploy to production

vercel --prod

Step 10: Seed initial data (optional)

For testing, you can seed the database with sample data:
pnpm db:seed
This creates:
  • Sample services (Noji, AnkiPro)
  • Categories for each service
  • Mock email threads
Only run this in development! It will create mock data in your database.

Database schema reference

Here’s an overview of the database tables:

users

Stores authenticated workspace members.
ColumnTypeDescription
idtextPrimary key (e.g., user-123)
googleIdtextGoogle OAuth sub (unique)
emailtextUser email (unique)
nametextDisplay name
picturetextProfile picture URL
permissionenumview, edit, send, or admin
createdAttimestampAccount creation time

workspace_members

Email allowlist for login (invite-only).
ColumnTypeDescription
emailtextPrimary key
permissionenumDefault permission level
createdAttimestampWhen added

gmail_accounts

Services (Gmail accounts).
ColumnTypeDescription
idtextPrimary key (e.g., service-123)
nametextService name (e.g., “Noji”)
emailtextConnected Gmail address
colortextBrand color (hex)
signaturetextHTML email signature
documenttextReference docs (Markdown)
accessTokentextOAuth access token
refreshTokentextOAuth refresh token
lastHistoryIdtextGmail sync cursor
createdAttimestampService creation time

categories

Service-specific email categories.
ColumnTypeDescription
idtextPrimary key
accountIdtextForeign key to gmail_accounts
nametextCategory name
colortextBackground color (hex)
textColortextText color (hex)

email_threads

Email conversations.
ColumnTypeDescription
idtextPrimary key
accountIdtextForeign key to gmail_accounts
gmailThreadIdtextGmail thread ID
subjecttextEmail subject
customerEmailtextCustomer email address
customerNametextCustomer name
categoryIdtextAuto-assigned category
statusenuminbox, sent, or archived
detectedLanguagetextLanguage code (e.g., en)
isReadbooleanRead status
lastMessageAttimestampLast message time
createdAttimestampThread creation time

emails

Individual messages within threads.
ColumnTypeDescription
idtextPrimary key
threadIdtextForeign key to email_threads
gmailMessageIdtextGmail message ID
fromEmailtextSender email
fromNametextSender name
toEmailtextRecipient email
bodytextHTML body
directionenuminbound or outbound
sentAttimestampMessage timestamp
createdAttimestampDB creation time

drafts

AI-generated reply drafts.
ColumnTypeDescription
idtextPrimary key
threadIdtextForeign key to email_threads (unique)
subjecttextReply subject
contenttextHTML body
translationtextKorean translation
statusenumpending, ready, sent, or skipped
sentAttimestampWhen sent
updatedAttimestampLast edit time

Project structure

delightbridge/
├── src/
│   ├── app/                    # Next.js App Router
│   │   ├── api/                # API routes
│   │   │   ├── auth/           # NextAuth handlers
│   │   │   ├── cron/           # Vercel cron endpoints
│   │   │   ├── draft/          # AI draft generation
│   │   │   ├── members/        # Workspace member management
│   │   │   ├── services/       # Service CRUD + OAuth
│   │   │   └── threads/        # Email thread CRUD + send
│   │   ├── login/              # Login page
│   │   ├── layout.tsx          # Root layout
│   │   └── page.tsx            # Main app page
│   ├── components/             # React components
│   │   ├── MainLayout.tsx      # App orchestrator
│   │   ├── Sidebar.tsx         # Service switcher
│   │   ├── MailList.tsx        # Thread list
│   │   ├── MailDetail.tsx      # Thread detail panel
│   │   ├── ThreadView.tsx      # Email thread display
│   │   ├── DraftEditor.tsx     # TipTap editor
│   │   ├── TalkToDraft.tsx     # Natural language refinement
│   │   ├── TranslationPanel.tsx# Korean translation
│   │   ├── SendConfirmModal.tsx# Send confirmation
│   │   ├── BulkSendModal.tsx   # Bulk send confirmation
│   │   └── SettingsModal.tsx   # Settings UI
│   └── lib/
│       ├── db/                 # Database
│       │   └── schema.ts       # Drizzle schema
│       ├── types.ts            # TypeScript types
│       ├── utils.ts            # Utilities
│       ├── gmail.ts            # Gmail API helpers
│       ├── gmail-sync.ts       # Gmail sync logic
│       ├── session.ts          # NextAuth session guards
│       └── admin-emails.ts     # Admin email list
├── auth.ts                     # NextAuth config
├── auth.config.ts              # NextAuth Edge config
├── proxy.ts                    # Auth middleware
├── drizzle.config.ts           # Drizzle config
├── package.json                # Dependencies
├── vercel.json                 # Vercel cron config
└── .env.local                  # Environment variables (gitignored)

Available commands

pnpm dev          # Start development server (http://localhost:3000)
pnpm build        # Build for production
pnpm start        # Start production server
pnpm lint         # Run ESLint
pnpm db:push      # Push Drizzle schema to database
pnpm db:studio    # Open Drizzle Studio (database UI)
pnpm db:seed      # Seed database with mock data (dev only)

Next steps

Quickstart

Follow the quickstart guide to connect your first service and generate a draft

Team Collaboration

Add team members and configure permissions

Gmail Integration

Learn about automatic sync, manual triggers, and troubleshooting

API Reference

Explore the REST API endpoints

Troubleshooting

  • Check DATABASE_URL: Ensure it’s a valid PostgreSQL connection string
  • Check SSL mode: Neon requires ?sslmode=require at the end of the URL
  • Check IP allowlist: Some databases restrict connections by IP
  • Check redirect URIs: Make sure all URIs are added in Google Cloud Console
  • Check protocol: Use http:// for localhost and https:// for production
  • Check trailing slashes: Google is strict about exact URI matches
  • Check Node version: Use Node 20+
  • Clear cache: Run rm -rf .next node_modules pnpm-lock.yaml && pnpm install
  • Check TypeScript: Run pnpm build to see type errors
  • Restart dev server: .env.local changes require a restart
  • Check file name: It must be exactly .env.local (not .env)
  • Check deployment platform: Add variables in Vercel/Railway dashboard

Build docs developers (and LLMs) love