From 8b5e723f81c01490379ae88e17bf452898b86009 Mon Sep 17 00:00:00 2001 From: Simone Cavalli Date: Thu, 14 May 2026 21:11:32 +0200 Subject: [PATCH] feat(01-03): add /c/[token] Server Component route + layout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - src/app/c/[token]/page.tsx: Server Component calls getClientView(), notFound() on null - src/app/c/[token]/layout.tsx: layout with metadata for client portal - [Rule 1 - Bug] Renamed middleware.ts → proxy.ts and export middleware → proxy (Next.js 16 deprecated 'middleware' file convention; requires 'proxy' export name) - params typed as Promise<{ token: string }> per Next.js 15+ breaking change - npm run build: SUCCESS (no TypeScript errors) --- src/app/c/[token]/layout.tsx | 14 ++++++++++++++ src/app/c/[token]/page.tsx | 28 ++++++++++++++++++++++++++++ src/{middleware.ts => proxy.ts} | 2 +- 3 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 src/app/c/[token]/layout.tsx create mode 100644 src/app/c/[token]/page.tsx rename src/{middleware.ts => proxy.ts} (94%) diff --git a/src/app/c/[token]/layout.tsx b/src/app/c/[token]/layout.tsx new file mode 100644 index 0000000..5a10360 --- /dev/null +++ b/src/app/c/[token]/layout.tsx @@ -0,0 +1,14 @@ +import type { Metadata } from 'next'; + +export const metadata: Metadata = { + title: 'Client Portal', + description: 'Project status dashboard', +}; + +export default function ClientLayout({ + children, +}: { + children: React.ReactNode; +}) { + return <>{children}; +} \ No newline at end of file diff --git a/src/app/c/[token]/page.tsx b/src/app/c/[token]/page.tsx new file mode 100644 index 0000000..06c9738 --- /dev/null +++ b/src/app/c/[token]/page.tsx @@ -0,0 +1,28 @@ +import { getClientView } from '@/lib/client-view'; +import { notFound } from 'next/navigation'; + +export const revalidate = 60; // ISR: revalidate every 60 seconds + +export default async function ClientDashboard({ + params, +}: { + params: Promise<{ token: string }>; +}) { + const { token } = await params; + const view = await getClientView(token); + + if (!view) { + notFound(); + } + + return ( +
+ {/* Placeholder: Dashboard UI will be built in Plan 04 */} +
+

{view.client.brand_name}

+

{view.client.brief}

+

Token: {token}

+
+
+ ); +} \ No newline at end of file diff --git a/src/middleware.ts b/src/proxy.ts similarity index 94% rename from src/middleware.ts rename to src/proxy.ts index 9ab66ae..13bb305 100644 --- a/src/middleware.ts +++ b/src/proxy.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from 'next/server'; -export async function middleware(request: NextRequest) { +export async function proxy(request: NextRequest) { const pathname = request.nextUrl.pathname; // Extract token from path: /c/[token]/...