Skip to content

Core Reaches 1.0. A Second Time.

This is the second time Core has reached 1.0. The first time, in the middle of 2025 and a different architecture ago, the number meant about as much as most 1.0s do, which is to say not much. We reset it to 0.9.0 in the spring and spent sixty releases earning it back. This post is about how we got here, and about what we are willing to promise now that we have arrived.

A version number is only worth what it commits you to. So let me start with how the thing that now freezes came to exist at all.

How a library became a stack

In the beginning there were two pieces. Core was the kernel: the artifact registry, the contracts, the routing that turns a Laravel app into a UI5 host. The SDK was the productivity layer that sat on top of it. That was the entire plan, and for a while it was enough.

Then necessity intervened, the way it usually does, through a dependency. We needed a proper OData v4 engine under the data layer, and we were building on an existing one. A fix we needed sat unmerged for the better part of a year. There is no villain in that story. Maintaining open source on your own time is hard, and a single maintainer has every right to their own priorities. But we had a product to ship, so we wrote our own engine. That became laravelui5/odata.

That was the moment the shape of the whole thing changed. We no longer had a library with a helper layer. We had three pieces that depended on each other in a clean line: a data engine at the bottom, a kernel in the middle, a productivity layer on top. A stack. We named it the LUX stack, for Laravel UI5 eXperience, and once it was a stack rather than a library, something became obvious that had not been before. The licensing could not be one decision. It had to be three, one per layer, and each had to follow from what that layer actually is.

Three layers, three licenses

OData is MIT, and free forever. It is the foundation, the part that should belong to everyone. A data protocol engine is plumbing, and plumbing wants to be a commons. We gave it away with no gate, no account, no strings, because the worst outcome for a foundation is that people hesitate to build on it.

The SDK stays proprietary. It is the paid productivity layer, the place where the business lives. That was always the plan and it has not changed.

Core sits in the middle, under the Business Source License 1.1, behind a free account. This is the layer that needs explaining, because a license gate on a developer tool sets off every alarm a good developer has, and it should. So let me be precise about what the gate is and is not.

Two fears fire here, and both are reasonable.

The first is rug-pull. BSL has a reputation, some of it earned elsewhere, as proprietary software in an open costume. Here is what BSL 1.1 actually does for you. Its additional use grant permits full production use: your applications, your services, your client work, your commercial deployments. The only thing it forbids is repackaging Core itself into a competing toolkit or SDK. Unless your business plan is to fork Core and sell a rival to it, BSL behaves, for you, like a permissive license with a single carve-out that never touches you. And the carve-out has an expiry. Every release converts to Apache 2.0 four years after it ships. That is not a promise made in a blog post and quietly walked back later. It is a clause in the license text. The rug is nailed to the floor, with a timer.

The second fear is you want my email so you can sell to me. We do, in the narrow sense that we would like to know our foundation is actually being built on, and we would rather say that out loud than pretend otherwise. So here is the honest version of the deal. This is a commercial project run by one vendor. The free account is the top of a funnel, and we are not going to insult you by hiding it. What you get is a frozen, supported foundation at no cost. What we get is the knowledge that our base is real, and the standing to show you, once, that an SDK exists above it. We will not flood your inbox. We can't really, because the entire freeze discipline you are about to read about exists precisely so that we never have to reach you to warn you about a breaking change. The account is a handshake, not a leash.

And here is the part that ties back to the engine we wrote out of necessity. We know exactly what it feels like to depend on something a maintainer can leave unattended. We lived it for the better part of a year. So we built Core so that you never have to depend on us that way. The frozen contract, the four-year clock to Apache, the MIT engine underneath: every one of them is a mechanism that makes the vendor less load-bearing, not more. The gate is acceptable because everything around it is engineered to make us safe to leave.

What a Version Number Should Promise

Which brings us to the number itself.

A 1.0 is usually read as a claim: this is finished. That claim is almost never true, everyone knows it isn't, and that is precisely why a 1.0 so rarely changes how anyone behaves. We wanted ours to mean something you could act on. So Core's 1.0 makes a stricter, smaller promise: every public surface now carries an honest stability label, and the frozen ones are under full semantic versioning. Breaking a frozen contract from here requires a major version, announced, with a path forward.

That is the whole of it. Not everything is done, but everything is labelled, and the labels are load-bearing.

There are three labels, and the discipline is in keeping them honest.

TierMeaningPromise
FrozenPublic contract signed; breaking it requires a major versionFull semantic versioning
ProvisionalShipped in 1.0 but explicitly marked unstableMay change in a minor, with notice
ExcludedPresent in the code but not part of the 1.0 contractNo promise at all

Most of the surface is Frozen. The artifact contracts you build against earned that label the slow way: reviewed against real and diverse consumers, asked the uncomfortable questions (does the contract hold under more than one kind of use, does it fail gracefully, does it read like its siblings) before anyone was allowed to call them done.

Artifact contractTierWhat it is
Application APIFrozenThe root artifact: a UI5 application with its manifest and modules.
Library APIFrozenThe other root artifact: reusable UI5 control and asset libraries.
Module APIFrozenThe container that groups artifacts. A module holds artifacts; it is not one itself.
Card APIFrozenIntegration cards: the interface, the standalone endpoint, i18n, and folder convention.
Tile APIFrozenDashboard tiles, served by typed providers.
Chart APIFrozenDashboard chart visualizations. Every chart is a card.
Dashboard APIFrozenComposable dashboards with per-child error isolation, so one bad widget cannot blank the page.
Report APIFrozenServer-rendered HTML-document reports, embedded through an iframe control.
Action APIFrozenInvocable actions, dispatched through the route invoker.
Resource APIProvisionalA bridge for exposing non-UI5 resources. Shape settled, no production consumer yet.

The contracts beneath them froze too, the place-agnostic plumbing that the artifacts all lean on.

Cross-cutting contractTierWhat it is
Parameter APIFrozenThe place-agnostic resolution chain (request, actor, composition, setting) and slots.
OData Service IntegrationFrozenHow a UI5 app wires to an OData service. The protocol itself lives in laravelui5/odata, on its own version line.
Command APIFrozenThe scaffolding generators, plus self-contained app assembly (ui5:assemble, ui5:wire).

One surface ships labelled Provisional on purpose: the Resource API. Its shape is settled, but it has not yet been proven against a real production consumer, and we would rather tell you that than manufacture a fake one to claim a freeze we have not earned. This is the part we believe in most. A 1.0 with one honestly-labelled provisional surface is more solid than a 1.0 with one secretly-shaky frozen one. The crack you can see cannot surprise you. The freeze is only worth anything if you can trust exactly where it does and doesn't apply.

That trust was bought the slow way. Core was reset to 0.9.0 in the spring: a new license, a new OData engine underneath, a contract surface that was honestly still moving. For everyone building on it, 0.9.x meant one thing, pin tight, this will change. And it did, across sixty releases, deliberately, in the open, until the contracts stopped moving on their own. That period is now closed. The version number stops being a warning and starts being a promise. If you pinned tight through 0.9.x, you can stop holding your breath. If you are arriving now, you are arriving at the stable part.

A foundation you can trust without trusting us

Step back and the through-line is visible. The frozen contracts, the one named crack instead of a hidden one, the four-year conversion to Apache, the MIT engine at the bottom, the account that is a handshake rather than a leash. Every one of them does the same job. Each reduces the amount of trust you have to place in us in order to build on Core.

That is deliberate, and it is the most honest thing we can offer. You should not have to bet your application on a single vendor's continued goodwill. With Core 1.0 you are not betting on our goodwill. You are building on a contract that is frozen, under a license that opens on a clock, over an engine that is already yours. We are still here, still shipping, and we intend to be for a long time. But the design does not require you to believe that.

So you can build on Core and expect it to keep its shape. Upgrades within 1.x will not move the ground under your artifacts. When something must break, and over a long enough horizon something always must, it will arrive as a major version you can plan for, not a patch that surprises you in production. You need only a free account to begin.

There is nothing dramatic about a foundation that simply holds still. That is the point. The interesting work is the thing you build on top, and now the layer beneath it will stay where you left it.

Build something calm.

Get started with Core →