Seltzer Is Becoming KiwiEngine's Communication Layer
Road To KiwiEngine #43: An application can't live entirely inside itself. Eventually, something has to come in. A request. A form submission. An API call. A webhook. A client asking for data. And eventually, som
Road To KiwiEngine #43:
An application can't live entirely inside itself.
Eventually, something has to come in.
A request.
A form submission.
An API call.
A webhook.
A client asking for data.
And eventually, something has to go back out.
A response.
JSON.
An error.
A resource.
A status.
That's where Seltzer fits into KiwiEngine.
If Juice helps describe how an application looks, Sig makes its interfaces reactive, and Nectarine helps describe what the application is, Seltzer deals with a different boundary:
How does the application communicate with the world outside of it?
HTTP Is Everywhere
One of the strange things about web development is how quickly HTTP disappears behind everything else.
You build an API.
You create routes.
You submit forms.
You fetch data.
You receive webhooks.
You authenticate users.
You upload files.
Underneath all of that, requests are moving into the application and responses are moving back out.
HTTP isn't the interesting part of most applications.
But it's involved in almost everything they do.
That makes it exactly the kind of infrastructure I want KiwiEngine to understand well.
I Don't Want Every Application Relearning HTTP
I've built enough web applications to recognize how much repeated infrastructure accumulates around communication.
Parsing requests.
Creating responses.
Handling headers.
Understanding methods.
Managing status codes.
Dealing with errors.
Routing requests toward the correct behavior.
Normalizing the information applications actually care about.
None of those things are particularly unique to Blackwater Sound.
Or WebStore.
Or KiwiPress.
Or an artist platform.
They're web infrastructure.
So why should every application have to solve them independently?
That's the question Seltzer is trying to answer.
Seltzer Gives HTTP A Boundary
I don't want HTTP concerns leaking throughout the entire application.
Business logic shouldn't need to understand every detail of how a request arrived.
A commerce system should understand an order.
A music application should understand a session.
A publishing system should understand an article.
Those domains shouldn't be designed around raw HTTP mechanics.
Seltzer can sit at that boundary.
The outside world speaks HTTP.
The application speaks its domain.
Somewhere between those two things, translation has to happen.
That's where Seltzer belongs.
The Request Is Not The Business Logic
This distinction has become increasingly important to me.
Imagine WebStore receives a request to create an order.
The request might contain JSON.
It might include authentication information.
It has a method.
Headers.
A URL.
Maybe query parameters.
All of that matters.
But none of it is the order itself.
The business logic should eventually be able to reason about something closer to:
createOrder(customer, items);
rather than carrying an HTTP request through every layer of the application.
That separation matters.
Because the domain is the thing I'm actually trying to build.
HTTP is how someone reached it.
Responses Work The Same Way
The other direction matters too.
Suppose something goes wrong.
Maybe a product doesn't exist.
Maybe a user isn't authorized.
Maybe some input is invalid.
The domain should be able to communicate what happened without every piece of business logic manually constructing an HTTP response.
Somewhere, that result needs to become something the client understands.
A status.
A response body.
Headers.
Maybe an error representation.
That's infrastructure.
Seltzer can help create a consistent boundary between those concerns.
This Is What I Mean By Communication Layer
I'm not trying to make Seltzer responsible for everything that happens on the server.
Quite the opposite.
Its usefulness depends on knowing where to stop.
Seltzer doesn't need to understand commerce.
It doesn't need to understand music.
It doesn't need to know how KiwiPress organizes content.
It doesn't need to know how an artist platform manages releases.
It needs to understand the communication mechanisms those systems rely on.
That's a much smaller responsibility.
But it's also a foundational one.
Boring HTTP Is Good HTTP
One of my goals for KiwiEngine is for infrastructure to eventually become boring.
Not bad boring.
Dependable boring.
I shouldn't be inventing a new response pattern every time I create an endpoint.
I shouldn't wonder how errors are represented in every application.
I shouldn't have five different approaches to reading the same kind of request.
I shouldn't need to think deeply about basic HTTP plumbing every time I want two systems to communicate.
The interesting question should be:
What should happen when this request reaches my application?
Not:
How do I get this request into a usable shape?
That's the difference between building the product and rebuilding its infrastructure.
Predictability Creates Leverage
This connects back to something I've been learning throughout KiwiEngine.
Consistency isn't valuable simply because everything looks organized.
Consistency reduces the number of decisions I have to make.
If Seltzer establishes predictable request and response behavior, I can carry that understanding between applications.
When I move from KiwiPress to WebStore, I don't have to relearn the communication layer.
When I build something for Blackwater Sound, the underlying mechanics are familiar.
When I create another API later, I already know how requests move through the system.
That's leverage.
Not because Seltzer writes the application for me.
Because it removes questions I've already answered.
APIs Become Much More Interesting From Here
This is also where KiwiEngine starts becoming more useful for the kinds of systems I want to build.
WebStore will need APIs.
An artist platform will need APIs.
Blackwater Sound applications will need APIs.
KiwiPress needs communication between systems.
External services may need webhooks.
Print on Demand providers may need to send updates.
Payment systems may need to notify WebStore that something happened.
Software might need licensing endpoints.
Hardware could eventually communicate with services I've built.
The more projects I create, the more important a consistent communication layer becomes.
Not because every application communicates about the same thing.
Because they all need a dependable way to communicate.
External APIs Are Part Of This Too
Communication doesn't only move inward.
KiwiEngine applications will also need to talk to other systems.
WebStore might communicate with a payment provider.
A Print on Demand integration might communicate with a fulfillment service.
Blackwater Sound might communicate with music-related platforms.
Infrastructure systems may communicate with cloud providers.
Those APIs belong to other companies.
Their structures may be completely different.
But I still want clear boundaries around how my application interacts with them.
I don't want somebody else's API model becoming my application's domain model.
The external service should remain external.
My application should remain mine.
Communication connects them.
It shouldn't collapse the boundary between them.
Seltzer Doesn't Need To Become An API Framework For Everything
This is another place where restraint matters.
Once you have an HTTP library, it's easy to start attaching everything remotely related to server development to it.
Authentication?
Put it in Seltzer.
Database access?
Why not?
Validation?
Sure.
Business logic?
Throw that in too.
Eventually the HTTP library becomes the entire backend framework.
That's not what I want.
Seltzer should solve Seltzer problems.
Other KiwiEngine systems should solve theirs.
WebEngine can coordinate them.
That separation is what allows the ecosystem to become more capable without every individual library becoming enormous.
Nectarine Makes This More Interesting
This is where the previous post starts connecting to this one.
Nectarine can help KiwiEngine understand application structure and configuration.
That can include information about routes.
Seltzer understands HTTP.
Now those two responsibilities can participate in the same application without becoming the same library.
One system helps describe what should exist.
Another understands how communication actually happens.
WebEngine can coordinate those capabilities.
That's composition.
And it's starting to become much more tangible than it was when KiwiEngine was just a collection of experiments.
This Is What An Engine Should Do
The more I work on KiwiEngine, the less interested I am in enormous abstractions that pretend the underlying technology doesn't exist.
HTTP exists.
CSS exists.
JavaScript exists.
Servers exist.
Databases exist.
Infrastructure exists.
I'm not trying to hide reality.
I'm trying to establish better boundaries around it.
Juice doesn't make CSS disappear.
It provides a higher-level way to express common design intent.
Sig doesn't make JavaScript disappear.
It gives reactive interfaces a focused model.
Nectarine doesn't make application structure disappear.
It gives the engine a way to understand that structure.
And Seltzer doesn't make HTTP disappear.
It gives HTTP a place to live.
I think that's an important distinction.
Another Piece Of The Engine Is Becoming Predictable
That's really what this current stretch of Road To KiwiEngine is about.
Not adding as many features as possible.
Making responsibilities predictable.
Juice knows more clearly what it owns.
Sig knows more clearly what it owns.
Nectarine knows more clearly what it owns.
And Seltzer is establishing the communication boundary between KiwiEngine applications and the systems around them.
Each time one of those boundaries becomes clearer, WebEngine becomes easier to reason about.
Because the engine doesn't have to do everything itself.
It has dependable systems to coordinate.
And eventually, when I'm building an application, I don't want to spend much time thinking about Seltzer at all.
I want to think about the request that just arrived.
What it means to my application.
What should happen because of it.
And what I want to communicate back.
The application should own the conversation.
Seltzer should make sure the message gets through.
Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.