The AI communication tool for Gmail and Slack.

๐Ÿš€ Try the Dashboard ยท ๐Ÿงฉ Install Chrome Extension ยท If this project helps you, consider giving it a โญ

A self-hostable Chrome Extension + SaaS monorepo that injects an AI communication toolbar into Gmail and Slack. Select text โ†’ pick a rewrite mode โ†’ done. Supports custom prompt templates per user/org, streaming responses, and a full writing history.


Demo

Slack Gmail
Slack Gmail
Rewrite messages before sending Compose & reply with AI drafts

Features

  • Gmail toolbar โ€” select text in any compose window, get instant AI rewrites (improve, shorten, expand, formal, casual)
  • Custom prompt templates โ€” save reusable prompts per user or organization
  • Org writing tone โ€” set a baseline writing style that applies to all rewrites
  • Streaming rewrites โ€” real-time token streaming via SSE
  • Writing history โ€” every session saved, browsable in the dashboard
  • Multi-platform ready โ€” architecture designed to add Slack, LinkedIn, etc. with minimal code

Web Dashboard

The web app (apps/web) is your control center for ComCom. Sign in at http://localhost:3000 (or your deployed URL) to access it.

Overview (/dashboard)

  • Stats โ€” prompt template count, rewrites today, total rewrites
  • Recent Rewrites โ€” last 5 rewrite sessions with mode and date
  • Quick Actions โ€” shortcuts to create a prompt, configure tone, or install the extension

Prompt Templates (/dashboard/prompts)

Create and manage reusable AI prompts that appear inside the ComCom toolbar in Gmail and Slack.

Each template has:

  • Title โ€” displayed in the extension toolbar
  • System Prompt โ€” the instruction sent to the AI. Use {{variable_name}} placeholders for dynamic values
  • Variables โ€” define named placeholders with a label and optional default value
  • Share with organization โ€” toggle to make the prompt available to all org members

Example system prompt:

Rewrite the following email in a {{tone}} tone, keeping it under {{max_words}} words.

Writing History (/dashboard/history)

Every rewrite is logged automatically. The history page shows:

  • Original text vs. rewritten text side by side
  • Rewrite mode (improve, shorten, expand, formal, casual, or custom prompt)
  • Source (gmail, slack)
  • Timestamp and token usage

Settings (/dashboard/settings)

Set your organization's default writing tone applied to all AI rewrites:

  • Voice โ€” professional, friendly, casual, authoritative, or empathetic
  • Formality โ€” formal, semi-formal, or informal
  • Additional instructions โ€” free-text style rules (e.g. "Always sign off with Best regards. Avoid jargon.")

Architecture

Chrome Extension โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
                                                    โ†“
Next.js frontend โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€ Cloudflare Worker API
                                         โ†“               โ†“
                                    OpenAI API       Neon DB (Prisma)

Key principle: All business logic lives in the Cloudflare Worker. Next.js is frontend-only (no API routes except the Clerk webhook).

Stack

Layer Technology
Monorepo Turborepo + pnpm workspaces
Web App Next.js 14 App Router + TypeScript
Backend API Cloudflare Workers + Hono + TypeScript
UI Tailwind CSS + shadcn/ui
Chrome Extension Plasmo + React + TypeScript
Database PostgreSQL (Neon) via Prisma + Neon adapter
Auth Clerk (JWT verified in Worker)
AI OpenAI API (gpt-4o-mini)
Validation Zod

Project Structure

comcom/
โ”œโ”€โ”€ apps/
โ”‚   โ”œโ”€โ”€ web/              # Next.js frontend (Vercel) โ€” NO API routes
โ”‚   โ”œโ”€โ”€ worker/           # Cloudflare Worker backend (Hono)
โ”‚   โ””โ”€โ”€ extension/        # Chrome Extension (Plasmo)
โ”œโ”€โ”€ packages/
โ”‚   โ”œโ”€โ”€ ai/               # OpenAI wrapper + prompt builder
โ”‚   โ”œโ”€โ”€ db/               # Prisma schema + edge client + repositories
โ”‚   โ”œโ”€โ”€ prompts/          # Default prompt templates
โ”‚   โ”œโ”€โ”€ types/            # Shared TypeScript types + Zod schemas
โ”‚   โ””โ”€โ”€ ui/               # Shared React components

API Reference

Method Path Auth Description
GET /health None Health check
POST /api/rewrite JWT Sync AI rewrite
POST /api/rewrite/stream JWT Streaming AI rewrite (SSE)
GET /api/prompts JWT List user + org prompts
POST /api/prompts JWT Create prompt template
PATCH /api/prompts/:id JWT Update prompt
DELETE /api/prompts/:id JWT Delete prompt
GET /api/history JWT Writing session history
POST /api/history JWT Create session record
GET /api/tone JWT Get org writing tone
PUT /api/tone JWT Update org writing tone

Next.js retains only: POST /api/webhooks/clerk (user/org sync).


Self-Hosting

Prerequisites

  • Node.js >= 20
  • pnpm >= 9 (npm install -g pnpm)
  • Neon PostgreSQL database (or any Postgres โ€” Neon is recommended for its edge-compatible pooler)
  • Clerk account
  • OpenAI API key
  • Cloudflare account

1. Clone & install

git clone https://github.com/eric248550/comcom.git
cd comcom
pnpm install

2. Configure environment variables

Copy the example files and fill in your values:

cp .env.example .env
cp packages/db/.env.example packages/db/.env
cp apps/web/.env.local.example apps/web/.env.local
cp apps/worker/.dev.vars.example apps/worker/.dev.vars
cp apps/extension/.env.example apps/extension/.env.development
File Used by Key variables
.env Turborepo (all tasks) All vars โ€” source of truth
packages/db/.env Prisma CLI DATABASE_URL (pooled) + DIRECT_URL (direct)
apps/web/.env.local Next.js Clerk keys, WORKER_URL
apps/worker/.dev.vars Wrangler dev All secrets (Wrangler ignores root .env)
apps/extension/.env.development Plasmo PLASMO_PUBLIC_* vars only

Neon DB URLs: DATABASE_URL uses the pooled endpoint (-pooler in hostname) for runtime queries. DIRECT_URL uses the direct endpoint (no -pooler) for Prisma migrations โ€” PgBouncer does not support DDL.

3. Set up the database

Required before building the Worker. The Worker bundles the Prisma edge client at build time; skipping this step causes Could not resolve "./generated/prisma" errors.

pnpm db:generate   # Generate Prisma client
pnpm db:push       # Push schema to database (requires DIRECT_URL)

4. Run in development

# Terminal 1 โ€” start the Worker first (web app depends on it)
pnpm worker:dev    # โ†’ http://localhost:8787

# Terminal 2 โ€” Next.js web app
cd apps/web && pnpm dev   # โ†’ http://localhost:3000

# Terminal 3 โ€” Chrome extension (hot-reload)
cd apps/extension && pnpm dev

Or run everything in parallel:

pnpm dev

5. Load the extension in Chrome

  1. Open chrome://extensions โ†’ enable Developer mode
  2. Click Load unpacked โ†’ select apps/extension/build/chrome-mv3-dev
  3. Open Gmail, compose an email, select any text โ€” the ComCom toolbar appears

Deployment

Cloudflare Worker

# Set production secrets
wrangler secret put DATABASE_URL
wrangler secret put CLERK_SECRET_KEY
wrangler secret put CLERK_PUBLISHABLE_KEY
wrangler secret put OPENAI_API_KEY
wrangler secret put ALLOWED_ORIGINS

# Deploy
pnpm worker:deploy
# โ†’ https://comcom-api.<your-subdomain>.workers.dev

Vercel (Next.js)

Set these environment variables in the Vercel dashboard:

WORKER_URL=https://comcom-api.<subdomain>.workers.dev
NEXT_PUBLIC_WORKER_URL=https://comcom-api.<subdomain>.workers.dev
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
CLERK_WEBHOOK_SECRET=whsec_...
DATABASE_URL=<pooled neon url>

Also configure a Clerk webhook pointing to https://your-vercel-app.vercel.app/api/webhooks/clerk with the user.created, organization.created, and organizationMembership.created events.

Chrome Web Store

The extension is published at: https://chromewebstore.google.com/detail/comcom/dpmfokapmmmahdkaphlgodghojcdhigo

To publish a new version:

cd apps/extension && pnpm build
# Zip apps/extension/.plasmo/chrome-mv3-prod/ and submit to CWS

Data Flow

1. User selects text in Gmail compose
2. Extension sends POST /api/rewrite to Worker (with Clerk JWT)
3. Worker verifies JWT โ†’ resolves user + org from DB
4. Worker fetches prompt template + org tone from Neon DB
5. Worker builds final system prompt
6. Worker calls OpenAI API (streams or sync)
7. Worker saves WritingSession to DB
8. Extension receives result โ†’ replaces selected text in place

Extending to New Platforms

To add Slack, LinkedIn, or any other platform:

  1. Add a content script: apps/extension/src/contents/<platform>.tsx
  2. Implement getSelectedText() and replaceSelectedText() for that platform's DOM
  3. Reuse src/lib/api.ts โ€” it's already Worker-agnostic
  4. Update PlasmoCSConfig.matches for the new URL pattern

After making changes, verify nothing is broken

pnpm type-check pnpm lint pnpm build


For extension changes, run the [verify script](https://github.com/eric248550/comcom/blob/main/verify-extension.mjs) to walk through the auth flow manually:

```bash
node verify-extension.mjs

Package Scripts

Command Description
pnpm dev Start all apps in dev mode
pnpm build Build all packages and apps
pnpm worker:dev Start Worker dev server on :8787
pnpm worker:deploy Deploy Worker to Cloudflare
pnpm db:generate Regenerate Prisma client
pnpm db:push Push schema changes to DB
pnpm db:studio Open Prisma Studio
pnpm lint Lint all packages
pnpm type-check Type-check all packages
pnpm format Format all files with Prettier

Author

Eric Tsai โ€” [email protected] ยท GitHub @eric248550