Version 3 of the kit: - Radix UI replaced with Base UI (using the Shadcn UI patterns) - next-intl replaces react-i18next - enhanceAction deprecated; usage moved to next-safe-action - main layout now wrapped with [locale] path segment - Teams only mode - Layout updates - Zod v4 - Next.js 16.2 - Typescript 6 - All other dependencies updated - Removed deprecated Edge CSRF - Dynamic Github Action runner
211 lines
5.7 KiB
Plaintext
211 lines
5.7 KiB
Plaintext
---
|
|
status: "published"
|
|
label: "External Marketing Website"
|
|
title: "External Marketing Website in the Next.js Supabase Turbo Starter Kit"
|
|
description: "Configure Makerkit to redirect marketing pages to an external website built with Framer, Webflow, or WordPress."
|
|
order: 9
|
|
---
|
|
|
|
Redirect Makerkit's marketing pages to an external website by configuring the `proxy.ts` middleware. This lets you use Framer, Webflow, or WordPress for your marketing site while keeping Makerkit for your SaaS application.
|
|
|
|
{% sequence title="External Marketing Website Setup" description="Configure redirects to your external marketing site" %}
|
|
|
|
[Understand the architecture](#when-to-use-an-external-marketing-website)
|
|
|
|
[Configure the middleware](#configuring-the-middleware)
|
|
|
|
[Handle subpaths and assets](#handling-subpaths-and-assets)
|
|
|
|
[Verify the redirects](#verify-the-redirects)
|
|
|
|
{% /sequence %}
|
|
|
|
## When to Use an External Marketing Website
|
|
|
|
Use an external marketing website when:
|
|
|
|
- **Marketing team independence**: Your marketing team needs to update content without developer involvement
|
|
- **Design flexibility**: You want visual builders like Framer or Webflow for landing pages
|
|
- **Content management**: WordPress or a headless CMS better fits your content workflow
|
|
- **A/B testing**: Your marketing tools integrate better with external platforms
|
|
|
|
Keep marketing pages in Makerkit when:
|
|
|
|
- You want a unified codebase and deployment
|
|
- Your team is comfortable with React and Tailwind
|
|
- You need tight integration between marketing and app features
|
|
|
|
## Configuring the Middleware
|
|
|
|
{% alert type="default" title="Next.js 16+" %}
|
|
In Next.js 16+, Makerkit uses `proxy.ts` for middleware. Prior versions used `middleware.ts`.
|
|
{% /alert %}
|
|
|
|
Edit `apps/web/proxy.ts` to redirect marketing pages:
|
|
|
|
```typescript {% title="apps/web/proxy.ts" %}
|
|
import type { NextRequest } from 'next/server';
|
|
import { NextResponse } from 'next/server';
|
|
|
|
const EXTERNAL_MARKETING_URL = 'https://your-marketing-site.com';
|
|
|
|
const MARKETING_PAGES = [
|
|
'/',
|
|
'/pricing',
|
|
'/faq',
|
|
'/contact',
|
|
'/about',
|
|
'/blog',
|
|
'/privacy-policy',
|
|
'/terms-of-service',
|
|
'/cookie-policy',
|
|
];
|
|
|
|
export function proxy(req: NextRequest) {
|
|
if (isMarketingPage(req)) {
|
|
const redirectUrl = new URL(
|
|
req.nextUrl.pathname,
|
|
EXTERNAL_MARKETING_URL
|
|
);
|
|
|
|
// Preserve query parameters
|
|
redirectUrl.search = req.nextUrl.search;
|
|
|
|
return NextResponse.redirect(redirectUrl, { status: 301 });
|
|
}
|
|
|
|
// Continue with existing middleware logic
|
|
return NextResponse.next();
|
|
}
|
|
|
|
function isMarketingPage(req: NextRequest): boolean {
|
|
const pathname = req.nextUrl.pathname;
|
|
|
|
return MARKETING_PAGES.some((page) => {
|
|
if (page === '/') {
|
|
return pathname === '/';
|
|
}
|
|
return pathname === page || pathname.startsWith(`${page}/`);
|
|
});
|
|
}
|
|
```
|
|
|
|
### Configuration Options
|
|
|
|
| Option | Description |
|
|
|--------|-------------|
|
|
| `EXTERNAL_MARKETING_URL` | Your external marketing site's base URL |
|
|
| `MARKETING_PAGES` | Array of paths to redirect |
|
|
| Status code `301` | Permanent redirect (SEO-friendly) |
|
|
| Status code `302` | Temporary redirect (for testing) |
|
|
|
|
## Handling Subpaths and Assets
|
|
|
|
### Blog Posts with Dynamic Paths
|
|
|
|
If your blog uses dynamic paths like `/blog/post-slug`, handle them separately:
|
|
|
|
```typescript
|
|
const MARKETING_PAGES = [
|
|
// ... other pages
|
|
];
|
|
|
|
const MARKETING_PREFIXES = [
|
|
'/blog',
|
|
'/resources',
|
|
'/case-studies',
|
|
];
|
|
|
|
function isMarketingPage(req: NextRequest): boolean {
|
|
const pathname = req.nextUrl.pathname;
|
|
|
|
// Check exact matches
|
|
if (MARKETING_PAGES.includes(pathname)) {
|
|
return true;
|
|
}
|
|
|
|
// Check prefix matches
|
|
return MARKETING_PREFIXES.some((prefix) =>
|
|
pathname.startsWith(prefix)
|
|
);
|
|
}
|
|
```
|
|
|
|
### Excluding Application Routes
|
|
|
|
Keep certain routes in Makerkit even if they share a marketing prefix:
|
|
|
|
```typescript
|
|
const APP_ROUTES = [
|
|
'/blog/admin', // Blog admin panel stays in Makerkit
|
|
'/pricing/checkout', // Checkout flow stays in Makerkit
|
|
];
|
|
|
|
function isMarketingPage(req: NextRequest): boolean {
|
|
const pathname = req.nextUrl.pathname;
|
|
|
|
// Never redirect app routes
|
|
if (APP_ROUTES.some((route) => pathname.startsWith(route))) {
|
|
return false;
|
|
}
|
|
|
|
// ... rest of the logic
|
|
}
|
|
```
|
|
|
|
## Verify the Redirects
|
|
|
|
After configuring, verify redirects work correctly:
|
|
|
|
```bash
|
|
# Start the development server
|
|
pnpm run dev
|
|
|
|
# Test a redirect (should return 301)
|
|
curl -I http://localhost:3000/pricing
|
|
```
|
|
|
|
Expected output:
|
|
|
|
```
|
|
HTTP/1.1 301 Moved Permanently
|
|
Location: https://your-marketing-site.com/pricing
|
|
```
|
|
|
|
### Common Issues
|
|
|
|
**Redirect loops**: Ensure your external site doesn't redirect back to Makerkit.
|
|
|
|
**Missing query parameters**: The example code preserves query params. Verify UTM parameters pass through correctly.
|
|
|
|
**Asset requests**: Don't redirect asset paths like `/images/` or `/_next/`. The middleware should only match page routes.
|
|
|
|
## Environment-Based Configuration
|
|
|
|
Use environment variables for different environments:
|
|
|
|
```typescript {% title="apps/web/proxy.ts" %}
|
|
const EXTERNAL_MARKETING_URL = process.env.EXTERNAL_MARKETING_URL;
|
|
|
|
export function proxy(req: NextRequest) {
|
|
// Only redirect if external URL is configured
|
|
if (!EXTERNAL_MARKETING_URL) {
|
|
return NextResponse.next();
|
|
}
|
|
|
|
// ... redirect logic
|
|
}
|
|
```
|
|
|
|
```bash {% title=".env.production" %}
|
|
EXTERNAL_MARKETING_URL=https://your-marketing-site.com
|
|
```
|
|
|
|
This lets you keep marketing pages in Makerkit during development while redirecting in production.
|
|
|
|
## Related Resources
|
|
|
|
- [Marketing Pages](/docs/next-supabase-turbo/development/marketing-pages) for customizing built-in marketing pages
|
|
- [SEO Configuration](/docs/next-supabase-turbo/development/seo) for sitemap and meta tag setup
|
|
- [Legal Pages](/docs/next-supabase-turbo/development/legal-pages) for privacy policy and terms pages
|