development_tools
Inspect a running site's dispatch rules, template resolution, source, composition,
and available model APIs. Combine this model with model#development_capture
when conditional or lazy rendering needs runtime evidence.
For local and remote workflows, see the LLM site development guide.
Access
All endpoints require an administrator with use mod_development permission
and a site environment of development, test, or acceptance. Production
is denied, including trusted CLI calls. Read-only administrators can use these
inspection endpoints.
Inspection does not render pages, edit source, or deploy changes. Template composition may compile an indexed template to obtain its metadata.
Browser quick start
Authorized pages with the development head assets expose
window.z_development_tools. Inspection requires neither a capture attachment
nor a visible debug button.
const tools = window.z_development_tools;
const route = await tools.dispatchTrace();
const template = await tools.template('page.tpl', 'article_resource_name');
const source = await tools.templateSource('page.tpl', 'article_resource_name');
const composition = await tools.templateComposition('page.tpl', 'article_resource_name');
All methods return promises containing the model result. Model errors reject
with error.code; transport failures also reject.
| JavaScript method | Result |
|---|---|
dispatch() | Active dispatch rules. |
dispatchTrace(path?) | Dispatch trace for a local path; defaults to location.pathname. |
template(name, id?) | Winning template and indexed override candidates. |
templateSource(name, id?, {candidate}?) | Selected candidate's metadata and UTF-8 source. |
templateComposition(name, id?, {candidate}?) | Selected candidate's inheritance, local blocks, and literal includes. |
templates({prefix, offset, limit}?) | Paginated indexed template names and winning locations. |
modules() | Active modules and priorities. |
models({prefix, offset, limit}?) | Paginated available models and exported callback methods. |
modelDocumentation(name) | Model documentation, availability, transport patterns, and incomplete GET-path hints. |
Template selection and source
Use relative indexed template names, never filesystem paths. The optional id
is a resource ID or name and applies the same category selection as catinclude.
Lookup returns the resolved name, winning filepath, and candidates in module
priority order. Lower numeric priorities win.
Source and composition accept a zero-based candidate position from that list.
Omit it for the winner; pass undefined for the resource when selecting a candidate
without category lookup:
const current = await tools.templateSource('page.tpl');
const next = current.candidates.find(c => c.candidate === current.candidate + 1);
if (next) {
const parent = await tools.templateSource(current.name, undefined, {
candidate: next.candidate
});
}
Use the next candidate to follow {% overrules %}. Each request resolves the
index afresh. Source results include source, candidate, module, priority,
and winner_filepath; filepath identifies the file actually read. Source
reading performs no rendering or compilation and is limited to 1 MiB of UTF-8.
Static composition
Composition uses compiler metadata and may compile the selected file. It does not render templates or evaluate runtime inheritance arguments.
| Field | Meaning |
|---|---|
inheritance | type is none, extends, or overrules; a resolved parent is in target, or lookup failure in error. |
blocks | Names defined in this file, not inherited or effective blocks. |
includes | Literal references with template, line, column, method, and is_catinclude. |
analysis | static. |
blocks_scope | local. |
includes_scope | literal_references. |
Include methods are normal, optional, or all. Dynamic include names,
conditional choices, and resource category selection at include call sites are
not resolved. Follow parent targets and include names with further lookups;
track visited files to avoid cycles. A missing parent is reported in
inheritance.error; compilation errors fail the request.
Discover model APIs
const models = await tools.models({prefix: 'rsc', offset: 0, limit: 50});
const api = await tools.modelDocumentation('rsc');
Model names omit m_. Discovery includes core and active-site models, honoring
the site's effective resolution and core-model precedence. Entries identify
name, erlang_module, owning module, filepath when available, load
availability, and exported get, post, or delete callback methods.
Documentation comes from BEAM metadata with a source fallback. The result
includes Markdown documentation, documentation_available, methods,
mqtt_topic, http_url, and path_hints. No model callbacks are invoked to
probe supported arguments or schemas.
path_hints_complete is always false. Hints can omit delegated or dynamic GET
paths and do not describe POST/DELETE schemas. A segment named any is a
placeholder. Exported callbacks and path hints do not grant permission to call
them. Unknown or inactive model names cannot be used to inspect arbitrary Erlang
modules or files.
HTTP and MQTT reference
All operations use GET. HTTP paths start with
/api/model/development_tools/get/; supply arguments as query fields. Browser
MQTT topics start with bridge/origin/model/development_tools/get/; supply
arguments as the payload object.
| Path | Arguments |
|---|---|
dispatch/list | None. |
dispatch/trace | path: local absolute URL path, including any language prefix. |
template/lookup | name, optional resource id. |
template/source | name, optional id and candidate. |
template/composition | Same selection as source. |
templates | Optional prefix, offset, limit. |
modules | None. |
models | Optional prefix, offset, limit. |
model/documentation | name without m_. |
Pagination defaults to an empty prefix, offset 0, and limit 50. Limits range from 1 to 200; offsets must be nonnegative. Dispatch tracing stays within the selected site and does not render its controller. Erlang tuples in dispatch results become JSON arrays.
HTTP JSON and MQTT response payloads use {status: "ok", result: ...} or
{status: "error", error: ...}. Common errors are:
| Error | Meaning |
|---|---|
eacces | Missing administrator/module access or unsupported environment. |
badarg | Invalid path, template name, selector, or pagination. |
enoent | Missing resource, template, candidate, source file, or model. |
too_large | Template source exceeds 1 MiB. |
invalid_utf8 | Template source is not valid UTF-8. |
unavailable | A discovered model implementation cannot be loaded. |
CLI
Run from the server checkout, locally or through SSH:
bin/zotonic inspect mysite dispatch
bin/zotonic inspect mysite dispatch-trace /nl/news/example
bin/zotonic inspect mysite template page.tpl article_resource_name
bin/zotonic inspect mysite templates _article
bin/zotonic inspect mysite modules
These CLI operations do not compile or render templates. Source, composition, and model documentation are available through JavaScript, HTTP, and MQTT.