Frontends
The web product exists twice, in Next.js and SvelteKit, kept in step feature by feature. Either one can talk to either backend, because both backends serve the same API. A React Native app is starting alongside them.
Editions
| Next.js | SvelteKit | Expo | |
|---|---|---|---|
| Framework | Next 16, React 19 | SvelteKit 2, Svelte 5 | Expo 57, React Native 0.86 |
| Data | TanStack Query and Table, zustand | TanStack Query and Table | TanStack Query, zustand |
| Primitives | Radix UI, React Aria | Bits UI | Restyle, Reanimated, Skia |
| Default backend | Go, :3100 | Nest, :3101 | Not connected |
| Status | Wired | Wired | Showcase |
Talking to the backend
- Browser→/api/v1/*Every call goes to a same-origin route handler, never straight to the backend.
BENTO_API_ORIGINpicks the backend; if it is down the proxy returns a 502 problem. - Proxy→BackendForwards the headers the API uses and every
Set-Cookie. The session and MFA challenge are HttpOnly cookies, so no token ever reaches JavaScript. - Services
lib/services/<domain>call the API with types generated from OpenAPI and returnResultvalues. They never import TanStack. - Query layer
lib/queryowns cache keys and turns results into query data. When the session ends it clears the cache and sends the user to sign in. - ScreensSensitive actions ask for re-authentication (step-up) and retry once; a changed terms version prompts for acceptance.
Conventions: frontend/SERVICE-QUERY-CONVENTION.md. The integration brief with every endpoint's behaviour: frontend/UI-INTEGRATION.md.
Feature status
Both web editions, against the backend features in the integration brief.
| Area | Status | Covers |
|---|---|---|
| Sign-up and sign-in | Wired | Password and email flows, terms acceptance, Google/Apple/Microsoft OAuth, passkeys, TOTP and recovery-code MFA, password reset and email change. |
| Workspaces | Wired | Create and switch workspaces, general settings, and the workspace shell with its sections. |
| Members and invitations | Wired | People, roles, invitations sent and received. |
| Security settings | Wired | Sessions, password, email, two-step verification, recovery codes, passkey and OAuth methods, activity, account deletion. |
| Data export | Wired | Request and download a personal data export. |
| Plan, files and usage | Wired | Plans, checkout/portal handoff, invoices, entitlements, file browser, trash, quota and usage. |
| Integrations | Wired | API keys, signed webhook endpoints and workspace MCP connection/tool approval. |
| Notifications | Wired | Inbox, notification preferences and mute controls. |
| Audit log | Wired | The workspace audit log screen. |
| AI tasks and assistant | Wired; parity evolving | Task launch/results, cancellation, saved assistant conversations, selected-file retrieval and citations. Hosted model quality and some provider-dependent tools still need qualification. |
| Workspace Chat | Wired | Direct and group conversations, messages, attachments, read cursors and leave behavior. |
| Realtime | Wired | WebSocket updates, cache invalidation, workspace and folder presence. |
Known gaps
Current UX and parity follow-ups are tracked in frontend/TODO.md. Browser coverage now exercises core Chat, assistant, AI task, MCP consent and selected authentication journeys across the Go/Nest and Next/Svelte pairings. Product-specific usability, accessibility, deployment routing and provider behavior still need review.
Routes
Both editions have the same route groups.
| Group | Routes |
|---|---|
(site) | /, /landing/[variant], /coming-soon |
(app) | /w, /w/new, /w/[workspace]/[section]/… (home, people, files, chat, assistant, AI runs, audit, plan, settings, integrations), /account/*, /invitations |
auth | Sign-in, sign-up, OAuth callbacks, passkey ceremonies, verify-email, forgot/reset password, email-change and sign-out. |
| Tooling | /kitchen-sink (the component catalog), /shell-preview/[variant], /health |
| Proxy | /api/v1/[...path] |
Style presets
Each web edition carries the same six CSS presets with the same semantic variable names. One import innext/app/globals.css or svelte/src/routes/+layout.svelte selects a preset;data-theme forces light or dark and data-density="compact" tightens controls.
Mobile
frontend/mobile is an Expo Router app with a component showcase, six theme presets, the sameResult kernel, an HTTP transport and TanStack Query. Its architecture defines two profiles, a companion to the web product and a standalone app, but neither is wired to the backend yet; the standalone screens use local fixtures.
Tests and CI
CI runs a generated-types freshness check, formatting, lint, type-check and Vitest.
CI runs formatting, lint, svelte-check and Vitest. It does not check generated types.
Node test scripts for themes, ideas, selection and feedback. Not in CI.
Unit tests cover the HTTP kernel, proxy headers, error presentation, step-up, uploads and each service's response readers. Screens are checked in a browser rather than in unit tests, and CI does not build the apps.
Previews
Both web editions are deployed without a backend, so account actions return the proxy's 502. They are published from deployments/showcase/vercel, not from pushes.