V8 Central — Product & Technical Spec
  1. Docs
  2. Frontend spec (from backend doc)
  3. FE: Foundation (Phase 1)

#FE: Foundation (from backend Phase 1)

What the backend's Phase 1: Foundation Setup (prepared by Pair 1, flow defined 2026-10-01, not built) means for the frontend, and the frontend foundation that has to exist before any feature screen. V8 requirement

#Backend Phase 1 → frontend consequences

Backend stepBackend ruleFrontend consequence
1.1 MySQLChanged from MariaDB on 2026-10-08. Driver mysql (never mariadb), target MySQL 8.4 LTS, sv_central_2 for Pair 2, utf8mb4 / utf8mb4_unicode_ci, strict mode. Development runs on the server's existing MariaDB 10.11, with the code kept MySQL-compatible: Eloquent and the query builder only, no MariaDB-only SQL, json columns through Laravel casts, UUIDs as char(36)Almost nothing for us — the frontend never touches the database. Two details are worth carrying anyway. UUIDs are char(36), so wherever the API returns one, an id is a string: never parse an id as a number, and never assume a sortable integer in a route param. And utf8mb4_unicode_ci is case-insensitive, so a duplicate-name check on the backend will treat MyApp and myapp as the same Assumption — a "name already taken" message should not imply that changing the capitalisation will help. Our base URL must still stay sa-central-api-2 (each pair has its own database)
1.2 RedisCache, sessions, queue on RedisNone directly
1.3 HorizonQueues default, notifications, emailsEmails (verification, reset, invites, IP approval) are queued. Screens say "We've sent an email" right away and offer resend after a cooldown, not "sending…"
1.4 SanctumChanged from Passport on 2026-10-08 (Vishal). Laravel Sanctum, Bearer API tokens only — no SPA cookie / stateful mode. Access token 15 days; Sanctum has no refresh token, so Central builds the 30-day refresh itself in Phase 2 (2.9); token abilities are used for scopes. Central issues the access + refresh token itself after all login checks pass (2.9). The personal API token (3.13) never expires — corrected 2026-10-09 when 3.13 was built; this line previously said "its own expiry when it is created", which was inferred from the empty global expiry rather than published. V7's fixed 6 months is gone and nothing replaces it V8 requirementGood news for D-1, not bad: the backend has ruled out the one alternative to the BFF proposal below, so there is nothing left to choose between. And a trap to avoid: "cookie-based Sanctum session" in the project rules is not Sanctum's SPA mode — there is no /sanctum/csrf-cookie step and no stateful-domain config. The cookie is Next.js's own httpOnly cookie carrying a Bearer token. The frontend is otherwise unaffected by how the token is made — it needs the login/refresh response fields below. Personal token = "API access" (3.13), excluded from the frontend by Bhavik's rule; migrated V7 tokens keep working
1.5 TelescopeLocal onlyNever linked from the frontend
1.6 CORSOnly the configured frontend URL. api/* only — oauth/* was dropped with Passport on 2026-10-08. Authorization header allowed. No wildcardsThe backend must list https://sa-central-2.23-172-120-38.nip.io. If we use the BFF (server-to-server), CORS only matters for any direct browser calls
1.7 Mail & loggingMAIL_MAILER=log in developmentIn development, emails go to the backend log. Testers need the backend team to share links from it
1.8 SecurityHTTPS URLs, secure cookies, trusted proxyThe frontend is served over HTTPS. Cookies Secure
1.9 Final checkThe MySQL connection plus a protected auth:sanctum route workFirst frontend smoke test: call that route through the BFF
1.10 Translations (i18n)New 2026-10-08 (Pair 2) — this answers Q8. Every user-facing API text — errors, validation, emails, notifications — comes from lang/ translation keys, never hardcoded English. A middleware reads Accept-Language and sets the app language, falling back to English. Which languages are offered: decided laterThe single most important line on this page for us, and it carries one obligation. The backend translates server-side, so a message arrives already in the user's language — simpler than the type-and-params scheme this spec proposed. But a server-side fetch carries no browser headers, so the BFF must read the locale cookie and set Accept-Language on every call, including from server components. Miss it and every backend message quietly falls back to English, which is the kind of bug that ships. And the language list is not agreed: we spec eight locales, the backend has not decided its set — so the switcher should offer what both sides support, or a user gets our UI translated and the backend's messages in English
1.11 Code qualityNew 2026-10-08 (Pair 2) — this answers Q7. Pint and PHPStan (Larastan) installed; every task must pass Pint + PHPStan + Pest before it is doneBackend-side, and it reverses the 2026-10-03 "skipped for now". Worth noting as a precedent rather than a requirement: the backend now has a hard per-task gate, and our equivalent is ESLint + Prettier + Vitest / Playwright — the same shape, and a fair thing to hold ourselves to
Not in phase"Next.js login flow (how the frontend gets and stores the Sanctum token): decided by the frontend pair" — reworded 2026-10-08, from "decided later". Added 2026-10-08: the refresh token and clearing expired tokens (sanctum:prune-expired, which needs the scheduler) also move to Phase 2D-1 is now ours to decide — that is the real change here. The backend has handed the login flow to the frontend pair rather than leaving it "decided later", so the BFF proposal below stops waiting for approval and becomes a decision Bhavik can simply take. The refresh moving to Phase 2 still matters: there is no refresh endpoint at all until Phase 2 ships, so a frontend built against Phase 1 alone has a 15-day session and no renewal

#D-1: Passport token in Next.js (frontend proposal for the backend team)

  • Tokens live only in httpOnly; Secure; SameSite=Lax cookies set by Next.js route handlers.
  • Server components and route handlers add Authorization: Bearer when calling sa-central-api-2.
  • On 401: one refresh (2.9) in the route handler, then retry once. If that fails, clear the cookies → login.
  • What the frontend needs from the backend: the login/refresh responses must return access_token, refresh_token, expires_in in the body (not only as cookies), plus a refresh endpoint that rotates and revokes (2.9).
  • Sharpened 2026-10-08: the refresh half is Central's own code, not a framework feature — Sanctum has no refresh token.
  • Answered 2026-10-09, when Phase 2 was built. The login response carries tokens in the body — two_factor_required: false + tokens + user + organizations, or two_factor_required: true + a challenge_token. That is the ask above, granted: the BFF can read the tokens and set its own cookies. Two details worth more than the answer itself:
    • The 2FA step is driven by a challenge_token, not a half-made session — nothing is signed in until 2FA passes, so the BFF carries only the challenge between the two steps and sets no session cookie until the end.
    • The refresh token is rotated on every use, and reusing a spent one revokes the whole login chain. So the BFF must serialise refresh through one in-flight promise and never auto-retry it. A retried refresh, or two concurrent requests both refreshing, logs the user out of everything. This is the sharpest constraint Phase 2 puts on the frontend.
  • Still not named: an expires_in (or equivalent) field. The lifetimes are known from the doc (15 days / 30 days), but the response shape says "tokens" without listing fields Open question — worth confirming rather than hard-coding 15 days in the BFF.

#Frontend foundation (frontend Phase 0)

ItemDetailDependency status
i18nnext-intl, app/ (no locale segment), middleware (cookie → Accept-Language; never in the URL), messages/{en,es,de,fr,pt,ja,ru,hi}.jsonnext-intl to be added (required by project rules)
App shellSidebar groups, top bar, mobile drawer, breadcrumbs, organization switcher slotshadcn primitives present
Themenext-themes, light/dark/systempresent
API layerlib/api/ axios instance (server side) + route handlers (BFF). Error normaliser, GET retry, abort, Accept-Languageaxios present
Formsreact-hook-form + zod resolversreact-hook-form to be added
TablesTanStack Table v8to be added
Statesloading.js / error.js / not-found.js per group, skeletons, empty-state component—
TestsVitest + Testing Library. Playwright + axeto be added
Env.env.local: CENTRAL_API_URL (server only). No secrets in NEXT_PUBLIC_*—

Every new dependency is justified in the Phase 0 plan and needs approval before it's added.

ServerAvatar V8 Central · prepared by central-app-2 (Pair 2 frontend) for Bhavik Jethwa · the frontend in this spec is not built yet; the backend started on 2026-10-08 · Built 2026-10-29 03:20 UTC