~/portfolio/blog — nodot,_and_why_godot_should_never_bless_
build: ok v0.4.7
← cd ../
guest@portfolio:~/blog$ cat 2024-01-nodot-component-libraries.md
2024.01.22

Nodot, and why Godot should never bless a single component library

#godot · #nodot · #open-source ·7 min

Someone on r/godot wrote a thoughtful post suggesting the core team adopt Nodot — my component library — as an official addon, or ship something like it in the box. I replied briefly because I was on my phone. This is the long version.

The short answer: thank you, please don’t, and here’s why.

Long story short, nobody cares

I’ll start with the unflattering part. The library has been public for a while. The traffic is fine. The contributions are not. People come to Godot, poke at the default nodes, watch a YouTube tutorial, and start reinventing the first-person controller for the ten thousandth time. A few port code over from Unity or Unreal and never look back.

That isn’t a complaint about users — it’s a description of the incentive landscape. A first-person controller you write yourself teaches you the engine. A first-person controller you drag in from a library doesn’t. New developers are correctly trading time for understanding. The component-library audience isn’t beginners. It’s the people who already know the engine well enough to be bored of writing the same scene three times.

That audience is small. It will always be small. That’s fine.

The bugs are mine, but the limits are not

Nodot has real issues. Most of them trace back to two underlying constraints:

  1. Node option configuration in Godot is fragile. Exported properties with custom inspectors, conditional visibility, and per-instance defaults all work most of the time and then suddenly don’t. I have nodes that present the wrong inspector after a scene reload until you click off and click back. I have @export_group blocks that mis-render under specific orderings. These are upstream paper cuts, not architectural mistakes, but they show up in my library because my library leans on those features harder than most.

  2. My nodes are too interdependent. A clean component model is “this node can stand alone, and composes with others through well-defined sockets.” Several Nodot nodes silently assume a sibling or an ancestor of a specific type. When that assumption holds, the developer experience is magical. When it doesn’t, the error is a null somewhere three nodes deep. That’s a design debt I’m paying down slowly — not a Godot problem.

Development continues slow and steady. I’m building a real game on top of the library, which is the only honest way to find out what the abstractions get wrong. PRs and design discussions are very welcome.

Why Godot shouldn’t pick a winner

This is the part I care about most.

A component library is an opinion. It says “here is what a player is, here is what an inventory is, here is what a vehicle is.” Those definitions are useful precisely because they’re opinionated — they make a thousand small decisions for you so you can ship.

But the right opinion depends on the game. My player node assumes twin-stick or first-person control, a physics body, and an inventory. That’s wrong for a turn-based strategy game. It’s wrong for a 2D rhythm game. It’s wrong for a visual novel. If Godot shipped my opinion as the default, every developer outside my target shape would either fight it or quietly write their own — and now the engine has two ways to make a player, one official and one real.

Anyone who’s done web dev has lived this. React has Material UI, Chakra, shadcn, Radix, Mantine, Ant. None of them is the “official” component library and that’s a feature. Each is opinionated about different things — accessibility-first, headless, design-system- first, density, theming. Picking one is a real architectural decision that depends on what you’re building. If React had blessed one of these in 2018, the others wouldn’t exist and we’d all be worse off.

Godot’s job isn’t to make that choice for the community. It’s to make sure building a Nodot — or a competitor to Nodot — is as frictionless as possible. That means:

  • A stable, well-documented inspector and property system so library authors can build rich editor UX without fighting the engine.
  • Better tooling for plugin authors to publish, version, and update.
  • A package registry that doesn’t depend on cloning a GitHub repo into addons/.
  • Class-name registration that doesn’t break when two addons reach for the same identifier.

Fix those, and a dozen Nodot-style libraries appear within a year. Each will be wrong for most projects and exactly right for a few. That’s how a healthy ecosystem looks.

What I’d actually like to see

If the core team has cycles for this, the highest-leverage move isn’t to adopt my library. It’s to make plugin authoring a first- class workflow:

  • A package manager that handles dependencies, version constraints, and updates from inside the editor.
  • A way for an addon to register custom nodes that survive renames and refactors.
  • Inspector primitives that handle conditional visibility, grouped exports, and per-instance overrides without hand-rolled _get_property_list gymnastics.
  • A standardised way for addons to declare compatibility with engine versions so users aren’t surprised.

Give me those, and Nodot becomes better. Give those to ten other people who disagree with me about what a node should be, and Godot gets ten better libraries to choose from.

That’s a much better outcome than a single library — mine or anyone else’s — getting frozen into the engine and slowly aging into the way things were always done.

So: thanks for the kind words, and for caring enough to write the post. Please don’t ship my opinions as defaults. Help the rest of the community ship theirs too.