Skip to content

Repository files navigation

shipwright

An AI-native, modular, own-it Next.js + Turborepo starter for shipping many MVPs fast.

shipwright is an open-source monorepo starter you assemble and own — not a paid SaaS boilerplate you rent, and not a black box you fork. You wire vetted libraries (Next.js, Drizzle, Better Auth, Stripe, shadcn/ui) into your own structure, pick features at install time, and ship products from it.

⚠️ Status: early / work in progress. Built in the open by dogfooding it on real apps — packages are extracted from actual usage, not pre-invented.

Why another starter?

Three things most starters don't do:

  1. AI-native. First-class Claude Code support ships in the repo: a curated root CLAUDE.md (with a convention for per-package CLAUDE.md files as packages need them) and a .claude/ directory (skills, subagents, settings). The repo is built to be driven by an AI coding agent.
  2. Modular, opt-in. Scaffold new apps and shared packages with pnpm gen app / pnpm gen package (Turborepo generators) — compose only what you need instead of inheriting a fixed all-in-one app. Every integration gracefully no-ops until you add its key.
  3. You own it. Assembled from vetted libraries on the bare official create-turbo skeleton — no vendor lock-in, no per-seat fees, no someone-else's-opinions you can't remove.

Stack (default presets — all swappable)

Because packages are extracted from real usage, not pre-invented, the table below is honest about what ships today vs. what's planned. Status reflects the current main:

Concern Default Status
Framework Next.js (App Router) + React ✅ In repo
Monorepo Turborepo + pnpm ✅ In repo
UI shadcn/ui + Tailwind ✅ In repo (@repo/ui)
Auth Better Auth (self-hosted, no per-MAU fee) ✅ In repo (@repo/auth)
DB / ORM Drizzle (libSQL/SQLite — local file or Turso) ✅ In repo (@repo/db); Postgres = CI-tested swap path
Env validation @t3-oss/env-nextjs + Zod ✅ In repo (@repo/env)
Security nonce CSP + security headers ✅ In repo (@repo/config)
Rate limiting in-memory / Upstash ✅ In repo (@repo/security)
Payments Stripe (checkout + idempotent webhooks) ✅ In repo (@repo/payments)
Email Resend + React Email ✅ In repo (@repo/email)
Analytics PostHog (consent-gated) ✅ In repo (@repo/analytics)
Observability Sentry + structured logger ✅ In repo (@repo/observability)
SEO / GEO metadata · sitemap · robots (AI crawlers) · JSON-LD (Article/FAQ/Breadcrumb) · llms.txt · OG image · Search Console ✅ In repo (@repo/seo)
Legal privacy / ToS / cookie consent ✅ In repo (@repo/legal)
PWA manifest + service worker + web-push ✅ In repo (@repo/pwa)
API style Server Actions (+ optional tRPC) ✅ Server Actions + tRPC (@repo/api)
File storage S3-compatible (R2 / S3 / MinIO) presigned upload ✅ In repo (@repo/storage)
i18n next-intl URL-prefix routing + hreflang ✅ In repo (@repo/i18n)

✅ = wired into apps/web today (the third-party integrations gracefully no-op until you add their API key, so the app, tests, and CI run with zero accounts). 🔜 = optional. Scaffold new apps/packages with pnpm gen, and every choice is a swappable preset.

Structure

apps/
  web/                 # reference app (the dogfood target): Tasks MVP
  admin/               # second app — dogfoods `pnpm gen app`, shares @repo/auth/db/ui
packages/
  ui/ auth/ db/ env/   # design system · Better Auth · Drizzle/libSQL · validated env
  config/              # @repo/config — security headers + nonce CSP
  security/            # @repo/security — rate limiting (in-memory / Upstash)
  payments/            # @repo/payments — Stripe checkout + idempotent webhooks
  email/               # @repo/email — Resend + React Email
  analytics/           # @repo/analytics — PostHog (consent-gated)
  observability/       # @repo/observability — Sentry + structured logger
  seo/ legal/          # metadata/sitemap/robots/JSON-LD · privacy/ToS/cookie consent
  pwa/                 # @repo/pwa — manifest + service worker + web-push
  api/                 # @repo/api — opt-in tRPC layer (TanStack React Query)
  storage/             # @repo/storage — S3-compatible presigned upload/download
  i18n/                # @repo/i18n — next-intl locale routing + navigation
  create-shipwright/   # the `npx create-shipwright` scaffolder
  eslint-config/ typescript-config/   # shared tooling
.claude/               # AI-native layer: skills, agents, settings
CLAUDE.md              # repo-wide guidance for Claude Code

Cross-cutting concerns (auth, db, payments, seo, email, observability…) become @repo/* packages as the reference app needs them — extracted from real usage, not pre-stubbed.

Getting started

pnpm install

# 1) Configure the reference app
cp apps/web/.env.example apps/web/.env   # then set BETTER_AUTH_SECRET (>= 32 chars)

# 2) Create the local SQLite tables in the app's db file. db:push runs from
#    packages/db, so point DATABASE_URL at the app's file (absolute path):
#    macOS/Linux:
DATABASE_URL="file:$PWD/apps/web/local.db" pnpm --filter @repo/db db:push
#    Windows (PowerShell):
#    $env:DATABASE_URL="file:$($PWD.Path)\apps\web\local.db"; pnpm --filter @repo/db db:push

# 3) Run it
pnpm dev --filter=web   # http://localhost:3000

Only BETTER_AUTH_SECRET is required — every third-party integration gracefully no-ops until you add its key, so the app, tests, and CI run with zero accounts.

Or scaffold a fresh project from this starter with the CLI:

npx create-shipwright my-app

Pick only the optional features you'll use — the rest stay in the scaffold (so it builds as-is) with exact removal steps in docs/REMOVING-FEATURES.md:

npx create-shipwright my-app --features payments,email

Scaffolding a PWA app

pnpm gen app scaffolds an installable + offline PWA in one step:

pnpm gen app            # interactive — answer "y" to "Make it a PWA?"
# or headless (3000/3100/3200/3300 are taken by web + admin):
pnpm gen app --args my-app 3400 true

It adds a manifest, an app-owned service worker, an /offline page, a placeholder app/icon.svg, and a nonce-CSP proxy.ts (whose strict policy the generated root layout opts into via await connection()). Replace the icon with real PNGs (public/icons/) before shipping. To add web push, pull in @repo/pwa/push (+ @repo/db); for an install button, @repo/pwa/install.

Deploying

See DEPLOY.md for host-agnostic recipes — Docker (Coolify / VPS / any container host, via Next.js standalone output), Vercel, and Cloudflare (OpenNext) — plus the env vars each needs, applying the schema to a prod Turso DB, and the Stripe webhook.

Roadmap

  • First reference app (apps/web) with auth + db (Tasks MVP: sign-up/in, per-user task CRUD, protected dashboard)
  • Extract @repo/{auth,db,env,config,security,payments,email,analytics,observability,seo,legal} from it
  • turbo gen scaffolding (pnpm gen app / pnpm gen package) + AI-native .claude/ layer
  • CI (lint/types/build/test/e2e/audit), nonce CSP + security headers, rate limiting
  • Optional @repo/pwa module (manifest + service worker + web-push)
  • Optional @repo/api (tRPC) — opt-in, alongside Server Actions
  • create-shipwright CLI (packages/create-shipwright) — in repo; npm publish wired via Changesets
  • Host-agnostic deploy recipes (Docker / Vercel / Cloudflare) + DEPLOY.md

License

MIT © Si Hyeong Lee

About

AI-native, modular, own-it Next.js + Turborepo starter for shipping many MVPs fast.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

Packages

Used by

Contributors

Languages