- Published on
Field Note: When I almost over-engineered a header generator
- Authors
- Name
- Eyji Koike Cuff
🛠️ The context
Recently, I had to mimic a Next.js API call in one of our systems. Seems simple enough — until I realized I had to include the mandatory next-router-state-tree
header in the request.
We already had some headers in the codebase as constants, but they were looking misplaced. So I thought:
What if I decode the state tree, reuse the base structure, add whatever I need, then re-encode it before sending the request?
It sounded elegant. Reusable. A clean abstraction, maybe even a little RouterHeaderBuilder
class.
But as I got closer to implementing it, I paused.
🧠 Abstractions vs. Usefulness
The more I thought about it, the more obvious it became: this header was tightly coupled to the page structure. If the header changed, it meant the site structure likely did too — and the request route would need updating regardless.
So why build a complex system for something so fragile?
Instead of introducing:
- Decoding logic
- Encoding utilities
- Error-prone assumptions about what parts were "reusable"
… I went with something simpler.
✅ The Simpler Solution
I copied the current header (yes, copy/paste), and avoided trying to dynamically rebuild or decode it.
Then I did two things to make it cleaner and safer:
- Created an
enum
for known routes and components (no stringly - typed keys) - Created a map that holds pre-defined state trees with the enum as keys
So now, if an engineer needs to mimic a different page:
- Add a new enum value
- Add the new route state to the map
- Pass it into the API call directly
Let me show you with a few lines:
class MyStateTree(str, Enum): # str here let's you do string things without calling for the .value property
ROUTE_ONE = "ROUTE_ONE"
NEXT_STATE_TREE = {
MyState.ROUTE_ONE: "%MY%20%ENCODED%20ROUTE"
}
# To use it as
session.get(
url="https://www.myendpoint.com"
headers={
"Next-Route-State-Tree": NEXT_STATE_TREE[MyStateTree.ROUTE_ONE]
}
)
📝 Final Thought
I almost built a clever solution for the wrong problem. What I really needed was something fast, understandable, and easy to change.
Sometimes the best abstraction is no abstraction, just a well-named constant and a clear enum.