Architecture Overview

Sendoka is a single Next.js 16 App Router application. All API surface, dashboard UI, and background handlers run as route handlers in one deployable unit.

Layers

┌─────────────────────────────────────────────────────────┐
│  Dashboard UI (src/app/overview/**)                    │
│  React Server Components — NextAuth session gated       │
└────────────┬────────────────────────────────────────────┘
             │ fetch
┌────────────▼────────────────────────────────────────────┐
│  Internal API (src/app/api/internal/**)                 │
│  Session-auth'd CRUD for dashboard                      │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  Public API v1 (src/app/api/v1/**)                      │
│  API-key auth'd send endpoints                          │
└────────────┬────────────────────────────────────────────┘
             │
┌────────────▼─────────────┬──────────────────────────────┐
│ withApiAuth middleware   │  • Bearer key → org/env     │
│ (src/lib/api/middleware) │  • Rate limit (Upstash)     │
└────────────┬─────────────┴──────────────────────────────┘
             │
┌────────────▼────────────────────────────────────────────┐
│  Providers (src/lib/providers/**)                       │
│  AWS SES v2 (email) · AWS SNS (SMS) · SES domain ID    │
└─────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────┐
│  Inbound Webhooks (src/app/api/webhooks/**)             │
│  SES → SNS HTTP · Stripe signed events                  │
└────────────┬────────────────────────────────────────────┘
             │
┌────────────▼────────────────────────────────────────────┐
│  Webhook fan-out → customer endpoints                   │
│  (src/lib/api/webhook-fanout.ts)                        │
└─────────────────────────────────────────────────────────┘

Data: Neon Postgres (Drizzle ORM). Cache/RL: Upstash Redis.

Key modules

  • src/app/api/v1/* — public REST API (email/SMS send, list, retrieve, batch).
  • src/app/api/internal/* — session-auth'd dashboard CRUD (keys, domains, webhooks, templates, team, org, billing, audit, two-factor).
  • src/app/api/auth/* — NextAuth + user registration + email verify + password reset.
  • src/app/api/webhooks/* — inbound from SES (status events), SNS SMS (delivery), Stripe.
  • src/app/api/cron/* — 13 scheduled jobs, each registered in vercel.ts and gated on the shared cronAuthorized. Full registry with schedules and per-job semantics: Cron jobs.
  • src/lib/api/* — cross-cutting: auth middleware, errors, idempotency, cursor pagination, rate limit (per-plan), usage metering, webhook fan-out + delivery log, audit log, SNS signature verification, template rendering.
  • src/lib/auth/* — NextAuth options, API-key generate/validate, TOTP, email-verification helper, active-org cookie resolver.
  • src/lib/billing/* — Stripe client + plan definitions.
  • src/lib/providers/* — AWS SES (simple + raw MIME) / SNS wrappers, domain identity management.
  • src/lib/db/* — Drizzle connection + 57 tables across schema/*.ts, re-exported through schema/index.ts.
  • src/components/ui/* — toast, skeleton, confirm dialog, error boundary.

Request authentication modes

Surface Auth Implementation
/overview/* NextAuth JWT proxy.ts (Next 16 renamed middleware.ts; the exported function must be named proxy)
/api/internal/* getServerSession route-level checks
/api/v1/* Bearer API key withApiAuth wrapper
/api/webhooks/stripe Stripe signature stripe.webhooks.constructEvent
/api/webhooks/ses SNS signature (RSA-SHA1/SHA256 against SigningCertURL) src/lib/api/sns-verify.ts
/api/webhooks/sns-sms SNS signature same module
/api/cron/* Bearer CRON_SECRET cronAuthorized (src/lib/api/cron-auth.ts), shared by all 13 routes — timingSafeEqual, fails closed in production
/api/auth/* public (register, NextAuth) n/a