import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' import { isDemoRequest } from '@encryptid/sdk/server/nextjs' /** * Middleware to handle subdomain-based space routing and protect /space routes. * * Subdomain routing: * - rfunds.online -> home/landing page * - www.rfunds.online -> home/landing page * - .rfunds.online -> rewrite to /s/ * * Auth protection: * - /space routes require auth (cookie or Bearer token) * - Demo spaces (ENCRYPTID_DEMO_SPACES env var) bypass auth * * Also handles localhost for development. */ export function middleware(request: NextRequest) { const url = request.nextUrl.clone() const hostname = request.headers.get('host') || '' const { pathname } = request.nextUrl // --- Subdomain routing --- let subdomain: string | null = null // Match production: .rfunds.online const match = hostname.match(/^([a-z0-9][a-z0-9-]*[a-z0-9]|[a-z0-9])\.\w+\.online/) if (match && match[1] !== 'www') { subdomain = match[1] } else if (hostname.includes('localhost')) { // Development: .localhost:port const parts = hostname.split('.localhost')[0].split('.') if (parts.length > 0 && parts[0] !== 'localhost') { subdomain = parts[parts.length - 1] } } // If we have a subdomain, rewrite root path to space page if (subdomain && subdomain.length > 0 && pathname === '/') { url.pathname = `/s/${subdomain}` return NextResponse.rewrite(url) } // --- Auth protection for /space routes --- // Only protect /space routes (not /tbff which is a public demo) if (pathname.startsWith('/space')) { // Demo spaces get anonymous access — SDK provides synthetic claims if (isDemoRequest(request)) { return NextResponse.next() } // Check for auth token in cookie (set by client after login) const token = request.cookies.get('encryptid_token')?.value // Also check Authorization header for API-style access const authHeader = request.headers.get('authorization') const bearerToken = authHeader?.startsWith('Bearer ') ? authHeader.slice(7) : null if (!token && !bearerToken) { url.pathname = '/' url.searchParams.set('login', 'required') url.searchParams.set('return', pathname) return NextResponse.redirect(url) } } return NextResponse.next() } export const config = { matcher: [ '/((?!_next/static|_next/image|favicon.ico|.*\\..*|api).*)', ], }