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 apphttp://localhost:3000/docs-> Proxied to docs apphttp://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_SECRETandDATABASE_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