navree
Documentation

Front end

Five npm packages for web front ends on a Navree API: a typed client, the backend-for-frontend, Next.js and Nuxt integrations, and navree.com's dark theme.

On this page

A Navree API is a bearer-token JSON API with an OpenAPI document, Navree's error shape, list queries, real-time channels over the Pusher protocol and operations you follow over server-sent events. A web front end needs the same pieces every time: a client typed from the document, a server that keeps the tokens out of the browser, sign-in with refresh and two-factor, abilities, live updates, data tables and a theme. The @navree/* packages are those pieces, tested once, so every front end on Navree works the same way.

Backend for frontendThe browser calls only its own web server, on the same origin, and holds cookies it can't read. The Next.js BFF keeps the access token (navree_at) and the refresh token (navree_rt) in httpOnly cookies and calls the Navree API with Authorization: Bearer. When the access token expires it refreshes once per refresh token, and Navree rotates the refresh token on every use. The Navree API reads and writes PostgreSQL in one transaction per request, and after a change it broadcasts to its WebSocket server, which pushes the event straight to the browser. The socket carries no token; private channels are authorized through the BFF.Browsercookies it can't readNext.js BFFhttpOnly cookiesnavree_ataccessnavree_rtrefreshNavree APIHTTP and WebSocketPostgreSQLusers · token familiessame originBearerrefresh,rotatesone transaction
Backend for frontend
  • request
  • real-time event

The packages

PackageWhat it gives youRuns in
@navree/clientcreateNavreeClient<paths>() on openapi-fetch and the schema navree openapi:client generates; NavreeError with the error code; listQuery(); page helpers; query keys; followOperation; text direction and error-code translation. Abilities (@navree/client/abilities) and real time (@navree/client/realtime) are separate entry points.Browser, server, any JavaScript runtime
@navree/bffThe backend-for-frontend on web-standard Request and Response: httpOnly token cookies, single-flight refresh, two-factor sign-in, the Origin check, a streaming proxy, ensureSession for server rendering.Node.js 20 and later
@navree/nextRoute handlers, auth() and client() for server components, the proxy that guards pages and refreshes tokens, useListQuery, DataTable, useOperation, workspaces, form errors; AbilityProvider and <Can>, RealtimeProvider and useChannel.Next.js 15 and 16
@navree/nuxtA Nuxt module: the BFF as Nitro routes, a session gate, auto-imported composables (useNavreeAuth, useWorkspace, useNavreeClient, useListQuery, useOperation, useChannel, useAbility) and <NavreeDataTable>.Nuxt 3.13 and 4
@navree/themenavree.com's dark theme: Tailwind CSS 4 tokens, shadcn/ui and shadcn-vue colors, the self-hosted fonts, and the tokens as data.Any CSS pipeline

The framework packages depend on @navree/client and @navree/bff, so a Next.js app installs @navree/next, @navree/client and @navree/theme, and a Nuxt app @navree/nuxt, @navree/client and @navree/theme. Optional features keep their libraries optional: CASL and pusher-js are only needed when you import the abilities or real-time entry points.

Installing

The packages live in packages/js/ of the Navree repository, a pnpm workspace. Build them once, then add them to your front end from the checkout:

Shell
web/package.json

Then generate the typed client's schema from your app:

Shell
Text

How a request travels

The browser never holds a token. It calls its own origin, and the app's server (Next.js route handlers, or Nitro in Nuxt) forwards each call to the API with Authorization: Bearer:

StepWhoWhat happens
1BrowserPOST /api/auth/login with the email and password, same origin.
2BFFCalls the API's POST /api/auth/login, keeps the access token in navree_at and the refresh token in navree_rt (both httpOnly), returns only {user}.
3BrowserGET /api/v1/deals?filter[stage]=won through the typed client, with X-Workspace: acme.
4BFFForwards it with the bearer token. On a 401 it refreshes once (shared by every request holding the same refresh token), sets the new cookies and retries.
5Server renderingauth() (Next.js) or getNavreeSession(event) (Nuxt) calls the API with the token from the cookie; the proxy or session gate has already refreshed an expired one.
6Browserpusher-js connects to the API's WebSocket server; private channels are signed by POST /broadcasting/auth through the BFF.

The pages in this section