code: nextjs,frontends,tsx (2 files)

This commit is contained in:
Richard Ward
2025-12-30 22:39:46 +00:00
parent 5f623911cb
commit 79fde8698b
2 changed files with 99 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
/**
* Tenant-Scoped Layout
*
* This layout wraps all pages under /{tenant}/{package}/...
* It provides tenant context to all child components.
*/
import { headers } from 'next/headers'
import { notFound } from 'next/navigation'
import { TenantProvider } from './tenant-context'
interface TenantLayoutProps {
children: React.ReactNode
params: Promise<{
tenant: string
package: string
}>
}
export default async function TenantLayout({
children,
params,
}: TenantLayoutProps) {
const resolvedParams = await params
const { tenant, package: pkg } = resolvedParams
// Validate tenant exists
// TODO: Check against database
// const tenantData = await getTenant(tenant)
// if (!tenantData) {
// notFound()
// }
// Validate package exists and is installed for tenant
// TODO: Check against database
// const packageInstalled = await isPackageInstalled(tenant, pkg)
// if (!packageInstalled) {
// notFound()
// }
return (
<TenantProvider tenant={tenant} packageId={pkg}>
<div className="tenant-layout" data-tenant={tenant} data-package={pkg}>
{children}
</div>
</TenantProvider>
)
}

View File

@@ -0,0 +1,51 @@
/**
* Next.js Middleware
*
* Handles multi-tenant routing at the edge.
* Routes: /{tenant}/{package}/... are treated as tenant-scoped requests.
*/
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import { isReservedPath, RESERVED_PATHS } from '@/lib/routing/route-parser'
export function middleware(request: NextRequest) {
const { pathname } = request.nextUrl
// Skip reserved paths
const firstSegment = pathname.split('/')[1]
if (!firstSegment || isReservedPath(firstSegment)) {
return NextResponse.next()
}
// Check if this looks like a tenant route: /{tenant}/{package}/...
const segments = pathname.split('/').filter(Boolean)
if (segments.length >= 2) {
// Looks like a tenant route
const tenant = segments[0]
const pkg = segments[1]
// Add tenant info to headers for downstream use
const response = NextResponse.next()
response.headers.set('x-tenant-id', tenant)
response.headers.set('x-package-id', pkg)
return response
}
return NextResponse.next()
}
export const config = {
matcher: [
/*
* Match all request paths except:
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico (favicon file)
* - public folder
*/
'/((?!_next/static|_next/image|favicon.ico|public/).*)',
],
}