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 methodResult
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.

FieldMeaning
inheritancetype is none, extends, or overrules; a resolved parent is in target, or lookup failure in error.
blocksNames defined in this file, not inherited or effective blocks.
includesLiteral references with template, line, column, method, and is_catinclude.
analysisstatic.
blocks_scopelocal.
includes_scopeliteral_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.

PathArguments
dispatch/listNone.
dispatch/tracepath: local absolute URL path, including any language prefix.
template/lookupname, optional resource id.
template/sourcename, optional id and candidate.
template/compositionSame selection as source.
templatesOptional prefix, offset, limit.
modulesNone.
modelsOptional prefix, offset, limit.
model/documentationname 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:

ErrorMeaning
eaccesMissing administrator/module access or unsupported environment.
badargInvalid path, template name, selector, or pagination.
enoentMissing resource, template, candidate, source file, or model.
too_largeTemplate source exceeds 1 MiB.
invalid_utf8Template source is not valid UTF-8.
unavailableA 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.

Edit on GitHub