Documentation
Get up and running with NewsletterOS in minutes.
Quick Start
- 1. Run
pnpm installto install all dependencies - 2. Copy
.env.exampletoapps/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_URL is not set
Database Setup
- NewsletterOS uses PostgreSQL (forge-control postgres-shared) for data and Better Auth for sign-in.
- Set DATABASE_URL and BETTER_AUTH_SECRET (see .env.example).
- Run
DATABASE_URL=postgres://… ./infra/db-migrate.shto apply db/migrations/*.pg.sql. - Tables: newsletters, subscribers, campaigns, campaign_emails, segments, profiles.
- Every query is scoped to the signed-in owner in the app layer (no RLS).
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 RESEND_API_KEY and EMAIL_FROM for email delivery (EMAIL_PROVIDER=resend is the default; mailstack is also supported).
- Campaign HTML is sanitized via DOMPurify before sending.
- Each recipient gets their own email — addresses are never shared in a To: list.
- 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.
- Dashboard data is served by server actions that only return the signed-in owner’s rows.
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 the configured email provider (auth required)
- POST /api/stripe/checkout — Create Stripe checkout session
- POST /api/stripe/webhook — Handle Stripe webhook events (signature verified)
Full source code and README available on GitHub.
Get started free