← Back to blog

We Open Sourced the Foundation of Cordango

The beta is live, we're raising, and the layer underneath the whole thing is now Apache-2.0 on GitHub. Here is what 437 lines of YAML actually turn into, and why giving this part away is the most useful thing we've done all year.

Thinking out loud
We Open Sourced the Foundation of Cordango

I lost a weekend in June to a spreadsheet. Liquidity plan, five years, three scenarios, the thing you end up building the moment investors start asking questions with numbers in them. Somewhere around the third broken cell reference that quietly pointed at the wrong month, I gave up and did something that felt stupid at the time. I rebuilt the entire plan as a Cordango app instead.

Sixteen entities. Scenarios, periods, cohorts, hiring lines, funding rounds, cost lines, a running cash balance that reads the row before it. It took an evening, and it has been the only version of our plan I've trusted since.

That app is now sitting in a public repo with our real numbers swapped out for fake ones. It's called budget-planner, and it's the largest of the five examples we shipped.

What's actually open now

Three things, as of this week:

The org is at github.com/cordango if you want the whole thing.

Cordango itself, the platform companies run their applications on, is still the product. It's in invite-only beta at cordango.com and we're raising money to build it out properly. But the layer underneath it, the part that decides what an application can even be, belongs to everyone now.

One file, and what happens to it

The screenshot at the top of this post is scenario.cordango.yaml from that budget planner. Forty lines in you've seen the entity name, its icon, whether it's a collection, and a handful of fields with their types and their colours. Keep scrolling and you hit the part that's actually interesting: fields that aren't stored at all. total_funding is a sum rolled up from every funding round attached to the scenario. runway_months is cash at plan end divided by average monthly spend. Nobody writes that query. You write what the number means, and the compiler works out the rest.

That's the idea, but a file doesn't prove much on its own. The build does.

Take expenses, the smallest complete example in the repo. Fourteen YAML files, 437 lines all in. One entity, an approval lifecycle, three roles that genuinely see different things.

cordango build --target standalone --out ../expenses-app
cd ../expenses-app
docker compose up --build

What comes out is 56 C# files and 33 Vue components. Roughly 8,700 lines of ordinary code in an ordinary repository, with an ASP.NET Core API, EF Core migrations you can sit down and read, a Vue 3 and Vuetify front end, sign-in, per-field permissions enforced on the server rather than hidden in the UI, and a demo dataset. Open localhost:8080 and the first screen asks you to create the administrator account. There's no default password and none is generated for you, because default passwords are how this stuff ends up on Shodan.

Then delete the toolchain. The application still builds. No licence server, no account, no model API, nothing phoning home. That last bit matters more than anything else in this post, and I'll come back to it.

The thing I had backwards for about six months

I thought the hosted platform was the interesting half and the generator was a party trick. Something to wave at a procurement team when they got nervous. Build it once, demo it, move on.

That was wrong, and the conversations we had in spring told me so in almost the same words every time. Nobody wants to put the system their operations run on inside a platform maintained by a company our size. Completely fair. I wouldn't either.

What they will do is build on something they can walk out of, with the source in hand, on a Tuesday, without asking us. The exit clause turned out to be the product. Once I stopped treating the generator as marketing and started treating it as the load-bearing part, most of the roadmap rearranged itself.

Nothing gets dropped quietly

This is the rule I'd defend in an argument, and it's the one I'm proudest of.

If a target can't build something your definition asks for, the build stops. It doesn't shrug and emit 90 percent. You get a diagnostic code and the exact path in the definition that caused it. If you want the partial build anyway you pass --allow-incomplete, which says out loud that you know. Every gap then gets written into the generated README and recorded permanently in cordango.build.json, so a partial build can never quietly pass for a finished one six months later when nobody remembers.

The old low-code platforms didn't fail because drag-and-drop was ugly. They failed at the 80 percent mark, where the tool ran out of ideas and you spent the next three years gluing on the rest by hand inside somebody else's box. AI codegen fails differently and worse. It cheerfully hands you something that looks complete and isn't, and you find out in production.

Refusing to build is a terrible demo. It's a much better Tuesday.

Read the examples in this order

expenses first, because it's the smallest thing that's still a real application. Then time-off for an approval step and a duration the app works out for itself. Then task-manager if you want to see computed fields and parents counting their children, and room-booking for the trick where the rules live in a policy entity instead of being hard-coded somewhere awful.

budget-planner last. Sixteen entities, 94 files, a bit over 5,000 lines of definition, and it pushes the calculation plane harder than anything else we have. Cohort growth, rollups across a window, figures read across a reference. It's also the example that keeps finding bugs in our own compiler, which is exactly why I use it for real work rather than as a demo.

Where this honestly is

Pre-alpha, and I want to be blunt about that. dotnet-vue is the only target that works today. Node and Vue is next, Python and React are designed and not written. PostgreSQL is the only database. The standalone generator doesn't emit workflows, computed fields or command guards yet, which is why the examples README tells you to expect --allow-incomplete instead of pretending otherwise.

The schema will move. Things will break. It's on GitHub anyway, because a format that stays private until it's perfect is a format nobody ever stress-tested.

Why I think this one is a big deal

Not because open sourcing a compiler is novel. It isn't.

It's what the 437 does to the shape of the problem. And before anyone points it out: 8,700 lines is small. A real internal application, the kind with fifteen entities and two integrations and six years of edge cases baked into it, is many times that. Which is exactly why the number is worth looking at. expenses is the smallest complete application you can build, and it already emits more code than a person is going to read. Scale it to something a company actually runs on and the definition grows to a few thousand lines while the generated code goes somewhere nobody is reviewing anything.

Underneath, it's the same shapes every time. Records, permissions, a state machine, a few screens, an audit trail. We have paid people to retype that, badly, for thirty years, and then paid a SaaS vendor per seat per month when we got tired of retyping it.

437 lines is small enough that a person reads all of it in a sitting. Even the budget planner, sixteen entities and a bit over 5,000 lines of definition, is one long afternoon. What comes out the other side is never readable at any size, and that gap is the whole argument. You can review intent. You cannot meaningfully review a generated codebase at volume, and anyone telling you their team reads AI output line by line is describing a policy, not a habit.

So the split that actually holds up has AI writing the definition, which is small, reviewable, and full of decisions a human should be making, while a deterministic compiler writes the code, which is large, boring, and has no decisions left in it. What it does not look like is "AI writes your application", which is the version everyone is selling and the version nobody can review. Same definition and same generator version, same bytes out, every time. CI generates a fixture twice and compares them. That isn't a nice property to have on the side, it's the thing that makes any of this reviewable at all.

And the reason the foundation is Apache-2.0 rather than source-available with teeth in it: a format that decides what a company's software is allowed to express should not be one small startup's private property. If we get funded and this works, great. If we don't, the definitions still compile, the applications still run, and nobody's operations are hostage to whether my round closed.

What I'd genuinely like right now, in order. Run cordango new expenses, then docker compose up --build, then tell me what the vocabulary can't say that your actual business needs it to say. That last one is worth more to me than a star. Issues is the place for it, and if you'd rather just argue about the schema, discussions is open too.

I'll take either. The spreadsheet is still on my drive as a backup, and I would very much like to delete it.

Smoower logo Smoower

Know what your DevRel team should ship next

Smoower watches your repos, releases, and issues, plus what devs say about you on Reddit, Hacker News, and YouTube. Each teammate gets the next task worth doing and a draft worth shipping, with the source signal attached.

See a sample draft →