Skip to content

insideaayush/saas-core-template

Repository files navigation

saas-core-template

Production-shaped foundation for launching a startup SaaS baseline quickly.

Stack

  • Frontend: Next.js (TypeScript)
  • UI: shadcn/ui (Tailwind + Radix)
  • Backend: Go (net/http)
  • Database: Postgres
  • Cache: Redis (Upstash in cloud, local Redis in development)
  • Auth: Clerk (managed auth, organization context)
  • Billing: Stripe (checkout + portal + webhook sync)
  • Deploy: Render (backend + Postgres) + Vercel (frontend)
  • CI: GitHub Actions

Repository layout

  • frontend/ Next.js shell and app routes
  • backend/ Go API shell, auth/billing endpoints, and migrations
  • docker-compose.yml local Postgres + Redis
  • render.yaml Render blueprint for backend and Postgres
  • .github/workflows/ci.yml CI for frontend and backend
  • docs/roadmap.md product phases after shell

Prerequisites

  • Node.js 20+
  • npm 10+
  • Go 1.22+
  • Docker Desktop (or Docker Engine + Compose)

Environment variables

Copy examples and adjust as needed:

cp .env.example .env
cp backend/.env.example backend/.env
cp frontend/.env.example frontend/.env.local

Core variables:

  • Backend
    • PORT (default 8080)
    • DATABASE_URL (local Postgres or Render Postgres URL)
    • REDIS_URL (local Redis or Upstash Redis URL)
    • APP_BASE_URL (frontend URL used for checkout return paths)
    • APP_ENV (development or production)
    • APP_VERSION (dev, commit SHA, or release tag)
    • OTEL_SERVICE_NAME (default saas-core-template-backend)
    • OTEL_TRACES_EXPORTER (console, otlp, or none)
    • OTEL_EXPORTER_OTLP_ENDPOINT (local collector default http://localhost:4318)
    • OTEL_EXPORTER_OTLP_HEADERS (for managed OTLP auth, e.g. Grafana Cloud)
    • ERROR_REPORTING_PROVIDER (console, sentry, or none)
    • SENTRY_DSN (backend error reporting)
    • SENTRY_ENVIRONMENT (defaults to empty)
    • ANALYTICS_PROVIDER (console, posthog, or none)
    • POSTHOG_PROJECT_KEY
    • POSTHOG_HOST
    • EMAIL_PROVIDER (console, resend, or none)
    • EMAIL_FROM
    • RESEND_API_KEY
    • JOBS_ENABLED (worker toggle)
    • JOBS_WORKER_ID
    • JOBS_POLL_INTERVAL
    • FILE_STORAGE_PROVIDER (disk, s3, or none)
    • FILE_STORAGE_DISK_PATH
    • S3_BUCKET, S3_REGION, S3_ENDPOINT, S3_ACCESS_KEY_ID, S3_SECRET_ACCESS_KEY, S3_FORCE_PATH_STYLE
    • CLERK_SECRET_KEY
    • CLERK_API_URL (default https://api.clerk.com)
    • STRIPE_SECRET_KEY
    • STRIPE_WEBHOOK_SECRET
    • STRIPE_API_URL (default https://api.stripe.com/v1)
    • STRIPE_PRICE_PRO_MONTHLY
    • STRIPE_PRICE_TEAM_MONTHLY
  • Frontend
    • NEXT_PUBLIC_API_URL (e.g. http://localhost:8080)
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY
    • NEXT_PUBLIC_ANALYTICS_PROVIDER (console, posthog, or none)
    • NEXT_PUBLIC_POSTHOG_KEY
    • NEXT_PUBLIC_POSTHOG_HOST
    • NEXT_PUBLIC_SUPPORT_PROVIDER (crisp or none)
    • NEXT_PUBLIC_CRISP_WEBSITE_ID
    • NEXT_PUBLIC_ERROR_REPORTING_PROVIDER (console, sentry, or none)
    • NEXT_PUBLIC_SENTRY_DSN
    • NEXT_PUBLIC_SENTRY_ENVIRONMENT
    • Locale is stored in a locale cookie (supported: en, es)

Database migrations

SQL migrations live in backend/migrations/.

Apply them before using auth/billing endpoints.

Recommended: run the built-in migration CLI (tracks applied migrations in schema_migrations):

make migrate-up

Initial migration files (applied in order):

  • backend/migrations/0001_identity_tenancy_billing.up.sql
  • backend/migrations/0002_jobs_audit_files.up.sql
  • backend/migrations/0003_personal_workspaces.up.sql
  • backend/migrations/0004_team_owner_enforcement.up.sql
  • backend/migrations/0005_org_invites.up.sql

Local development

Run infra first:

make infra-up

This starts Postgres, Redis, and a local OpenTelemetry collector (for local tracing).

Optional: run a local end-to-end smoke test (infra + api + worker + ui):

make smoke-local

If your local Node version can't run Next.js, skip the UI step:

make smoke-local SMOKE_ARGS=--skip-ui

Smoke test uses a separate Postgres database (default saas_core_template_smoke) and recreates it each run. Override with SMOKE_DB_NAME=<name>.

Start backend in one terminal:

make dev-api

Start worker in another terminal (jobs + email):

make dev-worker

Start frontend in another terminal:

make dev-ui

Open:

  • Frontend: http://localhost:3000
  • Backend health: http://localhost:8080/healthz
  • Backend readiness: http://localhost:8080/readyz
  • Backend metadata: http://localhost:8080/api/v1/meta
  • Sign in: http://localhost:3000/sign-in
  • Pricing: http://localhost:3000/pricing

Stop local infra:

make infra-down

CI checks

Run locally:

make ci

GitHub Actions workflow runs on pull requests and pushes to main, develop, and dev:

  • Backend: go test, go vet, build
  • Frontend: install, lint, typecheck, build

CI currently runs on main, develop, and dev branches.

Branch strategy

  • main: release branch
  • develop: integration branch
  • dev or feature/*: feature implementation branches

Recommended flow:

  1. Build in dev or feature/*.
  2. Open PR into develop.
  3. Release from develop into main.

Versioning

  • Template version source of truth: VERSION
  • Versioning scheme: SemVer (MAJOR.MINOR.PATCH)
  • CI validates VERSION format on main, develop, and dev.

See docs/operations/git-branching-and-versioning.md for full guidance.

Production deployment

This template deploys:

  • Backend + Postgres on Render (see render.yaml)
  • Frontend on Vercel (deploy frontend/)

Backend + Postgres (Render)

  1. Connect this GitHub repository in Render.
  2. Create services from the render.yaml blueprint.
  3. Set backend secrets: REDIS_URL, CLERK_SECRET_KEY, STRIPE_SECRET_KEY, STRIPE_WEBHOOK_SECRET, Stripe price IDs.
  4. Set APP_BASE_URL to your Vercel frontend URL (used for Stripe return URLs).
  5. Ensure auto-deploy is enabled for main.

Frontend (Vercel)

  1. Import the repo in Vercel.
  2. Set project root directory to frontend/.
  3. Set environment variables:
    • NEXT_PUBLIC_API_URL = Render backend URL
    • NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY = Clerk publishable key
  4. Deploy.

Deployment flow:

  • Push to main -> GitHub Actions CI passes -> Render auto-deploys backend; Vercel deploys frontend.

Notes

  • Local Redis exists for parity; production uses Upstash Redis.
  • main branch protection should require CI checks before merge.
  • Auth/billing provider boundaries and migration playbooks are documented in docs/.

Initialize from template

After cloning, run:

./scripts/init-template.sh "your-project-name"

This replaces saas-core-template references across tracked files (including Go module/import paths and deployment service names) and prints follow-up commands.

About

saas-core-template is an agent-first, production-shaped SaaS starter that gives you a deployable Next.js + Go foundation with auth, multi-tenant architecture, pricing/billing scaffolding, CI/CD, and built-in docs/skills for consistent, scalable development.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors