Extending the admin menu

See m_admin_menu on how to extend the admin menu.

Extending the admin edit page

There are several special templates names that will be automatically included into the /admin/edit/xxx page from when you create these specially named templates.

Will be automatically included into main (left) div (at top).
Will be automatically included into main (left) div (at bottom).
Will be automatically included into right sidebar (near middle/bottom).

These templates are included using the all catinclude tag; so if you need something in the sidebar just for persons, create a _admin_edit_sidebar.person.tpl file in your project.

Overriding TinyMCE options

If you need to override TinyMCE options; adding plugins, or setting other settings; you can create an _admin_tinymce_overrides_js.tpl file which can contain extra settings for the TinyMCE editors in the admin.

The template must contain JavasSript which modifies the tinyInit variable just before the editor is started. For example, to tweak the “paste” options you can put the following in the template:

tinyInit.theme_advanced_blockformats = "p,h1,h2"
tinyInit.paste_auto_cleanup_on_paste = true;
tinyInit.paste_remove_styles = true;
tinyInit.paste_remove_styles_if_webkit = true;
tinyInit.paste_strip_class_attributes = true;
tinyInit.paste_text_sticky = true;
tinyInit.paste_text_sticky_default = true;

TinyMCE Zotonic options

Zotonic provides extra init options:

Set this to false to prevent the insert media dialog from showing. Default true.
Set this to false to prevent the media properties dialog from showing. Default true.

Writing admin widget templates

This section contains examples of templates to create widgets for the /admin. Each of these examples extends basic several widget templates from mod_admin. To write your own you need to drop example content and fill holes in these example widgets.

You can use them as basis for your site admin-related tasks.

Very simple example widget for admin dashboard. Contains blocks for title and body. Look at /admin to see several dashboard widgets (latest events, pages, media, etc).
Sligthly more complex widget example. Same templates are used into /admin/edit/N for main content and sidebar widgets. These widgets do not provide any localization abilities. Also note that there are several special widget names:
Complex widget example. Is used to edit localized rsc properties. It will be rendered as tabs. See /admin/edit/N top left to see the tabs. If mod_translation disabled, then i18n-widgets are displayed same as _admin_widget_std.tpl.

Making an admin widget conditionally visible

To make an entire admin widget visible or not, depending on some condition that you want to calculate inside the widget’s code, you can use the widget_wrapper block (which sits around the entire widget) in combination with the inherit tag, wrapping that with a condition.

For instance, mod_backup uses this technique to display the import/export sidebar widget. Excerpt from mod_backup’s _admin_edit_sidebar.tpl:

{# Make the widget conditional, based on the config value mod_backup.admin_panel #}
{% block widget_wrapper %}
    {% if m.config.mod_backup.admin_panel.value %}
        {% inherit %}
    {% endif %}
{% endblock %}

In this example, when the condition is true, the wrapper is rendered normally (content is inherited from the extended template); when false, the wrapper block is overridden by new (but void) content.

Extending the admin overview page

The overview page at admin/overview shows a table with links to all pages. It can be filtered and sorted. This extension deals with the view when a category filter has been selected.

The goal is to add more specific information that helps to distinguish pages.

The Category column, second from the left, can be extended to carry category-specific information. As an example, pages of category Event show the start date for each event, grayed out when the event is in the past. Something like this:

Title Starts Created on
Great event 2016-08-27 00:00:00 25 Aug 2015, 22:19
Past event 2014-01-02 00:00:00 01 Jan 2014, 13:10

Instead of dates, the information can be anything - from color coding labels to location data, the number of comments or the completeness state of product descriptions.

Setting up templates

To make it work we are using 3 templates (where category_name is the lowercase name of your category):


Overrides the overview with a field variable for our custom sort. If we are using an existing resource property such as date_start, we write:

{% include "_admin_overview_list.tpl"


The sort header caption. For a non-sortable header, just write the caption as text. For a sortable header, include the sort functionality in _admin_sort_header.tpl and pass the caption as variable:

{% include "_admin_sort_header.tpl"
    caption="My caption"

type="date" indicates that sorting should start descending, from new to old.


Contains the category-specific information. This is a freeform Zotonic template. The Events example checks if the end date is in the past:

{% if id.date_end|in_past %}
    <span class="text-muted">{{ id.date_start|timesince }}</span>
{% else %}
    <span>{{ id.date_start|timesince }}</span>
{% endif %}

Custom sort properties

To sort on values that are not stored in the default Zotonic resources, you will need to create a custom pivot. This will create an additional database table with the values to sort on.

Let’s take the (unlikely) example where we want to display the summary of each page (and sort on it as well). The summary data is not stored in an easily accessible way (at least for sorting), so we need to add 2 pivot methods to our Erlang module:



init(Context) ->
    z_pivot_rsc:define_custom_pivot(?MODULE, [{summary, "text"}], Context),

observe_custom_pivot({custom_pivot, Id}, Context) ->
    case z_trans:lookup_fallback(m_rsc:p(Id, summary, Context), Context) of
        undefined ->
        Summary ->
            {?MODULE, [{summary, Summary}]}

For this example we are just grabbing the default language text.

The field name in _admin_overview_list.category_name.tpl now just needs to contain the pivot column name:

{% include "_admin_overview_list.tpl"

And the sort header template _admin_sort_header.category_name.tpl adds the custom pivot variable:

{% include "_admin_sort_header.tpl"

Resource meta features

Resources in the meta category can have ‘features’: certain resource properties (usually in the form of checkboxes) that decide what to show or hide on certain pages in the admin. To use this, create a _admin_features.category.tpl in your module.

For instance, the module mod_geomap defines the following _admin_features.category.tpl to create an extra checkbox so that per category can be defined whether or not the geodata box should be shown:

<div class="controls">
        <label class="checkbox">
        <input value="1" type="checkbox"
               {% if id.is_feature_show_geodata|if_undefined:true %}checked{% endif %}
        {_ Show geo data on edit page _}

And on the edit page there is this check to conditionally include the geodata box:

{% if id.category_id.is_feature_show_geodata|if_undefined:true %}

The filter if_undefined is used so that the default value can be true when the checkbox has never been touched.

Configuration keys

For the admin there are the following configuration keys:

  • mod_admin.rsc_dialog_tabs
  • mod_admin.rsc_dialog_is_published
  • mod_admin.rsc_dialog_is_dependent
  • mod_admin.rsc_dialog_hide_dependent
  • mod_admin.connect_created_me

The mod_admin.rsc_dialog_tabs key defines which tabs are shown in the new resource, media-upload, and image-link dialogs. Per defauls these dialogs show all the possible tabs, with this configurarion key it is possible to change that.

Available tabs are: find,new,upload,url,embed,oembed,depiction. More can be defined by modules.

Tab depiction is used for the TinyMCE image-link dialog; it shows all media connected using the depiction predicate.

The configuration mod_admin.rsc_dialog_is_published defines the default is_published state for new resources. Setting this key to 1 will check the is_published checkbox.

The configuration mod_admin.edge_list_max_length defines the maximum number of connections shown per predicate in the connection list sidebar. If there are more connections then the list truncated, and the message _Too many connections, only the first and last are shown._ is displayed. The default is 100 connections.

The configuration mod_admin.rsc_dialog_is_dependent defines the default is_dependent state for new resources. Setting this key to 1 will check the is_dependent checkbox.

With the configuration mod_admin.rsc_dialog_hide_dependent the dependent checkbox can be hidden for non admin users.

If the mod_admin.connect_created_me is set then the connect dialogs will per default filter for content made by the current user. The current setting is stored in the sessionStorage with the key dialog_connect_created_me.

Edit on GitHub



This model exposes some meta-information for the use in mod_admin templates.


Not yet documented.


This model holds the admin menu, which is built up by calling each module to add items to the menu.


Add an editorial note to any resource.


Not yet documented.



The admin controller is the main controller behind which admin pages are served. Its main purpose is that it does an…


The main admin edit controller. This controller serves the edit page where resources can be edited.


A controller for rendering preview thumbnails of any media embedded in a richtext-editor component of a resource on the…


Shows the list of pages ( resources) which refer to this resource through an edge.

Dispatch rules


Dispatch rules Name Path Resource Args admin [“admin”] controller_admin [seo_noindex] admin_overview_rsc [“admin”



Creates a temporary resource if its input value is not defined.



Action module which provides postback handlers for the “status” view of the admin:


Delete a media file from a resource, without confirmation.


Delete a resource, without confirmation.


Open a dialog to confirm the deletion of a resource.


Open a dialog to duplicate the current resource with a new id and title.


Open a dialog to edit the “basic” information of a resource.


Shows the admin dialog for uploading a media item. See Media.


Show the admin dialog for creating a new resource.


Add an edge between two resources. Used in the admin.


Remove an edge between two resources. Used in the admin.


Used for inserting an internal link in the TinyMCE editor in the admin.


Used for triggering the insertion of a media item in the TinyMCE editor in the admin.


Used after a media item is selected in the media chooser for the TinyMCE editor.


Used by the admin as a callback when a media file has been selected for insertion into the rich-text editor.

See also


Include the markup of an extended template into the extending template.


Tests whether a value is undefined, returning the given argument.


Adds editing of resources, menu-trees and collections for non-admin users.

Referred by


Creates a temporary resource if its input value is not defined.

all include

Call all modules to include a certain template.


Generate the URL for a named dispatch rule. In this way it is possible to automatically change the generated URLs when…

All dispatch rules

All the dispatch rules from all modules. For a background on dispatch rules, see The URL dispatch system.


At different moments in the lifecycle of the web request, Zotonic sends notifications. By observing these notifications…

all catinclude

Include a template for all a resource’s categories from all modules.


Actions, tags (also known as screen components), and javascript for user interfaces using wires .