# mod\_development

Source: https://zotonic.com/docs/1457/mod_development

URI: https://zotonic.com/id/1457

Language: en



Inspect and debug running Zotonic sites. Enable this module to add **System > Development** to the admin, with template and dispatch inspection, tracing, source-editor integration, and development settings.
<!-- z-media 3091 {"alt":"The Development page with settings, source editor, template and dispatch debugging, introspection, and function call tracing.","caption":"-","size":"large"} -->
Choose a tool
-------------

| Task                                                                           | Tool                                                                             |
| ------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| Adjust development settings or inspect the site interactively                  | System > Development.                                                            |
| Inspect dispatch rules, indexed templates, source, composition, and model APIs | <a href="/id/doc_model_model_development_tools" class="doc-reference doc-reference-model"><code>model#development_tools</code></a>, through JavaScript, HTTP, MQTT, or the inspection CLI. |
| Capture templates and console output while interacting with an open page       | <a href="/id/doc_model_model_development_capture" class="doc-reference doc-reference-model"><code>model#development_capture</code></a>, through the browser API or floating trace button. |
| Configure template editor completion and go-to-definition                      | Language server integration below.                                               |
| Control existing admin diagnostics and source-editor launches                  | <a href="/id/doc_model_model_development" class="doc-reference doc-reference-model"><code>model#development</code></a>. |

For local and remote agent workflows, see the [LLM site development guide](../../../doc/guides/llm-site-development.md).

The inspection and capture APIs require administrator/module access and a `development`, `test`, or `acceptance` environment. They are unavailable on production even if the human trace button is enabled there. Read-only admins can inspect and read captures; capture mutations require write access. These restrictions are separate from the legacy recompile API setting below.

Debug options
-------------

The settings column contains these development options:

- **Show paths to included template files.** Add comments to generated templates showing the exact file included at each point.
- **Show defined blocks.** Add comments marking the start and end of each `{% block %} ... {% endblock %}` in generated templates.
- **Always hide the floating template trace button.** Hide the button in every environment. This takes precedence over the option to show it on production and acceptance sites.
- **Allow to show the floating template trace button on production and acceptance sites.** Make the button available outside development and test environments. It is still shown only to users with permission to use `mod_development`, and not on the development tools' own pages. In development and test it is available by default unless explicitly hidden.
- **Download CSS and JavaScript as separate files.** Generate separate `<link>` and `<script>` tags for the files in a `{% lib %}` tag. This makes debugging easier, but increases the number of requests needed to load a page.
- **Live reload of changed CSS files. Reload page on change of templates or JavaScript.** Update styles in the browser when CSS changes, and reload the page when a template or JavaScript file changes. Enabling this checkbox also enables downloading CSS and JavaScript as separate files. The development tools' own pages do not automatically reload on template or JavaScript changes.
- **Disable caching by the `{% cache %}` tag.** Bypass template cache blocks while checking changes. This does not disable other caches, such as browser caching or application data caches.
- **Trace all database queries for the current session.** Enable database query tracing for requests in your session. This checkbox requires `mod_server_storage`. Turn it off after investigating.
- **Enable API to recompile and build Zotonic.** Enable the legacy build/cache APIs, including `/api/model/development/get/recompile` for compilation and `/api/model/development/get/flush` for flushing caches. These APIs do not require authentication when enabled; use this option only on trusted development installations. The authenticated inspection and capture APIs do not require this option.
- **Show server log in the browser console.** Start forwarding server logs to the current browser tab's developer console. Stopping it stops console logging for all connected logging tabs on the site. This option requires `mod_logging` and permission to receive client logs. In development, the checkbox is replaced by a notice: admin pages show these logs automatically, and site pages can opt in with the `environment-development` class on their `<html>` element.

Open source file in editor
--------------------------

The second settings column configures opening templates in a source editor. This is either done by running a command to open a file, or by opening a browser URL. The editor can be chosen explicitly or detected automatically.

The local editor choice is stored in `config.d/zotonic-editor.config` under the node configuration directory and shared by development sites and shell helpers. Browser URL preferences and host-path mappings remain browser/site-specific. Choosing automatic detection clears the explicit machine choice. Detection uses trusted node configuration, ZOTONIC\_EDITOR/VISUAL/EDITOR, inherited editor sessions, file associations, running editors and installed launchers, in that order. Ambiguous detection requires a choice. Local browser-triggered launches require the development environment and the mod\_development permission.

Containers only launch through browser URLs. Configure a browser editor preset or custom URL and map the container source root to the host checkout root. Sublime and Vim URLs need an installed host-side protocol handler.

In the Erlang shell use `z:edit(mod_foobar)`, `z:edit(mod_foobar, function_name)`, `z:edit(StackTrace)` or `z:edit(<<"path/to/template.tpl">>, 42)`. Library and template names are resolved across running sites; ambiguous names require a full path.

A trusted zotonic configuration `development_editor` can contain an executable and argument list, for example:

```erlang
{"code", ["--reuse-window", "--goto", "{file}:{line}:{column}"]}
```

Set the zotonic configuration `development_editor_browser_only` to true to force browser launches on a remote host or a container that cannot be detected automatically.

### Node configuration

These settings belong to the global `zotonic` configuration, (so not to a site's configuration or the module configuration):

| Setting                           | Default      | Purpose                                                                          |
| --------------------------------- | ------------ | -------------------------------------------------------------------------------- |
| `development_editor`              | `undefined`  | Trusted `{Executable, Args}` command. When set, takes precedence over editor environment variables during automatic detection. |
| `development_editor_id`           | `<<"auto">>` | Saved candidate ID. An explicit ID overrides automatic selection; an unavailable choice is reported instead of silently falling back. |
| `development_editor_browser_only` | `false`      | Disables local discovery and launching, including shell helpers. Containers enforce this behavior regardless of the setting. |

For example, a node configuration fragment can contain:

```erlang
[{zotonic, [
    {development_editor, {"code", ["--reuse-window", "--goto", "{file}:{line}:{column}"]}}
]}].
```

The executable can be a name on PATH or an absolute path. Executable paths and arguments accept strings or UTF-8 binaries. Each list element is one argument; paths with spaces do not need embedded shell quotes. `{file}`, `{line}` and `{column}` are replaced within arguments, with positions starting at 1. When no argument contains `{file}`, the filename is appended. Commands are executed without a shell: shell variables, pipelines and command substitutions are not expanded. Terminal editors need a supported remote client or session.

Choose the local editor in Admin > Development to save `development_editor_id` in `config.d/zotonic-editor.config`. The choice applies immediately and is loaded again on restart. Automatic detection saves `<<"auto">>`; it does not remove a custom `development_editor` command. Avoid defining the saved ID in multiple configuration files. Use `z_config_files:config_dir()` in the Erlang shell to find the node configuration directory; deployments can override it with `ZOTONIC_CONFIG_DIR`. The generated file stores only the candidate ID.

Browser URL presets, custom URLs and source-root mappings are stored separately in the browser for the site. They are not node configuration settings. In Docker, map the source path inside the container to the corresponding checkout on the host and install any required URL handler on that host. Shell helpers cannot open the browser on the user's machine and return `{error, browser_only}`.

Language server (LSP) integration
---------------------------------

The template language server provides editor support for `.tpl` files using a running site's module and template indexes. It complements an Erlang language server; it does not provide language services for `.erl` files.

Supported features include:

- Syntax diagnostics for unsaved templates, without compiling or rendering them.
- Go to definition for literal template references, `extends` and `overrules`, including the next template in module priority order and symlinked sources.
- Definitions for filters, models, scomps, actions and literal delegates at their `event/2` handler.
- Hover information showing the reference type, site and matching source files, with symlinks resolved. Markdown formatting is used when the editor requests it; plain text remains available.
- Completion of template names, filters, models and built-in and custom tags.

Category includes list candidate templates: selecting the effective template requires a resource/category context. Formatting, rename and workspace references are not currently supported.

### Model path completion

Completion after a model name follows literal `m_get/3` path patterns and simple literal alternatives in guards. Bracket expressions such as `m.rsc[id].title` are treated as arguments without evaluating them. Suggestions also include common and computed resource properties, request keys from `m_req`, declared module configuration keys, and system keys from `z_config`. Configuration values are never fetched. Predicate names are suggested only with an explicitly selected site.

Static descriptions are cached by the loaded module checksum and refreshed after code reload. Models with dynamic paths or returned maps can supplement inferred paths with a `model_paths` attribute. Use binary keys and `any` for an argument:

```erlang
-model_paths([
    #{path => [<<"result">>, any, <<"title">>],
      description => <<"Title of the selected result.">>}
]).
```

This describes `m.example.result[id].title`. Metadata describes names and optional plain-text documentation only; the language server never calls `m_get/3` to probe a path. Arbitrary helper calls, runtime map fields and resource-specific custom properties are not inferred. Missing debug information falls back to the available source file; paths without either source are omitted.

### Start and select a site

Compile and start Zotonic, and enable `mod_development` on the desired site. Configure the editor to start this stdio command:

```sh
/absolute/path/to/zotonic/bin/zotonic-lsp
```

This launcher requires Python 3 on the editor host. It probes the local node first, then checks running Docker containers and infers source path mappings from bind mounts. Multiple matching containers require an explicit `--container NAME`. Discovery runs only at startup; the launcher replaces itself with the selected process and adds no ongoing proxy. Use `bin/zotonic lsp` directly to skip discovery and connect to the local node.

Semantic lookups use the selected site when one is configured. Otherwise, filters, models and delegates are resolved across running development sites. Template references first use sites containing the current file; if no target is found, other running development sites are tried. Matching source locations and template priority orders are accepted without selecting a site. Conflicting targets still require an explicit choice. Completion combines suggestions from candidate sites, and syntax diagnostics do not require a site selection.

### Editor setup

The VS Code client is in `apps/zotonic_mod_development/priv/editors/vscode`. Run `npm ci` there and load it with VS Code's `--extensionDevelopmentPath` option, or package and install it as a VSIX. Configure automatic runtime selection with:

```json
{
    "zotonic.command": "/absolute/path/to/zotonic/bin/zotonic-lsp",
    "zotonic.args": [],
    "zotonic.site": "mysite"
}
```

Use **Zotonic: Select Site** or the status-bar item to save a site choice in the workspace. **Zotonic: Restart Language Server** reconnects after a node restart. The extension runs only in trusted workspaces.

For Sublime Text, install the **LSP** package and copy the supplied `apps/zotonic_mod_development/priv/editors/sublime/Zotonic.sublime-syntax` into `Packages/User`. Configure the server with `command` set to `["/absolute/path/to/zotonic/bin/zotonic-lsp"]`, `selector` set to `text.html.zotonic`, and the desired site in `initialization_options.site` and `settings.zotonic.site`. An example server configuration is included beside the syntax file.

The transport connects through the existing Erlang cookie and node environment; it is a trusted developer tool, not an HTTP API. For containers, the editor continues editing host files while the language server runs inside the container. Explicit `pathMappings` can handle source mounts that cannot be inferred automatically. LSP settings belong to the editor workspace, separately from the source-editor launch settings on the admin page.

See the [language-server setup guide](https://github.com/zotonic/zotonic/blob/master/doc/technotes/language-server.md) for complete editor configurations, Docker commands, path mappings, protocol limits and verification instructions.

Template debugging
------------------

Template selection depends on the active modules, their priorities, and optionally a resource's category. Use template inspection to find the selected file and its override candidates instead of guessing from a filename.

The compilation display shows templates being compiled. The floating trace button opens the render trace for the current browser session. Use the capture API when an agent needs to start/stop a capture and retrieve its graph and console output programmatically.

Dispatch rule debugging
-----------------------

Enter a request path to see which dispatch rules match and how the path is rewritten. Include any language prefix from the actual URL. Dispatch inspection does not render the selected controller.

Function call tracing
---------------------

The function tracing tool allows you to trace calls to a specific function in a module. You can specify the module name, function name and the number of calls to trace. The output will be sent to the page that started the trace, via MQTT.

Function tracing can be enabled or disabled in the zotonic.config file. By default it is enabled for the development and test environments. You can enable it runtime using:

```sh
bin/zotonic setconfig zotonic function_tracing_enabled true
```

Or disable it with:

```sh
bin/zotonic setconfig zotonic function_tracing_enabled false
```

In dispatch rules it is possible to protect certain requests from being traced. This is done by adding the dispatch rule option `sensitive`. This option is set for the authentication requests. On development environments this dispatch option is ignored.

Automatic recompilation
-----------------------

File watching requires either `inotify-tools` or `fswatch` to be installed.

The core Zotonic system starts either `inotify-tools` or `fswatch`, depending on which one is available. You have to install one of these to enable auto-compile and auto-load of changed files.

See below for platform-specific installation instructions.

If a changed file is detected then Zotonic will:

- If an .erl file changes then the file is recompiled.
- If a .scss or .sass file changes then `sassc` is called to compile it to its .css equivalent. If the changed `.sass` file starts with a `_` then all `.sass` files without a `_` will be compiled.
- If a .less file changes then `lessc` is called to compile it to its .css equivalent.
- If a .coffee file changes then `coffee` is called to compile it to its .js equivalent.
- If a lib file changes then the module indexer will be called so that any removed or added templates will be handled correctly.
- If a template file changes then the module indexer will be called so that any removed or added template will be handled correctly.
- If a dispatch file changes then all dispatch rules are reloaded.
- If a beam file changes then the module will be loaded. If the beam file is a Zotonic module then it will be automatically restarted if either the function exports or the `mod_schema` changed.
- If the .yrl definition of the template parser changes, then the .erl version of the parser is regenerated. (This will trigger a compile, which triggers a beam load).

### Linux installation

On Linux this feature depends on the inotifywait tool, which is part of the `inotify-tools` package. For displaying notifications, it uses `notify-send`:

```sh
sudo apt-get install inotify-tools libnotify-bin
```

### macOS installation

On macOS we use the external programs `fswatch` and `terminal-notifier`:

```sh
brew install fswatch terminal-notifier
```

Accepted events
---------------

This module handles the following notifier callbacks:

- `observe_admin_menu`: Add development/debug entries to the admin menu.
- `observe_filewatcher`: Catch filewatcher file change events, reloads css or the open pages using `m_config:get_value`.
- `observe_request_context`: Copy the database trace flag to a new (fresh) request process using `z_development_dbtrace:copy_from_session`.

Delegate callbacks:

- `event/2` with `postback` messages: `log_client_enable`, `template_debug_enable`, `template_graph`, `template_trace_fetch`, `template_trace_path`, `template_trace_start`, `template_trace_stop`, `template_view`, `template_xref_check`.
- `event/2` with `submit` messages: `function_trace`.

License: 

Attribution: 

Related resources: https://zotonic.com/api/agent/related/1457?language=en


## API access

- [API help](<https://zotonic.com/api-help>)
- [OpenAPI specification](<https://zotonic.com/openapi.json>)
- [This resource as JSON](<https://zotonic.com/api/agent/resource/1457?language=en>)
