Skip to main content

Guide

Fork vs Wrap: Extending Boilerplates in 2026

Fork vs wrap for SaaS boilerplates: git upstream strategy, override patterns, and which starters support true wrapping via npm packages. Avoid update hell.

StarterPick Team

TL;DR

Almost all boilerplate usage should be the "fork" approach — clone and own the code. True "wrapping" (using the boilerplate as a package dependency) is rare and only works for specific boilerplate architectures. The real question isn't fork vs wrap, but: how do you stay in sync with boilerplate updates without losing your customizations?

Key Takeaways

  • Fork (clone + modify): 95% of boilerplate usage
  • Wrap (npm package dependency): Only works for specifically designed boilerplates (Makerkit)
  • Rebase strategy: Keep a upstream remote to pull boilerplate updates
  • Branch strategy: Keep customizations on separate branches
  • The real risk: Not staying updated — security patches missed

Fork: The Default Approach

Most boilerplates are designed to be cloned and modified:

# Standard fork approach
git clone https://github.com/example/shipfast my-saas
cd my-saas
rm -rf .git           # Remove original git history
git init
git add .
git commit -m "Initial commit from ShipFast boilerplate"

From this point, your codebase is yours. You own it, modify it, and maintain it. No dependency on the original repository.

Advantages:

  • Full control over every line of code
  • No version conflicts
  • Can make any modification without restriction

Disadvantages:

  • You must manually apply boilerplate updates
  • Security patches require manual monitoring
  • If the boilerplate fixes a bug, you apply it yourself

Staying Updated with the Fork Approach

The key technique: keep the upstream as a separate remote

# Setup: keep track of the boilerplate's original repository
git remote add upstream https://github.com/example/shipfast.git
git fetch upstream

# When boilerplate releases an update:
git fetch upstream
git log upstream/main --oneline -5  # See what changed

# Cherry-pick specific commits you want
git cherry-pick abc1234  # Just the security patch

# Or merge selectively
git diff main upstream/main -- lib/stripe.ts  # See what changed in Stripe integration

This lets you pick and choose boilerplate updates without breaking your customizations.


Wrap: The Package Dependency Approach

A few boilerplates (notably Makerkit) are designed to work as package dependencies:

// Makerkit's plugin architecture enables true wrapping
// packages.json
{
  "dependencies": {
    "@makerkit/auth": "workspace:*",
    "@makerkit/billing": "workspace:*",
    "@makerkit/ui": "workspace:*"
  }
}

// You import features as packages — don't modify the source
import { AuthProvider } from '@makerkit/auth';
import { BillingProvider } from '@makerkit/billing';

// Your customizations live in YOUR code, not the boilerplate packages
export function AppLayout({ children }) {
  return (
    <AuthProvider config={yourAuthConfig}>
      <BillingProvider plans={yourPlans}>
        <YourCustomHeader />
        {children}
        <YourCustomFooter />
      </BillingProvider>
    </AuthProvider>
  );
}

When Makerkit releases an update: npm update @makerkit/auth — like any npm package update.

This only works when the boilerplate is designed for it. ShipFast, T3 Stack, and most others can't be used this way.


Customization Strategies Within the Fork

Once you've forked, you have several strategies for organizing customizations:

Strategy 1: Direct Modification (Most Common)

# Just modify files directly
# lib/stripe.ts — change the webhook handler
# components/auth/SignIn.tsx — customize the sign-in form

Simple, but makes boilerplate updates harder (more merge conflicts).

Strategy 2: Override Files

// Keep boilerplate code unchanged
// lib/stripe.original.ts — don't touch this

// Create your version that extends the original
// lib/stripe.ts — your customized version
import { originalWebhookHandler } from './stripe.original';

export async function webhookHandler(req: Request) {
  // Call original logic
  const result = await originalWebhookHandler(req);

  // Add your custom logic after
  await myCustomAnalytics.trackEvent('stripe_webhook', result);

  return result;
}

More verbose but makes your customizations explicit and easier to compare against updates.

Strategy 3: Feature Branches

# Keep the boilerplate on main
git checkout main  # = clean boilerplate

# Your customizations on a feature branch
git checkout -b product/saas-customizations
# All your changes here

# When updating:
git fetch upstream
git rebase upstream/main  # Rebase your customizations on latest boilerplate

Most disciplined approach — but requires good git hygiene.


The Anti-Pattern: Monolithic Customization

# Anti-pattern: Large uncommitted changes everywhere
git status
# 47 files modified, 3 files untracked

# When boilerplate releases update:
git pull upstream main
# 15 merge conflicts in 15 different files
# 4 hours resolving conflicts

If your customizations are scattered throughout the codebase without organization, updates become painful. The solution: commit frequently, in small chunks, with clear messages.


Practical Advice by Boilerplate

BoilerplateBest StrategyUpdate Method
ShipFastFork + direct modifyCherry-pick patches
T3 StackFork + extendRegenerate + merge
MakerkitFork (monorepo) OR wrap (packages)Package updates
SupastarterFork + service layer extensionsCherry-pick
Epic StackFork + extend modelsRebase

The Real Decision

The fork vs wrap question is mostly academic for most developers. The real decisions are:

  1. How often will I apply boilerplate updates? (Monthly? Security patches only?)
  2. Will I customize core infrastructure (auth, billing)? (High vs low customization)
  3. How many developers will work on the codebase? (Git strategy matters more for teams)

For solo founders: fork, modify freely, check for security patches monthly. For teams: fork, keep customizations organized, use git branches to separate boilerplate from product code.



The Security Patch Problem

The biggest practical downside of forking a boilerplate is missing security updates. When a CVE is discovered in NextAuth, Prisma, or a Stripe SDK dependency, the boilerplate maintainer patches it quickly. You won't know unless you're watching the upstream repository.

Build a routine around security maintenance:

# Monthly security check — 15 minutes
# Step 1: Check for npm vulnerabilities
npm audit

# Step 2: Check upstream boilerplate changelog
git fetch upstream
git log upstream/main --oneline --since="1 month ago"

# Step 3: Apply security-only patches
git log upstream/main --oneline --grep="security" --grep="CVE" --all-match
# Cherry-pick the relevant commits

# Step 4: Update your lock file
npm update && npm audit fix

Set a calendar reminder monthly. Security patches from boilerplate maintainers are usually small, targeted commits that apply cleanly even with significant customization.


When to Completely Abandon the Upstream

After 12-18 months of active development, the connection to the original boilerplate becomes largely academic. Your codebase has diverged significantly — different auth patterns, different data models, different UI components. Trying to merge upstream updates causes more conflicts than it resolves.

Healthy signals for "you've outgrown the upstream":

  • Your diff from upstream is 10,000+ lines
  • You've replaced the auth, billing, or database layer
  • Upstream updates now consistently conflict with your customizations
  • Your product requirements have moved well beyond what the boilerplate addressed

At this point, stop tracking the upstream and maintain your own internal standards for dependencies and security. The boilerplate has done its job — it got you to a production codebase faster than starting from scratch. Now you own the full stack.


Key Takeaways

  • Fork (clone and own) is the correct approach for 95%+ of boilerplate usage — most boilerplates are not designed to be npm packages
  • Keep a git upstream remote to track security patches and significant bug fixes; cherry-pick rather than merging broadly
  • Organize customizations with clear commit messages and feature branches — this makes boilerplate updates apply more cleanly
  • Makerkit is the primary exception: its monorepo package architecture supports true wrapping via npm update
  • Security patches are the most important upstream changes to monitor; build a monthly review habit
  • After 12-18 months of active development, you'll likely have outgrown the need to track upstream at all
  • The most valuable boilerplate "updates" to cherry-pick are usually small: dependency bumps for security patches, small bug fixes in webhook handling or auth edge cases, and new Next.js compatibility patches that don't change the application structure
  • Teams that maintain a staging environment before production can apply boilerplate updates to staging first and verify nothing breaks before rolling out to production users
  • The discipline of maintaining a clean separation between boilerplate infrastructure code and your product code pays off at funding time: investors and technical due diligence reviewers appreciate codebases where it's clear what's commodity infrastructure and what's your proprietary product logic
  • Fork strategy recommended for 95% of teams; the wrap strategy via npm packages only works for Makerkit's specific architecture — don't spend time trying to make it work for boilerplates that weren't designed that way
  • When evaluating a new boilerplate update before applying it, read the changelog and diff the changed files against your own — most boilerplate updates touch 3-5 files, making targeted cherry-picks straightforward

Evaluating Update-Friendliness Before Purchase

Not all forks are created equal. Before committing to a boilerplate, assess how difficult future updates will be by looking at the codebase structure:

Boilerplates with well-organized, modular code make cherry-picking updates easier. If the auth implementation lives in lib/auth/ with clear boundaries, a security patch to the auth layer applies cleanly. If auth logic is scattered through ten different files, applying targeted patches is much harder.

Look for separation of concern between infrastructure code (auth, billing, email) and application code (your product features). The cleanest boilerplates make this separation explicit — Makerkit's package architecture and Epic Stack's module boundaries are good examples. The messier boilerplates intertwine infrastructure and product code in ways that make both harder to maintain independently.

Ask what the boilerplate's dependency update policy is. Some authors pin all dependencies to specific versions and manually audit updates. Others use Dependabot or Renovate to open automated PRs. Either approach is fine, but knowing which pattern the boilerplate follows helps you understand the update work you'll inherit.

Technical Due Diligence at Funding Time

Several due diligence reviewers have noted that codebases built on active, maintained boilerplates are easier to evaluate than codebases built from scratch. The patterns are familiar — any engineer who has worked with T3 Stack or ShipFast can navigate a codebase built on those foundations without documentation. This accelerates technical due diligence for seed and Series A rounds where the engineering team does a code review.

The inverse is also true: a boilerplate that's been abandoned mid-development, with security patches three versions behind, raises flags in due diligence. Investors aren't just evaluating current functionality — they're evaluating the maintenance burden the engineering team will inherit. A boilerplate with documented update procedures and active upstream maintenance communicates that the founding team thinks about long-term maintainability, not just shipping speed.

For teams approaching fundraising, it's worth doing a dependency audit with npm audit and checking that all boilerplate dependencies are within one minor version of current. A clean audit report is a small but concrete signal of engineering care. It's also worth documenting which parts of the codebase are boilerplate-derived and which are proprietary product logic — this transparency accelerates the review process and demonstrates that the team understands its own architecture.

The right choice between these options depends on your specific requirements, team expertise, and production constraints. Test each option with a realistic subset of your use case before committing — what works for one team's workflow may not fit another's.


Find boilerplates designed for easy customization on StarterPick.

See our boilerplate trap and technical debt guide for the long-term perspective on boilerplate customization.

Browse best SaaS boilerplates for 2026 for options with the best update and maintenance track records.

Read the guide to migrating between SaaS boilerplates for when the fork strategy is no longer working.

Check out this starter

View ShipFaston StarterPick →

The SaaS Boilerplate Matrix (Free PDF)

20+ SaaS starters compared: pricing, tech stack, auth, payments, and what you actually ship with. Updated monthly. Used by 150+ founders.

Join 150+ SaaS founders. Unsubscribe in one click.