next-ship
v0.4.4
Published
a lightweight, production-ready turborepo template
Readme
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 Stripe alternative with better DX | | 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
- Node.js 20+
- pnpm
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 devRequired 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:3001See 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 libraryAll 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 settingsKey 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 instead of Stripe:
- 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
asChildprop 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 StudioComponents
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-uiDatabase Changes
After modifying schema:
- Edit
packages/database/src/schema.ts - Run
pnpm --filter @repo/database db:generate - Run
pnpm --filter @repo/database db:push
Adding a New App
- Create directory in
apps/ - Add
package.jsonwith dependencies - Create
next.config.ts - Add to
turbo.jsonpipeline if needed
Deployment
Vercel (Recommended)
- Connect your GitHub repository to Vercel
- Set environment variables in Vercel dashboard
- 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
