Concepts

Core and ext

Two repositories and one runtime: what belongs in core, what belongs in ext and how the folders are laid out.

Two repositories, one runtime

Nimbly splits every project into two separate git repositories that live nested on disk:

Repository What it is Who owns it
core The Nimbly framework - routing, template engine, shortcodes, admin, API Nimbly (never modified per project)
ext Your application - routes, templates, data, custom shortcodes You (every project has its own ext repo)

On disk they combine into one directory tree:

my-project/          ← core repo root
  core/              # Framework internals
  ext/               ← ext repo root (nested inside core)
  css/               # CSS source (shared build)
  js/                # JS source (shared build)

This means git status at the project root reflects core changes; git status inside ext/ reflects application changes. They are independent repos with independent histories, branches, and remotes.

They are also licensed separately: core is open source under the ISC license, while every ext repo is proprietary - copyright Nimbly Web Systems, all rights reserved - and carries its own ext/LICENSE.txt.

Deciding core vs. ext

The "never modify core" rule is about not bending core's existing framework code to fit one app. It is not a rule about where new framework-level features belong. Ask: would every Nimbly app need this, not just this project?

  • Yes → core. Built-in admin screens, generic resource CRUD, auth/roles/permissions, shortcodes any project could use. If getting basic functionality working in a new project would mean copy-pasting the same files into every ext repo, that's a sign the feature is stranded in the wrong place.
  • No → ext. This project's own resources, routes, business logic, branding, and config - anything that only makes sense for this specific application.

Concrete example of getting it wrong: the role editor (/nb-admin/roles/(id) and /nb-admin/roles/add) was originally built entirely in ext/uri/nb-admin/roles/, even though every other admin resource page (users, media, jobs, ...) is served generically from core/modules/admin/uri/nb-admin/(resource)/... with no per-project override at all. Roles/permissions are core to Nimbly's own permission system, not app data - so that route belonged beside debug/, media/, profile/ etc. under core/modules/admin/uri/nb-admin/, not in ext. Leaving it in ext meant every new project would have to hand-copy those files just to manage roles.

Directory layout

core/          # Framework - never modify
  lib/         # Core libraries and shortcode implementations
  modules/     # Core modules (admin, forms, api, install, user)
  tpl/         # Core templates (html wrapper, etc.)
  uri/         # Core routes
ext/           # Your application - all custom work goes here
  data/        # Resources (.meta + JSON records)
  lib/         # Custom libraries and shortcode implementations
  modules/     # Custom modules
  tpl/         # Reusable templates
  uri/         # Route templates
  static/      # Built assets (output of npm build)
css/           # CSS source
js/            # JS source (JSX/Alpine)

Rule: Never modify core/. All customization lives in ext/.

Rule: All text in core/ must be in English. Use [#text Key#] for every user-facing string so projects can supply translations via ext/data/.i18n/text.<lang>.po. Never hard-code Dutch or any other language in core templates.

View this page as Markdown