Well, we did it.
Sig.js is officially at version 1.0 and available on npm.
And I have to admit, this one feels pretty good.
I've spent a lot of time writing about KiwiEngine, its architecture, its individual libraries, and the philosophy behind building a system from smaller, focused components.
I've talked about why I want to build an engine instead of another collection of loosely connected utilities.
I've talked about intentional programming, abstractions, responsibility, and giving developers more control without making them rebuild everything.
But eventually, all that thinking has to turn into something.
Something that works.
Something that can be installed.
Something that other developers can actually use.
Today, Sig.js crossed that milestone.
From An Idea To A Published Library
For anyone who hasn't been following the series, Sig.js is the reactive UI library I've been developing as part of KiwiEngine.
It's built around signals and a lightweight JSX rendering model.
The goal is to make reactive interfaces understandable without requiring an enormous framework around them.
At its core, I wanted something that could answer a fairly straightforward question:
When application state changes, how does the interface respond?
That sounds simple.
And conceptually, it is.
But once you start building a reactive rendering system, the questions get considerably more interesting.
How are dependencies tracked?
How do effects respond to changes?
How do components manage their lifecycle?
What happens when something gets removed from the interface?
How should rendering and cleanup work together?
How do you prevent the abstraction from becoming more complicated than the problem?
Those are the kinds of questions that shaped Sig.
Sig Is More Than A Signals Utility
One of the important developments along the way was establishing Sig as more than a small reactive state library.
Signals are the foundation.
But the library also provides the machinery needed to build interfaces around them.
That includes:
- Reactive signals and effects
- Derived values through memoization
- A JSX runtime
- Component mounting and cleanup
- Reactive DOM behavior
- A lightweight router
- Integration with Juice
These pieces give Sig a much clearer identity.
It's not trying to become an entire application framework.
It's becoming a focused reactive UI engine.
And that distinction matters.
The JSX Runtime Was A Big Step
I wanted KiwiEngine to have a way to describe interactive interfaces without requiring another framework to own the rendering model.
JSX gives me an expressive way to describe the interface.
Sig handles the reactive behavior underneath it.
That's a useful separation.
The syntax describes what should appear.
The reactive system determines how the interface responds to changing state.
The renderer handles the relationship with the DOM.
And lifecycle behavior makes sure the system can clean up after itself.
That last part is especially important.
It's relatively easy to make a counter update.
It's considerably harder to make an entire application behave predictably as components appear, disappear, and change.
That's where the real engineering starts.
The Relationship With Juice Is Becoming Real
Another part of this release that I'm excited about is the integration with Juice.
I've written quite a bit about Juice recently.
Juice is becoming the design and styling engine within KiwiEngine.
It translates design intent and configuration into styling behavior.
Sig handles reactivity.
Those are different responsibilities.
But interfaces need both.
A checkbox might have a visual state.
A disclosure might open or close.
A modal might become visible.
An interactive control might need to communicate its state back to the application.
The Sig and Juice integration creates a way for those systems to work together without turning them into one enormous library.
And importantly, that integration is optional.
Sig doesn't have to become Juice.
Juice doesn't have to become Sig.
They can remain independent systems that become more capable when composed.
That's exactly the architecture I've been trying to build.
Getting To Version 1 Wasn't About Adding Everything
This is probably the biggest lesson of the release.
There are still things Sig doesn't do.
There are still things I want to explore.
There are still experimental APIs.
And there are capabilities that I've deliberately decided don't belong in this first stable release.
For example, server-side rendering isn't part of Sig 1.0.
Neither is a virtual DOM.
I'm not trying to reproduce every abstraction available in other UI frameworks.
I'm trying to establish a focused model that makes sense for Sig.
Some capabilities may arrive later.
Some may never belong.
And that's okay.
A library doesn't become mature simply because it has more features.
Sometimes maturity means becoming more comfortable with its limitations.
Version 1 Is A Commitment
I've said this before in the series, but I think it's worth repeating.
Version 1.0 doesn't mean a library is finished.
It means something closer to:
I understand what this library is, and I'm ready to establish a dependable foundation around that understanding.
For Sig, that means the stable public API now carries a stronger compatibility commitment.
Changes need to be more deliberate.
Breaking existing behavior has consequences.
Documentation becomes more important.
Testing becomes more important.
The developer experience becomes more important.
It's no longer just a collection of experiments I can freely reshape whenever another idea comes along.
It's a library with a public contract.
And that's a different kind of responsibility.
The Release Was About Stabilizing, Not Reinventing
Something I particularly like about this milestone is that version 1.0 didn't require inventing a completely new API.
The release formalizes the API developed through the previous 0.7.x work.
That's how I want these libraries to mature.
Experiment.
Build.
Test.
Refine.
Use the library.
Discover where the abstraction is awkward.
Improve it.
Then, when the design becomes stable enough, establish that contract.
I don't want version numbers to become a marketing exercise.
I want them to mean something.
Testing Outside The Monorepo Matters
There's another important part of releasing a library that can be easy to overlook.
It's one thing for a package to work inside the repository where it was developed.
It's another thing for someone to install it from npm into an independent project.
That distinction matters.
A library shouldn't require mysterious workspace configuration or internal repository knowledge just to get started.
For this release, the standalone counter example was tested against the published npm package.
That included installation, TypeScript checking, and building the application.
It's a small example.
But it proves something important.
Sig isn't just a piece of the KiwiEngine repository.
It can exist as a published package that developers install and use.
That's a meaningful step toward the kind of modular ecosystem I want.
You Can Install Sig.js Now
Sig.js 1.0 is published under the CitrusWorx npm scope.
npm install @citrusworx/sigjs
The package includes its reactive core, JSX runtime, router, and optional Juice integration.
You don't need to adopt all of KiwiEngine just to explore Sig.
That's intentional.
I've always wanted the individual libraries to have their own identities and responsibilities.
They should be useful within the larger ecosystem.
But they shouldn't exist only because the larger ecosystem exists.
This Is A Milestone For KiwiEngine Too
This is the part that makes the release especially exciting to me.
Sig reaching 1.0 isn't just a milestone for Sig.
It's progress toward KiwiEngine becoming the engine I've been describing throughout this series.
Because an engine needs dependable components.
Not just promising prototypes.
Not just architectural diagrams.
Not just ideas about how everything might work together someday.
It needs actual systems with defined responsibilities and stable interfaces.
Juice is continuing toward that point.
Nectarine is developing its role.
Seltzer is establishing its communication boundaries.
WebEngine is bringing the pieces together.
And now Sig has reached its first stable major release.
One of the components is ready to stand on its own.
That's real progress.
Now I Get To Build With It
This is probably what I'm looking forward to most.
I've spent a lot of time building tools for building things.
And I enjoy that.
I genuinely enjoy architecture.
I enjoy thinking about APIs.
I enjoy designing systems.
But I also have a lot of applications I want to create.
Blackwater Sound.
WebStore.
Artist platforms.
Music software.
Interactive creative tools.
Applications that support my other businesses and projects.
Sig is part of the foundation that will help me build those things.
And now I have a stable release I can begin depending on.
That's the payoff.
Not the version number by itself.
What the version number allows me to start doing.
The Road Doesn't End At 1.0
There's still plenty of work ahead.
Sig will continue evolving.
There will be bugs to fix.
Documentation to improve.
Patterns to discover through real applications.
And probably a few architectural assumptions that real-world usage will challenge.
That's part of building software.
But the nature of the work is changing.
I'm no longer only trying to figure out what Sig should become.
I'm beginning to build on what it already is.
And that feels like a pretty significant milestone.
Sig.js 1.0 is here.
One library has reached a stable foundation.
One more piece of KiwiEngine is ready.
And the engine is getting closer to doing what I built it for in the first place.
Helping me build the things I've been imagining.
Top comments (1)
Grat for 1.0
Bit better if you write personally about your program instead of AI. Maybe found your voice by AI and train to write in your style. No man write in this style or I am make mistake?