If you like my work, please consider supporting its development.

This page describes how to write generalized plugins in a way that integrates with Midnight. Most of the content in this document also applies to all of the specialized kinds of plugins.

The Configuration File

Midnight reads information from the site’s configuration file to determine how to integrate a plugin with the theme. A plugin called hello_world will have a configuration that looks something like below:

        path = "plugins/hello_world/css.css"
        path = "plugins/hello_world/head.html"
        path = "plugins/hello_world/foot.html"
        cache = true
                path: plugins/hello_world/css.css
                path: plugins/hello_world/head.html
                path: plugins/hello_world/foot.html
                cache: true
    "params": {
        "plugins": {
            "hello_world": {
                "css": {
                    "path": "plugins/hello_world/css.css"
                "head": {
                    "path": "plugins/hello_world/head.html"
                "foot": {
                    "path": "plugins/hello_world/foot.html",
                    "cache": true

In general, a plugin is configured under params -> plugin_type -> plugin_name. In this case, this is just a “normal” plugin, so the type is plugins.


The paths for the various plugin components follow a convention that does not need to be followed, but is good for organization. The convention is for each file (which is a partial) to be located under SITE_ROOT/layouts/partials/plugin_type/plugin_name/partial.file, with each partial named according to whether it goes in the head, the foot, or the CSS. The path should be the path that would be used in a call to partial or partialCached in a Hugo template.


The cache key is optional and, if true, states that the contents of the partial are the same across every page it occurs in and may be cached. If the contents of the partial at all depend on the contents of the page, do not cache it.

If the plugin is one of the specialized types, Midnight already determines whether it should be included on a given page, so the plugin can be cached in that case and should not contain any code determining, e.g. if the shortcode was called on the page.

If there is extra logic involved other than the basic logic Midnight uses, the logic should be retained in the partial and it should not be cached.

Head Partials

The partial specified under head is included inside of the <head> tag of the page and should be used for setting metadata or loading external stylesheets. A necessary partial is styles. All stylesheets should be loaded using styles. Also useful are the CSS color partials.

Foot Partials

The partial specified under foot is included at the end of the <body> tag and should be used for loading JavaScript files. A necessary partial is script. All script files should be loaded using script.

CSS Partials

The partial specified under css is included inside the site’s generated stylesheet, after all CSS variables have been declared. Useful partials include the CSS color ones.

Partial partials

Along with css, head, and foot, some specialized plugins (i.e. [comments][plugin-comments] and [sidebar widgets][plugin-sidebar]) have a partial section where path defines the partial that should be included in the correct spot if the plugin is enabled.

Content Security Policy

If the plugin makes any requests outside of the site using Midnight, it needs to include partials for each directive that return a space-separated list of allowed sources.

The paths to these partials must be included in the configuration file, under params.plugin-type.plugin-name.csp.directive-name. For example, the script-src directive for cool-comments would be defined under params.comments.cool-comments.csp.script-src. The path to the partial is specified under path and cache should be equal to true (it doesn’t make much difference, but doesn’t hurt either).

For examples, see the Midnight theme configuration file and the CSP [partials][commento-csp] for Commento.

Avoid Using unsafe-* Sources

Plugins should not inline any scripts or CSS on the page, but should instead include that inlined code in a site asset file that can be parsed as a template. Allowing inlined code can create security holes, which should be avoided.

Sometimes services being included as plugins automatically generate or modify elements such that they have inline styles or onload attributes, etc. unsafe-* sources can be enabled for these purposes; a bug report should also be given to the upstream project to not rely on inlined code.