Hackable Architecture - bryanedds/Nu GitHub Wiki

One of the features of Nu that makes it particularly hackable is its (literally) straightforward architecture. There are very few circular dependencies within any modules, and none at all in-the-large. In the same way that static typing eliminates entire categories of bugs, functional semantics eliminates entire categories of complexity - and this is visible from Nu's architecture:

This visualization was generated from actual build artifacts using this script. Each node is a folder in the Nu project (the Core folder is omitted for clarity). Note that every dependency only ever points downward from the most abstract modules to the most concrete, forming a dependency graph that is entirely directed and acyclic.

This is made possible by a feature of F#, inherited from ML, which is rare in modern languages: types, values, functions, and modules must always be declared prior to their ever being referenced (except within a single file using the and keyword). This enforces a level of architectural rigor that would otherwise be difficult to maintain.

This imparts several benefits for anyone interested in hacking or contributing to Nu:

  • studying Nu fully is a matter of opening the project and reading the code from top to bottom like a book,
  • changes to code only ever have downstream effects.

While Nu doesn't (currently) provide extensibility by way of a highty granular plugin system, it is comparatively simple, for example, to add new rendering capabilities by adding a new case to the RenderMessage3D type. The resulting compilation errors and warnings serve to guide, to a large extent, the areas of the code that must then be implemented.

Engine Modification as a User Story

One of Nu's strengths is how its simplicity and truly open nature makes engine modification a valid and preferred approach for certain types of user scenarios.

When you make a system hyper-extensible with tons of hooks or even an uber-pluggable model, you also significantly increase the complexity of that system, ironically sometimes to the point of making it significantly harder to modify and extend. Providing additional hooks and even a powerfully scriptable API can work in some situations, but at least as often as not, just makes the system overly complex. In these cases, it's often better to just expose the source, keep the system as simple as possible, and use that simplicity as leverage for end-users to modify the system to their heart's desires. Best of all, in a surprising number of cases, much if not all of those users' local changes can be upstreamed back into the engine by leveraging the engineering understanding surfaced by the user's implementation process either as an additional feature path in the engine or as an augmentation of the existing semantics.

The primary means by which we keep Nu as modifiable as possible is by keeping it as small, simple, and lightweight as possible. As of 2026, we could have started implementing features like integrated networking, world-streaming, a user-customizable render graph, and some form of dynamic global illumination, but we didn't because - a) these are big features with big investment, maintenance, and complexity costs, and b) neither we nor any of our users needed any of that for the games we're actually building. Instead, we've chosen to make Nu as modifiable as possible in cases users want to implement these or any number of other capabilities we can't necessarily anticipate.

By keeping the engine smaller, simpler, and lighter-weight than the typical general-purpose game engine, it can be much more tailorable than otherwise.