Customize ShipFast for Your Specific 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.
Customization 1: Changing the Color Scheme
ShipFast uses Tailwind CSS with DaisyUI. Brand customization starts here:
// 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',
},
},
],
},
};
Customization 2: Adding Multiple Pricing Tiers
ShipFast comes with one plan by default. Adding multiple tiers:
// 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 });
}
Customization 3: Adding Team/Organization Support
ShipFast doesn't include multi-tenancy. Adding basic teams:
// 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' },
});
}
Customization 4: Swapping NextAuth for Clerk
If you need Clerk's prebuilt UI and organization features:
// 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();
Warning: This replacement touches most API routes. Budget 2-3 days.
Customization 5: Replacing Mailgun with Resend
ShipFast historically used Mailgun. Switching to Resend (more developer-friendly):
// 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>
);
}
Staying Updated
After customizing, keep the upstream available:
# 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>
Most ShipFast customizations don't conflict with boilerplate updates, which are usually: dependency updates, bug fixes, and new optional features you can ignore.
Compare ShipFast with other customizable boilerplates on StarterPick.
Check out this boilerplate
View ShipFast on StarterPick →