When frontend applications grow, authentication is often the first place where architectural cracks appear.
JWTs, cookies, sessions, headers — each change tends to ripple through components, hooks, and state logic. Over time, the UI becomes inseparable from the authentication mechanism.
I wanted to explore what it looks like when that doesn’t happen.
The Goal
Build a frontend demo where:
- The UI does not know how authentication works
- Switching between cookie-based auth and JWT-based auth requires no UI changes
- The swap happens at the composition boundary, not inside components
This demo is built on top of my frontend-foundation template, which enforces strict separation between UI, hooks, services, and implementations.
The Setup
The application exposes a single hook to the UI:
useAuth(client)
Everything downstream depends on a stable contract:
- login()
- logout()
- getSession()
The UI never imports:
- cookie logic
- JWT logic
- storage APIs
- auth libraries
Two different clients implement the same contract:
- cookieClient
- jwtClient
Each client is passed into useAuth independently, allowing both strategies to run side-by-side on the same page.
Why This Matters
In many real-world projects:
- Switching auth strategies means rewriting hooks
- Components start branching on auth type
- State logic leaks implementation details
This demo proves that those problems are architectural, not inevitable.
If auth is treated as an implementation detail behind a contract, the UI becomes resilient to change.
Repositories
Demo app: Frontend Foundation Auth Swap Demo
Template: Frontend Foundation Starter Kit
Closing Thoughts
If swapping core infrastructure feels risky, it’s usually a signal that the UI is coupled too tightly to implementation details.
The fix isn’t a new library — it’s better boundaries.
Top comments (0)