# `apps/web-next` — Secondary frontend

Next.js 15 App Router. Marketing surface + a parallel dashboard. Server Components by default; Client Components opt-in. State is server-driven; auth lives in HTTP-only cookies set by the .NET API.

## Run

```bash
pnpm install
pnpm --filter @loma-portal/web-next dev
# → http://localhost:3000
```

## Layout

```
src/
├── middleware.ts                  next-intl + auth check + security headers
├── i18n/
│   ├── config.ts                  locales + defaultLocale
│   └── request.ts                 next-intl request config
├── messages/
│   ├── en.json
│   └── th.json
├── lib/
│   ├── api-client.ts              fetch wrapper (correlation-id, bearer, ApiResponse<T> unwrap)
│   └── types.ts                   ApiResponse / CurrentUser / AuthTokens
└── app/
    ├── layout.tsx                 Root layout + NextIntlClientProvider + design-tokens CSS
    ├── globals.css                Tailwind + token-driven base
    ├── page.tsx                   → /dashboard
    ├── login/
    │   ├── page.tsx               Server Component
    │   ├── login-form.tsx         Client Component
    │   └── login.action.ts        Zod-validated Server Action → sets HTTP-only cookie
    ├── dashboard/
    │   ├── page.tsx               Server Component
    │   ├── logout-button.tsx
    │   └── logout.action.ts
    ├── error.tsx
    ├── global-error.tsx
    └── not-found.tsx
```

## Notes

- All visual values come from `@loma-portal/design-tokens` (CSS variables). No hex codes inline.
- Auth: the .NET API (Phase 4) is expected to issue an `lp_access` cookie or returns tokens that this app converts into a cookie via `login.action.ts`.
- i18n: `next-intl` with `as-needed` locale prefix.
