feat(web-next): minimal authenticated shell home
Shell home for the platform-retrofit floor: a sign-in form (dev-seed credentials) and a signed-in placeholder with sign-out. Both flows run through the composed tRPC appRouter via server actions that own the session cookie on the app side; the auth feature is untouched. Adds the auth sign-in Playwright spec as the surviving e2e baseline and drops the last demo-template metadata. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016j8z4VHjedXDTjEDNg7qHK
This commit is contained in:
@@ -5,8 +5,8 @@ import { bindAll } from "../server/bind-production";
|
||||
import { Providers } from "./providers";
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Template — Next.js",
|
||||
description: "Clean Architecture Monorepo Template",
|
||||
title: "Veect",
|
||||
description: "Veect",
|
||||
};
|
||||
|
||||
export default async function RootLayout({
|
||||
|
||||
@@ -1,11 +1,90 @@
|
||||
import { cookies } from "next/headers";
|
||||
import { SESSION_COOKIE } from "@repo/auth";
|
||||
import { bindAll } from "../server/bind-production";
|
||||
import { signInAction, signOutAction } from "../server/auth-actions";
|
||||
|
||||
export default async function Home() {
|
||||
/**
|
||||
* Shell home: the sign-in surface plus a minimal authenticated placeholder.
|
||||
* The workspaces UI that replaces the placeholder arrives with the
|
||||
* walking-skeleton PRD. Signed-in state is cookie presence only — session
|
||||
* validation stays inside the auth feature and is exercised on sign-out.
|
||||
*/
|
||||
export default async function Home({
|
||||
searchParams,
|
||||
}: {
|
||||
searchParams: Promise<{ error?: string }>;
|
||||
}) {
|
||||
await bindAll();
|
||||
const [cookieStore, params] = await Promise.all([cookies(), searchParams]);
|
||||
const signedIn = cookieStore.has(SESSION_COOKIE);
|
||||
|
||||
return (
|
||||
<main className="mx-auto max-w-5xl px-6 py-8">
|
||||
<h1 className="mb-4 text-2xl font-bold text-foreground">Veect</h1>
|
||||
<main className="mx-auto flex min-h-screen w-full max-w-sm flex-col justify-center gap-6 px-6 py-8">
|
||||
<h1 className="text-2xl font-bold text-foreground">Veect</h1>
|
||||
|
||||
{signedIn ? (
|
||||
<section aria-label="Signed in" className="flex flex-col gap-4">
|
||||
<p className="text-foreground">You are signed in.</p>
|
||||
<form action={signOutAction}>
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground"
|
||||
>
|
||||
Sign out
|
||||
</button>
|
||||
</form>
|
||||
</section>
|
||||
) : (
|
||||
<form
|
||||
action={signInAction}
|
||||
aria-label="Sign in"
|
||||
className="flex flex-col gap-4"
|
||||
>
|
||||
<div className="flex flex-col gap-1">
|
||||
<label
|
||||
htmlFor="username"
|
||||
className="text-sm font-medium text-foreground"
|
||||
>
|
||||
Username
|
||||
</label>
|
||||
<input
|
||||
id="username"
|
||||
name="username"
|
||||
type="text"
|
||||
autoComplete="username"
|
||||
required
|
||||
className="rounded-md border border-input bg-background px-3 py-2 text-foreground"
|
||||
/>
|
||||
</div>
|
||||
<div className="flex flex-col gap-1">
|
||||
<label
|
||||
htmlFor="password"
|
||||
className="text-sm font-medium text-foreground"
|
||||
>
|
||||
Password
|
||||
</label>
|
||||
<input
|
||||
id="password"
|
||||
name="password"
|
||||
type="password"
|
||||
autoComplete="current-password"
|
||||
required
|
||||
className="rounded-md border border-input bg-background px-3 py-2 text-foreground"
|
||||
/>
|
||||
</div>
|
||||
{params.error === "invalid-credentials" ? (
|
||||
<p role="alert" className="text-sm text-destructive">
|
||||
Invalid username or password.
|
||||
</p>
|
||||
) : null}
|
||||
<button
|
||||
type="submit"
|
||||
className="rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground"
|
||||
>
|
||||
Sign in
|
||||
</button>
|
||||
</form>
|
||||
)}
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user