# Frontend Bff

> Use when building a Next.js frontend or its backend-for-frontend. The browser talks only to its own origin: runtime configuration so one image serves every environment, HttpOnly cookie sessions instead of a token API, edge middleware that verifies rather than merely decodes, the catch-all proxy with a candidate ladder, entitlement UX, and the shared web kernel whose absence is the costliest finding in the worked example.

- Skill: `konradcinkusz/frontend-bff` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add konradcinkusz/frontend-bff`
- Raw SKILL.md: https://api.skillmd.com/api/skills/konradcinkusz/frontend-bff/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Web & Frontend
- Author: konradcinkusz (https://skillmd.com/u/konradcinkusz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/konradcinkusz/frontend-bff

---


# Frontend and BFF patterns

**Read [`references/FRONTEND-BFF.md`](references/FRONTEND-BFF.md) before applying any of this.**
That file is the standard; everything below it is a summary to help you decide
whether this skill applies and to check your work afterwards.

Reference-architecture principles: P2, P6.

## What this standard covers

- The model in one paragraph
- Runtime configuration
- Sessions: HttpOnly cookies over a token API
- Edge middleware verifies, not just decodes
- The catch-all proxy and the candidate ladder
- Entitlement UX
- The shared web kernel

## Failure modes

| Symptom | Cause |
|---|---|
| Staging frontend calls production APIs | Addresses baked via `NEXT_PUBLIC_*` at build; move to the runtime config route |
| Token visible in devtools/localStorage | Client stored the token instead of handing it to the BFF cookie route |
| Login loop after logout | Cookie deleted with different attributes than it was set with |
| Forged token accepted at the edge | Middleware decoded instead of verified; use `jwtVerify` with issuer/audience |
| OAuth callback loses its parameters | Middleware redirect lacks the callback carve-out |
| Proxy 403s only in one environment | Candidate ladder missing that environment's rung (discovery vars vs internal DNS) |
| Downloads fail after idle periods | Proxy timeout shorter than the callee's cold start; or response buffered instead of streamed |
| Paying user sees an upgrade flash | Entitlement hook pessimistic while loading; must be optimistic |
| Same bug fixed in one app, alive in three | No shared web kit; BFF code hand-copied per app |

## Checklist

- [ ] Client JS never holds a token or a backend URL; browser talks only to its own origin
- [ ] Runtime `/api/config` route; no `NEXT_PUBLIC_*` for anything environment-specific; image promotable across environments
- [ ] Tokens in HttpOnly/secure/sameSite cookies set and cleared (same attributes) by BFF routes; session rehydrate route
- [ ] Middleware verifies signature + issuer + audience; public-route list; `?redirect=` preserved; callback carve-outs
- [ ] Catch-all proxy: prefix routing, candidate ladder, server-side bearer injection, streamed binaries with cold-start-sized timeout
- [ ] Entitlement UI optimistic while loading and documented as non-enforcement
- [ ] All apps in one workspace under one package manager; shared web-kit package owns BFF routes, auth context, consent, primitives

---

Generated from [`docs/guides/FRONTEND-BFF.md`](https://github.com/konradcinkusz/architecture-standards/blob/main/docs/guides/FRONTEND-BFF.md) by `scripts/build-marketplace.mjs`. Do not edit this file: change the source document, or its entry in `catalog/marketplace.catalog.json`, and re-run the generator.

