Whitelabel Landing Pages by Domain: The Complete Blueprint
Build a landing platform that can be branded per customer, served on their subdomain or custom domain, and managed from a single admin console.
TL;DR
Store a per-domain configuration, route requests at the edge by host, and render the landing with a theme + content payload. Add domain verification, automatic TLS, and an admin UI that lets customers update their landing without code.
LogNroll Team
Platform
The Whitelabel Goal
You want a single website platform that can be branded and deployed per customer on their own subdomain or custom domain. Each tenant controls copy, colors, logo, and calls-to-action, while your team controls the template and infrastructure.
System Checklist
Create domain-aware landing
Render copy, theme, and CTAs using domain-based configuration.
Configure domain + TLS
Verify ownership, issue certificates, and attach to edge routing.
Admin config console
Give tenants a control panel to update branding and content.
Resolve requests
Detect tenant by host, fetch config, and render landing.
1) Create a Landing That Adapts to the Domain
The landing page should take a configuration payload and render brand, content, and CTA variations based on the request host. Store it as structured JSON so you can validate and version updates.
{
"domain": "acme.example.com",
"brand": {
"name": "Acme",
"logoUrl": "https://cdn.example.com/acme/logo.svg",
"primaryColor": "#4f46e5"
},
"hero": {
"headline": "Ship campaigns faster with Acme",
"subheadline": "A private analytics stack branded for your team.",
"ctaLabel": "Book a demo",
"ctaUrl": "https://acme.example.com/book"
},
"sections": ["benefits", "testimonials", "pricing"],
"tracking": {
"pixelId": "fb-123",
"analyticsKey": "lnr-tenant-001"
}
}Use safe defaults for missing fields and keep a fallback landing for unknown domains (so you do not show a broken page).
Next.js example: resolve the tenant by domain
In the App Router you can read the host header and load the right configuration before rendering. This example uses a server component to fetch a tenant config by domain and then renders the landing.
// app/(landing)/page.tsx
import { headers } from "next/headers"
import { getTenantConfig } from "@/lib/tenants"
import Landing from "@/components/landing/Landing"
export default async function LandingPage() {
const host = headers().get("host") ?? ""
const config = await getTenantConfig(host)
if (!config) {
return <Landing variant="default" />
}
return <Landing variant="tenant" config={config} />
}Next.js example: edge middleware routing
If you want to separate public marketing pages from tenant landings, use middleware to route traffic based on the host header and attach the tenant id as a header.
// middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
import { lookupTenantByHost } from "@/lib/tenants"
export async function middleware(req: NextRequest) {
const host = req.headers.get("host") ?? ""
const tenant = await lookupTenantByHost(host)
if (!tenant) return NextResponse.next()
const requestHeaders = new Headers(req.headers)
requestHeaders.set("x-tenant-id", tenant.id)
return NextResponse.next({ request: { headers: requestHeaders } })
}
2) Configure Domains and Certificates
Customers can use subdomains (easy) or full custom domains (needs verification). A common flow is: add domain, verify via DNS (TXT or CNAME), then issue TLS certificates automatically and attach them to your edge or load balancer.
Subdomain setup
Give each tenant a subdomain like tenant.lognroll.app. You only manage DNS once, and routing is purely by host header.
Custom domain setup
Verify ownership with DNS records, then issue a TLS certificate and store it in your edge provider for secure HTTPS delivery.
3) Create an Admin Page for Landing Configuration
Give tenants an admin page that edits their brand + content while keeping the core layout locked. Use a live preview so marketing teams can iterate without shipping code.
- Brand settings: logo, primary color, typography, favicon.
- Hero content: headline, subheadline, CTA label + link.
- Sections: toggle testimonials, pricing, integrations, FAQ.
- Tracking: analytics keys, pixels, and consent options.
4) Request Resolution Diagram
This flow shows how a landing request is resolved, which configuration is selected, and how the final page is rendered.
1. Request
Browser hits
acme.example.com
2. Edge Router
Reads
Host header
3. Config Lookup
Fetches
Tenant config
4. Render
Landing
Theme + content
function handleRequest(req) {
const host = req.headers["host"]
const tenant = lookupTenantByHost(host)
if (!tenant) return renderDefaultLanding()
const config = fetchLandingConfig(tenant.id)
return renderLanding(config)
}Prompt Set: Build a Whitelabel Service with Open-Source Tools
Use these prompts with your coding assistant to scaffold a basic whitelabel platform. Each prompt assumes a popular open-source stack and focuses on one subsystem at a time.
Operational Tips
Cache configs at the edge
Store tenant configs in a fast KV or edge cache so landing renders are quick.
Use versioned templates
When you update the base layout, keep version flags so tenants can opt in.
Protect admin access
Role-based access and audit logs prevent accidental brand or domain changes.
Wrap Up
Whitelabel landings scale when domain routing, TLS, and configuration live in one pipeline. Keep the landing flexible, the admin UI focused, and the routing path deterministic so every request resolves fast and safely.