Documentation
Get up and running with Letterly in minutes.
Quick Start
- 1. Run
pnpm installto install all dependencies - 2. Copy
.env.exampletopackages/web/.env.local - 3. Run
pnpm run dev:webto start on localhost:3000 - 4. The app runs in demo mode with mock data when
DATABASE_URLis not set
Database Setup
- Letterly stores its data in PostgreSQL through Drizzle ORM (the
newsletterschema inpackages/db). - Set
DATABASE_URLinpackages/web/.env.localto leave demo mode. - Migrations live in
packages/db/drizzle. - Tables: newsletters, subscribers, campaigns, campaign_emails, segments, profiles.
Stripe Billing
- Create Stripe products for Starter ($9), Pro ($19), and Growth ($49) plans.
- Set STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, and STRIPE_PRICE_* env vars.
- Run
stripe listen --forward-to localhost:3000/api/stripe/webhookfor local testing. - Webhooks handle checkout completion, subscription updates, and cancellations.
AI Features
- Supports two AI providers: Google Gemini (primary) and Anthropic Claude (fallback).
- Set
GEMINI_API_KEYfor Gemini orANTHROPIC_API_KEYfor Claude. - Configure provider priority with
AI_PRIMARY_PROVIDERandAI_SECONDARY_PROVIDER. - AI usage is tracked per user with plan-based limits (Free: 100/mo, Starter: 500, Pro: 2000, Growth: unlimited).
- The AI route includes rate limiting (10 req/min), input sanitization, and automatic provider fallback.
Email Delivery
- Set EMAIL_PROVIDER=mailstack plus MAILSTACK_HMAC_SECRET (or legacy MAILSTACK_API_KEY), MAILSTACK_API_URL, and MAILSTACK_FROM_EMAIL for email delivery.
- The @blueforge-studio/service-email factory selects the adapter; the Mailstack adapter handles batching internally.
- Campaign HTML is sanitized via DOMPurify before sending.
- The BullMQ worker handles async email jobs — start with
pnpm run dev:worker.
Security
- All API mutation routes have CSRF/origin verification.
- Rate limiting is Redis-backed with in-memory fallback.
- API routes verify newsletter ownership before mutations.
- CSV exports escape formula-triggering characters to prevent injection.
API Reference
- POST /api/subscribers/import — CSV file import (auth required)
- GET /api/subscribers/export — CSV download (auth required)
- POST /api/ai/subject-lines — AI subject line generation
- POST /api/campaigns/send — Send campaign via service-email (Mailstack) (auth required)
- POST /api/stripe/checkout — Create Stripe checkout session for the signed-in account (requires sign-in)
- POST /api/stripe/webhook — Handle Stripe webhook events (signature verified)
Full source code and README available on GitHub.
Get started free