The Reversible Jacket Pattern
TL;DR: Reversible Jacket is a useful pattern for developing a web frontend UI and backend API simultaneously, and here’s a demo.
Tools like esbuild and Vite make developing static frontend web applications enjoyable, and there are tons of starter templates out there for them. But if your frontend UI and backend API are being developed together as two tightly-coupled halves of a monolith, how do you structure your project to handle both the development phase and the production phase without tearing your hair out?
Voilà: the Reversible Jacket. The idea is that the frontend dev server proxies API routes to the backend server during development, while in production the roles are reversed and the backend hosts the frontend’s static assets and the API routes as single-origin app. The README explains why that’s a good thing and how this reference implementation works. This could be useful for anyone making a Jamstack app using the BFF pattern, regardless of their specific tech stack.1 In my experience, a Reversible Jacket codebase is a pleasant and productive workspace once configured.
This is nothing revolutionary. Maybe this pattern is so obvious that nobody bothered to write it down, or it is already named something I’m oblivious to.2 If not, I think that “Reversible Jacket” is descriptive and memorable. Here are some tools I found that solve similar problems:
- The Vercel CLI has a
dev
command so you can test serverless functions locally. - The Netlify CLI has a
dev
command to run a local dev server with Netlify’s proxy and redirect rules, and apparently you can test functions locally too. - Supabase launched edge functions recently, and you can
develop locally using the command
supabase functions serve
. - The Stackery CLI allows for local development.
- The AWS SAM allows you to invoke lambda functions locally with the command
sam local invoke
.
All I’m trying to say is that there seems to be some momentum for this kind of smooth local development experience. Those proprietary tools above might not be much help to a UI/API destined for a platform like Kubernetes, ECS, GCR, Fly.io, Render, etc. We owe it to ourselves and the maintainers that will eventually inherit our codebases to invest in good DX.