Customize ShipFast for Your SaaS Idea 2026
TL;DR
ShipFast is designed to be modified, not extended. The source is yours — clone it, customize it, own it. The most common customizations are: adding teams/organizations, swapping the email provider, changing pricing structure, and adding a blog. This guide covers the 5 most requested ShipFast customizations with actual code.
Why ShipFast is Worth Customizing
ShipFast's appeal is in its scope: auth, billing, email, landing page, and dashboard all wired together and battle-tested by thousands of founders. Rather than building these from primitives, you inherit a working system and customize from there.
The design philosophy is opinionated-but-transparent. Marc (ShipFast's creator) made specific choices — DaisyUI for components, MongoDB or Supabase for data, NextAuth for auth — but every choice is in code you own. Nothing is abstracted behind a black box.
This means customization is straightforward: you change what you disagree with, delete what you don't need, and add what's missing. There's no framework extension API to learn. You modify source files directly.
The most common ShipFast customizations in order of frequency:
- Color scheme / branding — every new app looks like ShipFast until you change this
- Multiple pricing tiers — ShipFast ships with one plan; most products need two or three
- Team/organization support — ShipFast is user-centric; adding multi-tenancy requires new models
- Auth provider swap — switching from NextAuth to Clerk, or adding OAuth providers
- Email provider swap — Resend is the 2026 standard; ShipFast may default to Mailgun
Each of these is a 0.5–3 day change depending on how deep it goes.
Customization 1: Changing the Color Scheme
ShipFast uses Tailwind CSS with DaisyUI. Brand customization starts here. Until you change the colors, every ShipFast app looks identical.
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
// Override the default brand colors
primary: '#6366f1', // Your primary color
'primary-focus': '#4f46e5',
'primary-content': '#ffffff',
},
},
},
plugins: [
require('daisyui'),
],
daisyui: {
themes: [
{
light: {
...require('daisyui/src/theming/themes')['light'],
primary: '#6366f1',
'primary-focus': '#4f46e5',
},
dark: {
...require('daisyui/src/theming/themes')['dark'],
primary: '#818cf8',
'primary-focus': '#6366f1',
},
},
],
},
};
Beyond colors, update the following:
- Replace the logo in
public/andcomponents/logo.tsx - Update the favicon in
public/favicon.icoandapp/layout.tsxmetadata - Change the product name across
config.tsandapp/layout.tsx - Update
config.tswith your domain, product name, and social links
Time budget: Half a day for full brand customization including logo.
Customization 2: Adding Multiple Pricing Tiers
ShipFast ships with a single pricing tier example. Most products need at least two tiers (free + paid, starter + pro) or three (starter + pro + enterprise).
// config.ts — add multiple plans
export const config = {
// ... other config
stripe: {
plans: [
{
name: 'Starter',
description: 'For individuals',
price: 9,
priceId: process.env.STRIPE_STARTER_PRICE_ID!,
features: ['5 projects', '1 user', 'Email support'],
isFeatured: false,
},
{
name: 'Pro',
description: 'For small teams',
price: 29,
priceId: process.env.STRIPE_PRO_PRICE_ID!,
features: ['Unlimited projects', '5 users', 'Priority support'],
isFeatured: true, // Highlights this plan
},
{
name: 'Enterprise',
description: 'For larger organizations',
price: 99,
priceId: process.env.STRIPE_ENTERPRISE_PRICE_ID!,
features: ['Unlimited everything', 'Custom SSO', 'SLA'],
isFeatured: false,
},
],
},
};
// app/api/stripe/create-checkout/route.ts — handle plan selection
export async function POST(req: Request) {
const { priceId } = await req.json();
const session = await getServerSession(authOptions);
// Validate priceId is one of our valid plans
const validPriceIds = config.stripe.plans.map(p => p.priceId);
if (!validPriceIds.includes(priceId)) {
return Response.json({ error: 'Invalid plan' }, { status: 400 });
}
// Create checkout session with the specified price
const checkoutSession = await stripe.checkout.sessions.create({
mode: 'subscription',
line_items: [{ price: priceId, quantity: 1 }],
success_url: `${config.url}/dashboard?success=true`,
cancel_url: `${config.url}/pricing`,
customer_email: session!.user!.email!,
metadata: { userId: session!.user!.id },
});
return Response.json({ url: checkoutSession.url });
}
After changing the plans array, update your pricing page component to render multiple plan cards from config.stripe.plans. Also update your Stripe dashboard to create the matching products and price IDs.
Time budget: Half a day to configure and test.
Customization 3: Adding Team/Organization Support
ShipFast's data model is user-centric — each user has their own resources. Adding multi-tenancy (teams, workspaces, organizations) requires adding new Prisma models and threading the organization context through your app.
This is a significant change. Plan for 3–5 days if you need full multi-tenancy.
// prisma/schema.prisma — add organization models
model Organization {
id String @id @default(cuid())
name String
slug String @unique
createdAt DateTime @default(now())
members OrganizationMember[]
subscription Subscription?
}
model OrganizationMember {
id String @id @default(cuid())
organizationId String
userId String
role String @default("member") // "owner" | "admin" | "member"
createdAt DateTime @default(now())
organization Organization @relation(fields: [organizationId], references: [id])
user User @relation(fields: [userId], references: [id])
@@unique([organizationId, userId])
}
// lib/organization.ts
export async function createOrganization(userId: string, name: string) {
const slug = slugify(name) + '-' + nanoid(6);
return prisma.organization.create({
data: {
name,
slug,
members: {
create: {
userId,
role: 'owner',
},
},
},
});
}
export async function getUserOrganizations(userId: string) {
return prisma.organizationMember.findMany({
where: { userId },
include: { organization: true },
orderBy: { createdAt: 'asc' },
});
}
Once you add organizations, every data access in your app needs to scope queries by organizationId. This is the significant part of the migration — it's not just schema changes, it's updating every query and API route.
Alternative: If you need organizations quickly without the full implementation effort, consider switching from ShipFast to Makerkit or Supastarter, which include team management out of the box. The tradeoff is restarting on a different codebase versus the migration effort.
Time budget: 3–5 days for full multi-tenancy implementation.
Customization 4: Swapping NextAuth for Clerk
Clerk provides hosted auth UI, organization management, multi-factor authentication, and a better developer experience for organizations. If your product needs any of these features, swapping NextAuth for Clerk early (before you have users) is straightforward.
// app/layout.tsx — wrap with ClerkProvider
import { ClerkProvider } from '@clerk/nextjs';
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<ClerkProvider>
<html lang="en">
<body>{children}</body>
</html>
</ClerkProvider>
);
}
// middleware.ts — protect routes
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server';
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)']);
export default clerkMiddleware((auth, req) => {
if (isProtectedRoute(req)) auth().protect();
});
// Replace session checks throughout the app
// Before (NextAuth): const session = await getServerSession(authOptions);
// After (Clerk): const { userId } = await auth();
This replacement touches every API route and server component that reads the session. The grep footprint is large — budget 2–3 days for a thorough migration including testing.
When to keep NextAuth: If your auth requirements are simple (email/password + a few OAuth providers), NextAuth v5 is less costly and has no per-MAU pricing. Clerk starts adding cost above 10,000 MAUs ($25+/month at 10K).
Time budget: 2–3 days.
Customization 5: Replacing Mailgun with Resend
Resend has become the standard transactional email provider for Next.js developers in 2026. It supports React Email templates natively, has better developer experience than Mailgun, and the free tier is generous (3,000 emails/month).
// lib/email.ts — replace Mailgun with Resend
import { Resend } from 'resend';
const resend = new Resend(process.env.RESEND_API_KEY);
export async function sendWelcomeEmail(email: string, name: string) {
return resend.emails.send({
from: 'welcome@yoursaas.com',
to: email,
subject: 'Welcome to YourSaaS!',
react: <WelcomeEmailTemplate name={name} />,
// ^ Resend supports React Email templates natively
});
}
// emails/WelcomeEmailTemplate.tsx — using React Email
import {
Body, Container, Head, Heading, Html, Link, Preview, Text,
} from '@react-email/components';
export function WelcomeEmailTemplate({ name }: { name: string }) {
return (
<Html>
<Head />
<Preview>Welcome to YourSaaS</Preview>
<Body style={{ backgroundColor: '#ffffff', fontFamily: 'sans-serif' }}>
<Container>
<Heading>Welcome, {name}!</Heading>
<Text>Thanks for signing up...</Text>
<Link href="https://yoursaas.com/dashboard">Get started →</Link>
</Container>
</Body>
</Html>
);
}
React Email (the template library) integrates with Resend but also works with Nodemailer, Postmark, and others. Build your templates with react-email and you can switch email providers without rewriting templates.
Time budget: Half a day to swap the provider and update templates.
Keeping ShipFast Updated
After customizing, you lose easy access to upstream ShipFast updates (security fixes, dependency updates, new optional features). A few practices help:
# Add ShipFast's updates repo as a remote (if they provide one)
git remote add upstream <shipfast-updates-url>
# Check what changed in a specific file
git diff HEAD upstream/main -- lib/stripe.ts
# Apply only the security-related changes
git log upstream/main --oneline --grep="security"
git cherry-pick <commit-hash>
In practice, most ShipFast customizations don't conflict with boilerplate updates. Updates are typically dependency bumps, bug fixes, and new optional features you can selectively cherry-pick.
The exception: major auth library updates (NextAuth v4 → v5) or Stripe API version changes. For these, follow the official migration guides rather than cherry-picking.
Extending the Data Model
ShipFast's default data model is minimal by design: User, Session (auth), and subscription-related fields. Every product needs to add its own domain models on top.
The principle for extending ShipFast's Prisma schema: add new models rather than modifying User extensively. Relate your domain models to User via a foreign key, and keep auth-related fields on the User model clean.
// Good: separate domain models related to User
model Project {
id String @id @default(cuid())
userId String
user User @relation(fields: [userId], references: [id])
name String
description String?
settings Json @default("{}")
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
@@index([userId])
}
// Also good: extending User with a separate profile table
model UserProfile {
userId String @id
user User @relation(fields: [userId], references: [id])
bio String?
company String?
website String?
timezone String @default("UTC")
}
Resist the temptation to add product-specific fields directly to the User model. Keeping User clean means auth logic stays isolated from product logic, and you can upgrade ShipFast's auth layer more easily when new versions release.
Testing Your Customizations
ShipFast doesn't ship with a test suite — it's designed to ship fast, not as a tested framework. When you customize significantly, you're taking responsibility for quality assurance.
The minimal testing approach for ShipFast customizations:
Critical path tests: Write Playwright or Cypress e2e tests for the flows that generate revenue — signup, checkout, billing management. These are the flows you absolutely cannot have broken in production.
API route tests: For any API route that handles money or data mutations, write integration tests using Vitest + supertest. Mock Stripe and external services; hit a test database.
Type checking as a test: TypeScript compilation is your first test suite. Keep tsc --noEmit passing in CI. ShipFast's TypeScript config is reasonable — don't loosen it to suppress errors; fix them.
A single e2e test that covers "user signs up → subscribes → sees dashboard" catches the most common production-breaking regressions. Add it before you launch and run it in your deployment pipeline.
Customization Prioritization
When starting with ShipFast, do these in order:
- Branding (Day 1) — colors, logo, product name, domain. Psychological benefit of not looking like every other ShipFast app.
- Auth flow (Day 1) — decide if you're keeping NextAuth or moving to Clerk. Easier to decide early.
- Pricing tiers (Day 2) — set up the Stripe products and update config.
- Data model (Day 2–5) — add your core product models. Multi-tenancy if needed.
- Email (Day 3) — switch to Resend and build your email templates.
- Blog/SEO (Day 3–4) — if content marketing is part of your go-to-market.
Adding Feature Flags
Feature flags let you ship code to production that's disabled for most users, enabling gradual rollouts, A/B tests, and safe deployment of risky changes. ShipFast doesn't include feature flags, but they're straightforward to add.
For simple cases, environment-variable-controlled flags are sufficient — process.env.ENABLE_FEATURE_X === 'true'. These require a deployment to change and can't be targeted to specific users, but they work for "dark launch" scenarios where you want to ship code without enabling it.
For user-targeted flags (show feature to 10% of users, enable for beta testers only), use a dedicated service:
// lib/flags.ts — using PostHog's feature flags (free tier available)
import { PostHog } from 'posthog-node';
const posthog = new PostHog(process.env.POSTHOG_API_KEY!);
export async function isFeatureEnabled(
flagKey: string,
userId: string
): Promise<boolean> {
const enabled = await posthog.isFeatureEnabled(flagKey, userId);
return enabled ?? false;
}
// In a Server Component:
export default async function Dashboard() {
const session = await auth();
const newDashboardEnabled = await isFeatureEnabled('new-dashboard', session!.user.id);
return newDashboardEnabled ? <NewDashboard /> : <OldDashboard />;
}
PostHog is the standard choice in 2026 for ShipFast teams — it includes analytics, session recording, and feature flags in one tool, with a free tier up to 1M events/month.
Related Resources
To compare ShipFast against alternatives with teams built-in, see the Makerkit vs ShipFast vs Supastarter comparison. For adding a blog to ShipFast specifically, how to add blog and SEO to your SaaS boilerplate covers the MDX setup. If you're deciding between ShipFast and T3 Stack, the T3 Stack vs ShipFast comparison walks through the tradeoffs.
Deploying Your Customized ShipFast
ShipFast is designed for Vercel deployment, and the default configuration works without changes. A few things to verify before your first production deploy:
Environment variables: ShipFast requires NEXTAUTH_URL, NEXTAUTH_SECRET, DATABASE_URL (MongoDB Atlas or Supabase connection string), and STRIPE_SECRET_KEY. Add each to your Vercel project settings. NEXTAUTH_SECRET must be a random 32+ character string — generate with openssl rand -base64 32.
Database connection pooling: If you're on Supabase's Postgres, use the pooler connection string (the one with :6543 port) rather than the direct connection string for serverless environments. Vercel's serverless functions open a new database connection per request without pooling, and direct connections exhaust Supabase's connection limit quickly.
Stripe webhook signature verification: ShipFast's Stripe webhook handler verifies the signature using STRIPE_WEBHOOK_SECRET. Get this from your Stripe dashboard → Webhooks → your endpoint. Without this, webhook handlers reject all events.
After deploy, verify: user signup → email verification → Stripe checkout → dashboard loads → webhook fires and subscription updates in DB. This path is critical and worth testing end-to-end in production before promoting to users.
Methodology
Customization steps verified against ShipFast v2 (App Router version) as of Q1 2026. Clerk pricing from the official pricing page. Resend API usage from official documentation.
Compare ShipFast with other customizable boilerplates on StarterPick.
Check out this boilerplate
View ShipFaston StarterPick →