Contenticious - build web sites from markdown files


Generate config file, directories, example pages and the script:

    $ contenticious init
    generating contenticious boilerplate...

Serve markdown files from pages directory (live updated):

    $ ./ daemon
    Server available at

Generate static files ready for upload (dumped to the dump directory)

    $ ./ dump
    dumping everything to /Users/memowe/code/contenticious/dump ...

These examples show basic usage. Contenticious is highly customizable, but you may want to start with this basic commands to see what's happening.


Contenticious is a very simple way to build a nice little website from your content (file-system based).

You just write Markdown files in a directory structure and check the generated HTML live in your browser. The presentation is highly customizable on many levels, but I think the default is readable and rather pretty.

Since Contenticious is a Mojolicious web app, it can "be" a web server for your content, but you can dump everything to static files with a single command and upload it to your favourite web hoster.

It's also possible to mount Contenticious in your Mojolicious web app.

How to start

Change to an empty directory and type contenticious help in your termina. You'll see a short description of the contenticious command. Let's start with

    $ contenticious init

which will generate some files and directories:

config - a simple config file with Perl syntax. - the web app script which will serve or dump your content
pages - a directory (structure) in which you'll write Markdown files
public - a directory with files that will be served directly

Now start the server:

    $ ./ daemon
    Server available at

If you point your web browser to that address, you should see some example pages served directly (and updated live) from the pages directory. Feel free to edit that content and watch what happens in your browser.

On directory and file names

Your directory and file names become url path parts. You may want to add numbers to the directory and file names to get the navigation items in the right order. The numbers will never be seen outside.

To define content for a directory itself you can provide an file.

    file system                     urls
      |--                  /c.html
      |-- 018_perl
      |    |--             /perl.html
      |    |--   /perl/introduction.html
      |    '--       /perl/the_cpan.html
      '-- 072_brainfuck             /brainfuck.html
           |---        /brainfuck/turing.html
           '---           /brainfuck/wtf.html

If you don't provide an file for a directory, contenticious will render a list page for you. See this table for better illustration. In this case, brainfuck.html will be an auto-generated listing of the two sub pages, turing and wtf.

Later you will be informed how to customize the contenticious templates. You can adjust the listing by editing the template list.html.ep.

Note: it's impossible to have a directory and a file with the same path name, but I'm pretty sure you don't really need that. Instead use the mechanism from above.

More about content

Contenticious needs some meta informations about your content files, but it works very hard to guess if you don't provide it. Meta information is provided in the first few lines of your markdown documents and looks like this

    title: The Comprehensive Perl Archive Network
    navi_name: The CPAN

    It's huge, but your mom could eat it

    **CPAN, the Comprehensive Perl Archive Network**,
    is an archive of over 100,000 modules of software
    written in Perl, as well as documentation for it. ...

The title will show up in the title HTML element of the pages, which will be rendered in the window title bar in most browsers. If no title line is provided, contenticious will try to extract the first H1 headline of the document's body, which is the mom-line in this case. If there's no H1 headline, contenticious will use the file's path.

The second meta information is navi_name which will be used to generate the site navigation. If no navi_name is provided, contenticious will use the file's path.

Sometimes you'll need static content like images, sound files or PDF documents. No problem, just place them in the public directory and they will be served by contenticious under their own name. After you created the basic pages directory with contenticious, there's only one static file in public: the default stylesheet.


To change contenticious' presentation and behaviour, please look at the configuration file config first. It looks like this:

        pages_dir   => app->home->rel_dir('pages'),
        dump_dir    => app->home->rel_dir('dump'),
        name        => 'Shagadelic',
        copyright   => 'Zaphod Beeblebrox',
        cached      => 0,

As you can see, it is a Perl data structure and you can access the app shortcut for advanced hacking. I think, the most names are rather self-documenting, except cached. When set to a true value, contenticious will hold the document structure in memory to serve it faster. It's deactivated by default for development. Otherwise you would have to restart the server every time you want to view the latest version.

To change the design of contenticious' pages, edit the styles.css file in the public directory. Since the default HTML is very clean you should be able to change a lot with css changes.

If that's still not enough, use the following command to extract all templates to a newly created templates directory:

    $ ./ inflate

Then you can change the generated HTML with Mojolicious' flexible ep template syntax.


You can find a lot of information about the deployment of Mojolicious apps in its wiki. In most cases you want to set the chached option to a true value in contenticious' config file to increase performance.

If you plan to deploy your content with Mojolicious' built-in production server Hypnotoad, your contenticious config file is the right place to configure it as well:

        cached      => 0,
        hypnotoad   => {
            listen  => ['http://*:3000'],
            workers => 10,
            proxy   => 1,

But if you don't expect your content to be updated very often, just let Contenticious generate static HTML and CSS files for you:

    $ ./ dump

It will dump everything to the directory dump so you can upload it to your favourite web server without any perl, Mojolicious or contenticious magic.

Mount to an existing web app

With Mojolicious::Plugin::Mount it's possible to mount whole Mojolicious web apps into another. Since Contenticious is a web app (via, you can mount Contenticious too. It works pretty straight-forward. See this distribution's test script t/07_mount.t for an example.


The source code repository of Contenticious is on github:

There's also a simple issue tracker. Feel free to use it:


Copyright (c) Mirko Westermeier, <>


Thank you for your contributions!

Published under the MIT license.