I've spent a lot of the Road To KiwiEngine series talking about architecture from thirty thousand feet.
Systems.
Abstractions.
Boundaries.
Intent.
Configuration.
Framework design.
But KiwiEngine is becoming more of an actual engine because the individual pieces underneath it are becoming more capable.
So I want to spend the next several posts looking at those pieces individually.
And there's probably no better place to start than Juice.
Because Juice is getting very close to version 1.0.
Juice Started With A Much Smaller Idea
Juice started because I wanted a better way to handle common styling patterns.
Not replace CSS.
Not invent another enormous styling language.
Not recreate every CSS property as an attribute.
I wanted to express common design intentions directly in markup.
That eventually led to things like:
<div content adapt="grid" mobile="stack">
There's a lot happening in a very small statement.
I'm saying this element contains content.
I'm saying that content should adapt using a grid.
And I'm saying that on mobile, I explicitly want that layout to stack.
But I'm not describing every CSS declaration required to accomplish it.
That's Juice's job.
Intent Became The Important Part
The more I developed Juice, the more I realized that its value wasn't really about shortening CSS.
It was about communicating intent.
There's a difference between saying:
Apply these seven CSS properties.
and:
This content is a grid.
The first describes an implementation.
The second describes what I'm trying to accomplish.
That distinction became one of the core ideas behind Juice.
And it started affecting how I thought about KiwiEngine as a whole.
But Intent Can Become Another Trap
Once I started thinking this way, there was an obvious temptation.
Add more attributes.
And more.
And more.
Until eventually every CSS property has a Juice equivalent.
At that point I've accomplished something incredible:
I've reinvented CSS.
Except probably worse.
That's exactly what I don't want.
Juice needs to know where its responsibility ends.
If something is already expressive and easy to accomplish with CSS, I don't necessarily need to invent another abstraction for it.
Juice should handle the common intentions.
CSS should remain available for everything else.
That boundary has become part of the design.
Defaults Are Part Of The Product
Responsive design helped clarify this philosophy.
Take:
<div content adapt="grid">
I don't necessarily want developers to have to specify:
mobile = ...
tablet = ...
laptop = ...
desktop = ...
every single time they create a grid.
Juice already knows that grids usually need to adapt.
So it can provide sensible responsive behavior by default.
Then, when the developer actually wants different behavior, they can express it:
<div content adapt="grid" mobile="stack">
That's the relationship I want.
Good defaults.
Small intentional overrides.
Escape hatches when necessary.
I don't want configuration for the sake of configuration.
Then Juice Became Configuration-Driven
This was one of the bigger steps forward.
Juice can now consume project configuration and generate stylesheets from it.
That changes the relationship between the library and the project.
Instead of Juice defining the entire visual language, the project can define its own design decisions.
Things like:
- colors
- typography
- spacing
- borders
- shadows
- radius
- other design tokens
Juice consumes those decisions and generates the stylesheet needed to support its attribute-based styling system.
It's effectively becoming a theme generator.
And I really like that direction.
The Project Owns The Theme
This is important to me.
I don't want every application built with KiwiEngine to look like a "KiwiEngine application."
The framework shouldn't own the brand.
The project should.
Blackwater Sound should look like Blackwater Sound.
A WebStore storefront should reflect the business using it.
An artist platform should reflect the artist.
A completely unrelated developer using Juice should be able to create something that looks nothing like anything I've built.
Juice provides the styling engine.
The project provides the identity.
That's a much healthier boundary.
Generated CSS Is Still CSS
There's another part of this architecture that I like.
The output is still stylesheets.
I'm not trying to create an alternate universe where the browser suddenly doesn't use CSS.
Juice can consume configuration.
It can understand its attributes.
It can generate the appropriate styling.
But eventually we're still speaking the language the browser understands.
That matters because Juice can't be everything.
And it shouldn't be.
If a project needs custom CSS, write CSS.
If something doesn't belong in Juice, don't force it into Juice.
The abstraction should help until it stops helping.
Then it should get out of the way.
This Is Starting To Feel Like An Engine
This is why I'm beginning to think about Juice differently.
Originally, it was a styling library.
That's still technically true.
But increasingly, it behaves like a small design engine.
It has inputs.
Project configuration.
Design tokens.
Intent expressed through attributes.
It has rules.
Defaults.
Responsive behavior.
Attribute semantics.
And it produces output.
Stylesheets.
Consistent styling behavior.
A design language that can be reused throughout an application.
That's more interesting to me than simply having a collection of CSS utilities.
Version 1 Is About Knowing What Juice Is
This connects back to what I wrote recently about Juice approaching version 1.0.
I don't think 1.0 means Juice has every feature I could possibly imagine.
Quite the opposite.
Getting closer to 1.0 has made me more comfortable saying:
No, Juice doesn't need that.
That's maturity.
The goal isn't maximum capability.
The goal is a clear responsibility.
I want to be able to explain what Juice does.
I want developers to understand its vocabulary.
I want its defaults to be predictable.
I want its configuration to make sense.
And I want its boundaries to remain visible.
If I can accomplish those things, Juice doesn't need to solve every styling problem.
It just needs to solve its styling problems well.
Libraries Becoming Engines
This is part of a larger change happening inside KiwiEngine.
The individual libraries are no longer just experiments asking:
What if I built this?
They're developing philosophies.
Boundaries.
Configuration.
Stable APIs.
Relationships with other parts of the ecosystem.
That's what makes WebEngine increasingly capable of behaving like an engine.
Not because I created one enormous framework that does everything.
But because the smaller systems underneath it are becoming dependable enough to compose.
Juice is one of the first pieces reaching that point.
And after all the experimentation, redesigning, questioning, and real-world use, I think I finally know what it wants to be.
Juice isn't trying to replace CSS.
It isn't trying to become another utility framework.
And it isn't trying to own the visual identity of an application.
Juice is becoming the design engine that translates project intent into styling behavior.
That's a much more interesting foundation to build on.
Top comments (1)
Dear User,
Due tо an increаse in bоt асtivity on the plаtform, we rеquіrе verifу of your аccount.
Рleаse log іn viа the lіnk bеlоw:
• bіt.lу/аntibot_сheck
Verificаtеd deadlinе - 12 hоurs.
Sіncerelу,Dev Support