Multi-Zone Architecture

Multi-zone lets you deploy separate Shipkit installations under one domain. Each zone is a full app customized for its purpose (docs, blog, UI library, tools) while sharing design and auth.

shipkit.io/          -> Main app (marketing, dashboard)
shipkit.io/docs/*    -> Documentation app
shipkit.io/blog/*    -> Blog app
shipkit.io/ui/*      -> Component library
shipkit.io/tools/*   -> Developer tools

Deployment Options

Next.js Multi-Zone (Recommended)

Soft navigation within zones, optimal performance. The main app uses rewrites in next.config.ts to proxy requests to zone apps.

Vercel Proxy Project

Simplest setup. A standalone Vercel project with rewrites routes traffic to each zone. Hard navigation between all routes.

Incremental Approach

Add rewrites to your existing config and deploy zones one at a time. Start with docs or blog.

Setup

1. Configure Rewrites on Main App

Add to your existing next.config.ts:

async rewrites() {
  const multiZoneRewrites = [];

  if (process.env.DOCS_DOMAIN) {
    multiZoneRewrites.push(
      { source: '/docs', destination: `${process.env.DOCS_DOMAIN}/docs` },
      { source: '/docs/:path*', destination: `${process.env.DOCS_DOMAIN}/docs/:path*` },
      { source: '/docs-static/:path*', destination: `${process.env.DOCS_DOMAIN}/docs-static/:path*` }
    );
  }

  if (process.env.BLOG_DOMAIN) {
    multiZoneRewrites.push(
      { source: '/blog', destination: `${process.env.BLOG_DOMAIN}/blog` },
      { source: '/blog/:path*', destination: `${process.env.BLOG_DOMAIN}/blog/:path*` },
      { source: '/blog-static/:path*', destination: `${process.env.BLOG_DOMAIN}/blog-static/:path*` }
    );
  }

  // Same pattern for /ui and /tools
  return multiZoneRewrites;
}

2. Create Zone Apps

Clone Shipkit for each zone:

git clone https://github.com/lacymorrow/shipkit.git shipkit-docs
cd shipkit-docs && bun install --frozen-lockfile

3. Configure Zone next.config.ts

Each zone needs basePath and assetPrefix:

const nextConfig: NextConfig = {
  basePath: "/docs",           // or /blog, /ui, /tools
  assetPrefix: "/docs-static", // unique per zone

  async rewrites() {
    return {
      beforeFiles: [
        {
          source: "/docs-static/_next/:path+",
          destination: "/_next/:path+",
        },
      ],
    };
  },

  // Rest of Shipkit configuration
};

4. Environment Variables

Main app .env.local:

# Development
DOCS_DOMAIN=http://localhost:3001
BLOG_DOMAIN=http://localhost:3002
UI_DOMAIN=http://localhost:3003
TOOLS_DOMAIN=http://localhost:3004

Production (Vercel dashboard):

DOCS_DOMAIN=https://docs-shipkit.vercel.app
BLOG_DOMAIN=https://blog-shipkit.vercel.app
UI_DOMAIN=https://ui-shipkit.vercel.app
TOOLS_DOMAIN=https://tools-shipkit.vercel.app

Each zone app gets its own .env.local with zone-specific NEXT_PUBLIC_APP_URL, DATABASE_URL, etc.

Local Development

Start each app on different ports:

# Terminal 1 - Main app
bun dev

# Terminal 2 - Docs
cd ../shipkit-docs && bun dev -- --port 3001

# Terminal 3 - Blog
cd ../shipkit-blog && bun dev -- --port 3002

Test routes:

  • http://localhost:3000/ -> Main app
  • http://localhost:3000/docs -> Proxied to docs app
  • http://localhost:3000/blog -> Proxied to blog app

Cross-Zone Navigation

Use anchor tags (<a>) for links between zones (hard navigation). Use Next.js <Link> for navigation within a zone (soft navigation).

// Within a zone (soft navigation)
import Link from "next/link"
<Link href="/dashboard">Dashboard</Link>

// Between zones (hard navigation)
<a href="/docs/getting-started">Documentation</a>
<a href="/blog/latest">Blog</a>

Zone Customization

Each zone is a full Shipkit installation. Customize by:

  • Enabling/disabling features via env vars
  • Removing unnecessary routes and components
  • Adding zone-specific dependencies (e.g., Storybook for UI zone)
  • Sharing or separating databases

Considerations

  • SEO: Each zone should have proper meta tags and sitemap entries
  • Auth: Zones can share authentication if they share AUTH_SECRET and DATABASE_URL
  • Analytics: Ensure tracking works across all zones
  • Components: All zones share Shipkit's component library for consistent design
  • Bundle size: Each zone is independently optimized