Template store & hot reload
The store
Templates live behind the templates.Store interface (Fetch/List/Put). The loaded store is a fallback store — a chain of sub-stores (one per loader type) tried in order — so a name resolves to the first loader that provides it.
Loading
StoreLoader.loadTemplatesMap (app/templates/fileloader/store_loader.go):
- loads plain templates from the templates directory using the ordered loaders (file → raw → remote-http);
- builds dependent loaders (compositions) that need the already-loaded store;
- loads compositions from the compositions directory;
- combines everything into the fallback store.
Per directory, loaders are tried in priority order; “not found” errors are non-fatal (try the next loader). With --templates-recursive, loading descends into nested directories, naming children parent/child.
The LazyStore seam
The internal render server needs the store to serve assets, but the store is built later in the DI graph. A LazyStore implements both StoreProvider and StoreConsumer: Wire binds one instance to both interfaces, the store loader fills it, and the internal server reads it. This is the late-binding seam that lets the graph wire up before the store exists.
Hot reload
--templates-reload-mode:
none— a staticMapStorebuilt once at startup (production default).always— aDevStorethat re-reads the template from disk on every fetch, so edits take effect without a restart (development default).
Engines & loaders
Engine dispatch (instance_loader.go) tries engines in priority order per part (body/header/footer), first match wins. Sibling loaders handle schema, params, assets, examples, and partials. The composition sub-package holds the YAML/jq and JS planners and the pdfcpu merge; the remote sub-package holds the HTTP template loader.
See Extension points to add a new engine, loader, or planner.