layout.tsx65 lines · main
1import Link from 'next/link';
2import type { ReactNode } from 'react';
3import { cookies } from 'next/headers';
4import { notFound } from 'next/navigation';
5
6import { loadAuthV2Workspace } from '../lib/load-workspace';
7import { AuthProjectNav } from './auth-project-nav';
8
9export const dynamic = 'force-dynamic';
10
11/**
12 * Per-project Auth shell — same header + tabs pattern as Projects:
13 * ← Auth
14 * {name}
15 * {slug} · Auth on|off
16 * [tabs…] [↗ developer mode]
17 */
18export default async function AuthProjectLayout({
19 children,
20 params,
21}: {
22 children: ReactNode;
23 params: Promise<{ projectId: string }>;
24}) {
25 const { projectId } = await params;
26 const developerMode =
27 (await cookies()).get('briven_auth_project_dev')?.value === '1';
28 const projects = await loadAuthV2Workspace();
29 const project = projects.find(
30 (p) => p.id === projectId || p.id.toLowerCase() === projectId.toLowerCase(),
31 );
32 if (!project) {
33 notFound();
34 }
35
36 // Trust workspace flag; layout badge only (page may re-check enable).
37 const authOn = project.authEnabled === true;
38
39 return (
40 <div className="flex flex-col gap-6">
41 <header>
42 <Link
43 href="/dashboard/auth"
44 className="font-mono text-xs text-[var(--color-text-subtle)] hover:text-[var(--color-text-muted)]"
45 >
46 ← Auth
47 </Link>
48 <h1 className="mt-2 font-mono text-xl tracking-tight text-[var(--color-text)]">
49 {project.name}
50 </h1>
51 <p className="mt-1 font-mono text-sm text-[var(--color-text-muted)]">
52 {project.slug}
53 {' · '}
54 {authOn ? (
55 <span style={{ color: 'var(--auth-accent, #FFFD74)' }}>Auth on</span>
56 ) : (
57 <span>Auth off</span>
58 )}
59 </p>
60 </header>
61 <AuthProjectNav projectId={project.id} developerMode={developerMode} />
62 <section>{children}</section>
63 </div>
64 );
65}