NewsletterOS

Documentation

Get up and running with NewsletterOS in minutes.

Quick Start

  • 1. Run pnpm install to install all dependencies
  • 2. Copy .env.example to apps/web/.env.local
  • 3. Run pnpm run dev:web to 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.sh to 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/webhook for 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_KEY for Gemini or ANTHROPIC_API_KEY for Claude.
  • Configure provider priority with AI_PRIMARY_PROVIDER and AI_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