CSS HTML JavaScript Shell
Clone or download
Latest commit 28356b2 Jul 15, 2018
Failed to load latest commit information.
.well-known Create keybase.txt Nov 15, 2017
config Update footer.yml Jun 2, 2018
content Absolute url for cloaks on 404 Jul 15, 2018
static honour navbar when scrolling to anchor May 24, 2018
templates add support for robots meta tag Jun 23, 2018
.exrc Add .exrc Jun 11, 2016
.travis.yml move standard to run only on travis as it shouldn't output to any file May 24, 2018
LICENSE Moving to cc by-dc-sa Feb 22, 2016
README.md link to CONTRIBUTING.md Nov 11, 2016
config.yml Update copyright years Feb 10, 2018
package.json yeah missplaced comma in json... May 24, 2018
postcss.json Change to use postcss rather than myth Jun 24, 2016


web-7.0 Build Status irc: #freenode-website

A shiny replacement for http://freenode.net.


You'll need our node.js dependencies:

$ sudo npm install -g postcss-cli svgo
$ npm install

Then, assuming a Python 3.4 (or later) installation:

$ python3 -m venv env
$ . env/bin/activate
$ pip install -r requirements.txt
$ cms7

If everything went well, you should see a lot of log output, and out/ will have the website in it.

Because we generate the site statically, you'll need to re-run cms7 each time you change something. If your editor likes compile commands that can run from any directory, you can also use cms7 -c /path/to/config.yml.


  • Whenever possible, one commit per feature.
  • If feature/pull-request branches have only one developer, please regularly rebase them onto master until they are merged in.
  • Don't merge branches with meaningless commit messages; always squash them instead.
  • Wait for discussion of big changes. Your branches will still be here tomorrow.

Please comply with the contribution guidelines

Helpful tip for those merging PRs: you can browse the tree a merge would result in by navigating to https://github.com/freenode/web-7.0/tree/pull/XYZ/merge, where XYZ is the pull request number.

You can also go to https://freenode.net/web-7.0/BRANCHNAME/ to see a build of any particular branch. This also works for internal pull requests (they are named pull-X).

Architecture / Orientation

The site is generated from Markdown sources and Jinja2 templates, found in content/ and templates/ respectively. The Travis build deploys to GitHub Pages automatically on every push.

Various modules convert the sources to a useful output structure. Eventually cms7 will document this process, but for now:

  • content/pages/ contains plain pages which are rendered in out/ using page.html.

  • content/news/ contains blog/news posts which are rendered in out/news/ using article.html.

  • content/kb/ contains KB categories: each directory content/kb/X/ has the entries for category X. These are rendered in out/kb/answers/ with kb.html.

    Indexes of these entries are rendered in out/kb/ with kb_index.html, according to a list in config/kb.yml.

Markdown metadata

cms7 uses the markdown metadata extension, and recognises some special keys:

  • title sets the page title
  • slug overrides the target URL: pages/hello with slug: banana would become out/banana.html
  • template overrides the template with which to render this Markdown file


  • author
  • date
  • enclosure sets the podcast URL of an article

Internal linking

Everything that ends up in the final output has a name that identifies it to the rest of the website. If a file is derived directly from an input file, generally its name is derived from the name of the input.

  • Markdown files like content/pages/hello.md are named their own name relative to the content directory, minus their extension: pages/hello.
  • static resources like static/img/cat.jpg are named their own name relative to the repository root: static/img/cat.jpg.
  • Templates that are rendered from nothing (e.g. to make the index page) are named whatever the config file says to name them.
  • KB indexes are named kb/index/X, where X is the name of the index in config/kb.yml.

cms7 can generate a relative URL to anything with a name from any page. This should always be preferred over manually writing links. To generate a relative link from a Markdown document, just link to a name:

[A page about frogs](pages/frog)

To do the same from a template, call url_for:

<a href="{{ url_for('pages/frog') }}">A page about frogs</a>