Skip to content

Package Structure

SMTA is structured as a pnpm workspace with Turborepo. Source is split across packages by concern so that application projects only adopt what they need. All packages are published to npm under the @smta scope and versioned together — installing @smta/schemas@1.2.0 guarantees compatibility with a database deployed from @smta/cli@1.2.0.

packages/
├── core/ @smta/core — adapter-agnostic SQL (56 files)
├── supabase/ @smta/supabase — Supabase-specific SQL and FK constraints
├── payload/ @smta/payload — Payload CMS adapter SQL + TypeScript middleware
├── billing/ @smta/billing — TypeScript BillingProvider interface
├── schemas/ @smta/schemas — Zod v4 validation schemas
└── cli/ @smta/cli — deployment CLI (npx @smta/cli)
apps/
└── docs/ @smta/docs — this documentation site
scripts/
├── combine_files.js — local dev equivalent of @smta/cli
├── run_tests.sh — runs the full pgTap test suite
└── 99_testing_grants.sql

Contains all adapter-agnostic SQL: schemas, tables, triggers, RLS policies, and public functions. This is the bulk of SMTA — 56 SQL files organized into subdirectories:

packages/core/sql/
├── init/ — extension and schema creation
├── platform/
│ ├── tables/ — platform-admin tables
│ ├── functions/ — platform management functions
│ └── rls/ — platform table RLS policies
├── core/
│ ├── tables/ — org, unit, membership tables
│ ├── triggers/ — updated_at, auto-create triggers
│ └── rls/ — core table RLS policies
├── public/
│ └── functions/ — public API functions for app code
└── utils/
└── functions/ — internal utility functions

All SQL in this package must be adapter-agnostic. It must not reference Supabase- or Payload-specific constructs.

Contains 3 SQL files plus FK constraint additions that complete the schema for Supabase deployments. This package supplements @smta/core with Supabase-specific wiring (auth schema foreign keys, etc.).

Contains 1 SQL file adapting SMTA for use with Payload CMS, plus a TypeScript middleware package for injecting the auth session variable into Payload requests.

A TypeScript package exposing the BillingProvider interface. Application code implements this interface to connect SMTA’s subscription hooks to a billing provider such as Stripe.

Zod v4 schemas for validating SMTA data at the application boundary. Import these in server actions, API routes, or form validation logic.

The deployment CLI. Resolves @smta/core and the chosen adapter package at runtime, reads their sql-scripts.json manifests, and concatenates the SQL files into a single deployment artifact written to the current directory.

Terminal window
npx @smta/cli --adapter supabase
# → SMTA-supabase-<timestamp>.sql

@smta/core is a hard dependency. @smta/supabase and @smta/payload are optional dependencies — only the adapter you need gets installed.

Every SQL-containing package has a sql-scripts.json file that lists its SQL files in execution order. This file is what @smta/cli (and scripts/combine_files.js locally) reads to assemble the final deployment SQL.

Example structure:

{
"scripts": [
"sql/init/01_extensions.sql",
"sql/init/02_schemas.sql",
"sql/core/tables/01_organizations.sql",
"sql/core/tables/02_units.sql",
"sql/core/rls/01_organizations.sql"
]
}

Order matters: a file that creates a table must appear before any file that adds RLS policies or triggers to that table.

All six packages are released together at the same version using Changesets in fixed mode. This ensures the SQL deployed and the TypeScript packages installed are always compatible. A GitHub Actions workflow opens a version PR when changesets are present and publishes to npm when that PR is merged.

The documentation site is built with Starlight (Astro). Content lives in apps/docs/src/content/docs/ as .mdx files. The sidebar structure is configured in apps/docs/astro.config.mjs.

To run the docs site locally:

Terminal window
cd apps/docs
npm run dev