Skip to content

oscardobsonbrown/next-ship

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,581 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

next-ship

Production-grade Next.js starter for modern SaaS applications.

Built for solo founders and small teams who want a fast, maintainable foundation without the enterprise complexity.

Why next-ship?

Most Next.js starters are either too basic or too complex. next-ship hits the sweet spot:

  • Modern stack β€” Latest stable tools that work well together
  • Simplified β€” Removed enterprise features you don't need as a solo founder
  • Fast to ship β€” Pre-configured auth, payments, database, and analytics
  • Easy to maintain β€” Consolidated tooling, flat URLs
  • Production-ready β€” Type-safe, secure, and scalable

Stack

Framework

  • Next.js 16.2 β€” React 19, latest features
  • TypeScript 5.9 β€” Strict mode, end-to-end type safety
  • Turborepo + pnpm β€” Monorepo with fast, disk-space efficient installs
  • Tailwind CSS 4 β€” Latest syntax, no configuration needed

Core Services

Service Purpose
Clerk Authentication β€” simple, secure, works out of the box
Drizzle ORM Database β€” type-safe, SQL-like, better performance than Prisma
Neon PostgreSQL Database hosting β€” serverless, scales with you
Polar.sh Payments β€” modern SaaS billing with strong TypeScript support
PostHog Analytics + Error tracking β€” one tool instead of three
Resend Transactional email β€” simple API, great deliverability
BaseHub CMS β€” type-safe content management
Nosecone Security headers

UI Components

  • Base UI β€” shadcn's next-generation component library (replacement for Radix)
  • Tailwind CSS v4 β€” Latest features, no config
  • Geist font β€” Modern, readable typography

Quick Start

Prerequisites

Installation

# Clone the repository
git clone https://github.com/oscardobsonbrown/next-ship.git
cd next-ship

# Install dependencies
pnpm install

# Set up environment variables
# Copy .env.example files to .env in each app/package and fill in your API keys

# Run database migrations
pnpm --filter @repo/database db:push

# Start development
pnpm dev

Required Environment Variables

Create .env files in each app directory:

apps/web/.env:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_WEB_URL=http://localhost:3001
NEXT_PUBLIC_POSTHOG_KEY=phc_...

apps/app/.env:

NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_POSTHOG_KEY=phc_...

apps/api/.env:

DATABASE_URL=postgresql://...
CLERK_SECRET_KEY=sk_test_...
CLERK_WEBHOOK_SECRET=whsec_...
POLAR_ACCESS_TOKEN=polar_...
POLAR_WEBHOOK_SECRET=whsec_...
RESEND_TOKEN=re_...

NEXT_PUBLIC_APP_URL=http://localhost:3000
NEXT_PUBLIC_WEB_URL=http://localhost:3001

See individual .env.example files for complete lists.

Architecture

Apps

apps/
β”œβ”€β”€ web/           # Marketing site (port 3001)
β”‚   β”œβ”€β”€ /          # Homepage
β”‚   β”œβ”€β”€ /contact   # Contact form
β”‚   β”œβ”€β”€ /pricing   # Pricing page
β”‚   └── /blog      # Blog with CMS integration
β”œβ”€β”€ app/           # Main application (port 3000)
β”‚   β”œβ”€β”€ /sign-in   # Authentication
β”‚   β”œβ”€β”€ /sign-up
β”‚   └── /dashboard # Main app dashboard
β”œβ”€β”€ api/           # API server (port 3002)
β”‚   └── /webhooks  # Payment webhooks, auth callbacks
β”œβ”€β”€ docs/          # Documentation site
β”œβ”€β”€ email/         # Email preview server
└── storybook/     # Component library

All apps are independently deployable.

Packages

packages/
β”œβ”€β”€ auth/           # Clerk configuration
β”œβ”€β”€ database/       # Drizzle ORM, schema, migrations
β”œβ”€β”€ design-system/  # Base UI components, Tailwind config
β”œβ”€β”€ payments/       # Polar.sh integration
β”œβ”€β”€ analytics/      # PostHog client/server
β”œβ”€β”€ observability/  # Error handling, logging
β”œβ”€β”€ security/       # Security headers configuration
β”œβ”€β”€ cms/            # BaseHub integration
β”œβ”€β”€ email/          # React Email templates
β”œβ”€β”€ ai/             # Vercel AI SDK utilities
β”œβ”€β”€ seo/            # Metadata, sitemaps, JSON-LD
└── typescript-config/  # Shared TypeScript settings

Key Decisions

Flat URLs

Clean URL structure without locale prefixes. /contact instead of /en/contact. Simpler routing, faster builds, no configuration needed.

Consolidated Observability

One tool instead of three:

  • PostHog for analytics, session replay, and error tracking
  • No Sentry (replaced by PostHog error tracking)
  • No Logtail (Vercel logs + PostHog capture are sufficient)

Modern Database Layer

Drizzle ORM instead of Prisma:

  • Better query performance
  • SQL-like syntax (you write actual SQL)
  • Smaller bundle size
  • Edge runtime compatible

Modern Payments

Polar.sh for payments:

  • Better developer experience
  • Modern TypeScript SDK
  • Webhook handling included
  • Perfect for SaaS subscriptions

Modern UI

Base UI instead of Radix:

  • shadcn's next-generation component library
  • Better accessibility
  • No asChild prop complexity
  • Cleaner composition patterns

Database

Drizzle ORM with Neon PostgreSQL:

// packages/database/src/schema.ts
import { pgTable, serial, varchar } from "drizzle-orm/pg-core";

export const pages = pgTable("pages", {
  id: serial("id").primaryKey(),
  name: varchar("name", { length: 255 }).notNull(),
});

Run migrations:

pnpm --filter @repo/database db:generate  # Generate migration files
pnpm --filter @repo/database db:push     # Push to database
pnpm --filter @repo/database db:studio     # Open Drizzle Studio

Components

Base UI components via shadcn CLI:

# Add a component
npx shadcn@latest add button -c packages/design-system

# Use in your app
import { Button } from "@repo/design-system/components/ui/button";

Composition pattern (no asChild):

// βœ… Correct
<Link href="/contact">
  <Button>Contact</Button>
</Link>

// ❌ Old pattern (doesn't work with Base UI)
<Button asChild>
  <Link href="/contact">Contact</Link>
</Button>

Development

Commands

# Type check all packages
pnpm typecheck

# Run tests
pnpm test

# Build all apps
pnpm build

# Lint and format
pnpm check
pnpm fix

# Update dependencies
pnpm bump-deps

# Update all shadcn components
pnpm bump-ui

Database Changes

After modifying schema:

  1. Edit packages/database/src/schema.ts
  2. Run pnpm --filter @repo/database db:generate
  3. Run pnpm --filter @repo/database db:push

Adding a New App

  1. Create directory in apps/
  2. Add package.json with dependencies
  3. Create next.config.ts
  4. Add to turbo.json pipeline if needed

Deployment

Vercel (Recommended)

  1. Connect your GitHub repository to Vercel
  2. Set environment variables in Vercel dashboard
  3. Deploy

The monorepo is configured to deploy all apps independently via Turborepo.

Environment Variables by App

Each app needs specific environment variables:

  • Web: NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY, NEXT_PUBLIC_POSTHOG_KEY, etc.
  • App: All Clerk variables, PostHog key
  • API: Database URL, all service API keys (Polar, Resend, etc.)

Inspired By

Built on lessons learned from next-ship, with simplifications for solo founders:

  • Removed complex routing patterns
  • Consolidated observability tools
  • Updated to latest stack (Drizzle, Base UI, Polar.sh)
  • Flattened URL structure
  • Simplified codebase

License

MIT

About

lightweight, production-ready turborepo template

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 80.8%
  • Python 13.1%
  • Shell 3.9%
  • CSS 1.3%
  • JavaScript 0.7%
  • HTML 0.1%
  • Handlebars 0.1%