1. Introduction

Styx is a functional static site generator written in Nix expression language.

Styx is aimed to be flexible and easy to customize. It is based on the Nix package manager, so it get many of its advantages: caching system, determinism to name a few. External applications can be used in Styx in a very easy way without having to install them by using the Nix package manager.

1.1. Styx Overview

Pros:

  • Uniformity: The same language is used in templates and logic.

  • Caching: Styx benefit of the Nix caching system, so only needed pages are rebuild.

  • Light weight: Styx has very few dependencies.

  • Flexibility: Styx is very flexible and make it is easy to implement new features.

Cons:

  • Performance: Some parts of Styx like the posts conversion can be very slow, this is partly counter-balanced by the caching system, but on a fresh site generation Styx can be magnitudes slower than other static site generators.

  • Semantics: Styx is using the Nix expression language for its logic and templates. The Nix expression language is quite different of usual languages and can need some time to get familiar with.

  • Nix: Styx has only one dependency, the Nix package manager. To use Styx you must install Nix, and depending your platform, that can be challenging. But installing Nix might totally change your views on package management!

2. Installation

The only requirement to install Styx is the Nix package manager. Refer to the Nix installation instructions to install Nix.

It is possible to install Nix with the following command:

$ nix-env -i https://github.com/ericsagnes/styx/archive/latest.tar.gz

To only test Styx, it is recommended to use the nix-shell command to start a temporary environment including Styx:

$ nix-shell -p `nix-build https://github.com/ericsagnes/styx/archive/latest.tar.gz`

3. Quick Start

A Styx site can be created and locally served with the following set of commands:

$ nix-shell -p $(nix-build https://github.com/styx-static/styx/archive/latest.tar.gz) (1)
[nix-shell]$ styx new myblog (2)
[nix-shell]$ cd myblog (3)
[nix-shell:~/myblog]$ styx preview (4)
1 Enter a nix-shell with Styx.
2 Generate a new site in the myblog directory.
3 Enter the Styx site root folder.
4 Start a preview the site on a local server.

Your styx site will be available at http://127.0.0.1:8080.

Now, take a look at the site.nix to see how the site is defined. There are many comments, but in doubt check the site.nix section, it explains site.nix in details.

4. Command line interface

The Styx provides a command line program styx.

4.1. Generic flags

styx --help

Display the help message.

styx --version

Display the version.

4.2. New

The new command is used to create a new Styx site.

styx new

Create a Styx site in "styx-site" directory in current path.

styx-new -o "myblog"

Create a Styx site in myblog directory in current path.

styx-new -o "myblog" --target /tmp

Create a Styx site in myblog directory in /tmp.

4.3. Build

The build command is used to build a Styx site. It must be used in a Styx site root file.

styx build

Build the Styx site and write the output in the public folder.

styx build -o FOLDER

Build the nix site and write the output in the FOLDER folder.

The nix-build --show-trace, --arg NAME VALUE and --argstr NAME VALUE flags can be used with the build command.

4.4. Preview

The preview command is used to launch a server that will list on localhost (127.0.0.1) port 8080 by default. The preview command will override conf.siteUrl to preserve links.

The server can be stopped by pressing Ctrl+C.

styx preview

Start a preview server on 127.0.0.1:8080.

styx preview --port 9090

Start a preview server on 127.0.0.1:9090.

styx preview --port 9090 --drafts

Start a preview server on 127.0.0.1:9090 with drafts rendered.

4.5. Live

The live is similar to preview, with the unique difference that site is automatically rebuilt when a change is made.

The live mode should be quitted by pressing q.

styx live

Start a live preview server on 127.0.0.1:8080.

styx preview --port 9090

Start a live preview server on 127.0.0.1:9090.

styx preview --port 9090 --drafts

Start a live preview server on 127.0.0.1:9090 with drafts rendered.

If the live mode is not quitted by pressing q, there is a possibility that the server process will stay alive in backgroud. The server process can be found by running ps aux | grep caddy and killed with the kill command.

4.6. Serve

The serve command is used to build a site and launch a local server. This allow to check the site without having to deploying it. The server can be stopped by pressing Ctrl+C.

styx serve

Will serve on the localhost on port 8080.

styx-serve --port 9090

Will serve on the port 9090.

styx serve --detach

Will serve on the localhost on port 8080 and run the server on background, process can be found by running ps aux | grep caddy.

The nix-build --show-trace, --arg NAME VALUE and --argstr NAME VALUE flags can be used with the serve command.

4.7. Deploy

The`deploy` command is used to deploy A styx site on a remote server. Currently only GitHub pages are supported.

For more details see the Deployment section.

styx deploy --init—​gh-pages

Prepare a git repository to be able to deploy on GitHub pages.

styx deploy --gh-pages

Commit the Styx site to the gh-pages branch.

5. Basics

Styx is using the Nix expression language. The Nix expression language is a lazy evaluated functional language with unconventional semantics. It is recommended to read the Nix expression language chapter of the Nix manual to get more familiar with it.

5.1. Configuration

Styx is configured with the conf.nix file present in the site root directory.

conf.nix
{
  # Directory where templates are located
  pagesDir = ./pages;

  # Directory where posts are located
  postsDir = ./posts;

  # Directory where drafts are located
  draftsDir = ./drafts;

  # Directory where the themes are located
  themesDir = ./themes;

  # Directory where static files are located
  staticDir = ./static;

  # URL of the site, must be set to the url of the domain the site will be deployed
  siteUrl = "http://yourdomain.com";

  # Site title, used in the site header and the atom feed
  siteTitle = "Styx Sample Site";

  # Site description used in the base template
  siteDescription = "Write a description for your new site here.";

  # Maximum number of posts on the index page
  postsOnIndexPage = 3;

  # Maximum number of posts per archive page
  postsPerArchivePage = 5;
}

The configuration is an attribute set, and new configuration attributes can be added at will.

pagesDir

Directory where pages are located.

postsDir

Directory where posts are located.

draftsDir

Directory where drafts are located.

themesDir

Directory where themes are located.

siteURL

URL of the site, must be set to the URL of the domain the site will be deployed. Must not contain a trailing /.

siteTitle

Site title, used in the site header and the atom feed.

siteDescription

Site description used in the base template.

postsOnIndexPage

Maximum number of posts on the index page.

postsPerArchivePage

Maximum number of posts per archive page.

5.2. Directory Structure

├── conf.nix (1)
├── site.nix (2)
├── drafts/ (3)
├── lib/ (4)
├── pages/ (5)
├── posts/ (6)
├── templates/ (7)
└── themes/ (8)
1 conf.nix is the main configuration, see Configuration for details.
2 site.nix is the main file for site generation, see site.nix for details.
3 drafts/ is the default directory containing drafts, see Drafts for details.
4 lib/ is the directory holding Styx library functions, see Library for details.
5 pages/ is the default directory containing pages, see Pages for details.
6 posts/ is the default directory containing drafts, see Drafts for details.
7 templates/ is the default directory containing templates files, see Templates for details.
8 themes/ is the default directory containing themes, see Themes for details.

5.3. site.nix

site.nix is the central file of a Styx site and is responsible for generating the website.

site.nix consists in a single function that generate a site when evaluated.

Functions in the Nix expression language are declared in a head: body syntax, for example a: b: a + b is a function adding two numbers.

The following sections will explain site.nix parts by parts.

5.3.1. Skeleton

The skeleton is the boiler-plate code of Styx, it should be edited at own risks as any change in it might lead to unexpected results.

It is not required to understand how the skeleton work to make a Styx site, so this section can be safely skipped.

site.nix skeleton
{ pkgs ? import <nixpkgs> {} (1)
, renderDrafts ? false (2)
, siteUrl ? null
, lastChange ? null
}@args: (3)

let lib = import ./lib pkgs; (4)
in with lib; (5)

let (6)

# Main Logic (7)

in generateSite { inherit files pagesList; } (8)
1 This is a function head declared as a deconstructed set, ? righthand set the default value for the lefhand argument. This line is importing the default system nixpkgs.
2 renderDrafts ? false means that renderDrafts default value is false.
3 The { …​ }@args pattern provide a way to refer to the full parameter attribute set via args.
4 let is a construction to declare local variables, a let block finish by a in. Any variable defined in a let is available in the let scope and in the scope right after the in. let a = 1; 1 + a will result in 2. let are used to structure code in an easier to understand manner. This line import the lib/default.nix file and set it to a lib variable. The lib variable is an attribute set containing Styx library functions.
5 The in section of the previous let. The with coming next is a way to put all the top-level attributes of an attribute set in the scope. with { a = 1; b = 2; }; a + b result in 3. So in the previous line lib is imported in the lib local variable, and in this line all the top-level lib functions are inserted in the local scope.
6 Another let to start a scope inheriting lib and all its attributes (top-level functions).
7 Contains the main logic, and will be explained in the next section.
8 This is what the whole site.nix function return. generateSite is a function that generate the site. All the logic in the "Main Logic" part is meant to prepare generateSite arguments.
The default parameters in site.nix head: pkgs, renderDrafts, siteUrl and lastChange are set and expected by Styx. Removing or changing them will break the site generation process.

5.3.2. Main Logic

Main logic part can be divided in three parts:

The order of declarations in the main logic part is not important and can be changed to fit preference.

Also the main logic part being in a let block, it is possible to refer any of its variables at any position. (It is possible to use a variable before declaring it)

Setup

This part contains some boiler-plate code. New variables can be declared at will to fit any special needs. (Comments removed in favor of call-out explanations)

Setup section
  conf = overrideConf (import ./conf.nix) args; (1)

  themes = [ "default" ]; (2)

  state = { inherit lastChange; }; (3)

  templates = lib.themes.loadTemplates { (4)
    inherit themes defaultEnvironment customEnvironments;
    themesDir = conf.themesDir;
  };

  files = lib.themes.loadFiles { (5)
    inherit themes;
    themesDir = conf.themesDir;
  };
1 Loading the main configuration file, conf.nix in a conf local variable.
2 Setting used themes, themes should be a list of theme names.
3 Setting a state local variable containing "impure" values. It contains only the lastChange variable coming from site.nix main function head. (Skeleton point 1) lastChange value is automatically set by the Styx command.
4 Loading themes templates.
5 Loading themes static files.
Templates declaration

Templates are automatically loaded via the theme system.

This section is reposible for setting custom template environments to specific templates. For more details on template environments, see Template environment.

Templates section
  defaultEnvironment = { inherit conf state lib templates; }; (1)

  navbar = [ (head pages.archives) pages.about ]; (2)

  customEnvironments = { (3)
    layout = defaultEnvironment // { inherit navbar; feed = pages.feed; }; (4)
  };
1 This initialize a default template environment. Most of templates expect to have access to conf, state, lib and templates. It is not recommended to remove any of these. On the other hand it is fine to add new attributes to the default environment to fit special needs.
2 This define a navbar local variable containing pages to include in the NavBar. For more details about Navbar setting, see the NavBar section.
3 customEnvironments should be a set with a similar structure to templates, but with keys that defines a custom environment for the template. Any template that is not part of customEnvironments will use the defaultEnvironment.
4 The environment passed to the layout template is the default environment extended with a variable feed that holds the feed page (pages.feed) and the navbar variable that holds the list of pages to show in the NavBar. The base template is managing the main layout of the site and the head section of the HTML document. As we want to have a link to the feed in it, we add the feed page to a variable so it can be used in the template. Similar for the NavBar.
// is the operator to merge attribute sets. If the two sets have a same key, the right hand set value will be set. The merge is not recursive.
Pages declaration

The pages declaration consists in declaring all the pages of the site in an attribute set. The sample site contains many similar pages declarations, so this section will only present interesting examples.

A page is an attribute set with a few constraints, to learn more about how it should be structured see the Pages section.

A page attribute set must consist at least of template, href and title attributes. The feed page is an exception as it use the site title from conf and then does not need a title attribute.
Pages section 1/2
  pages = rec { (1)
    index = { (2)
      title = "Home";
      href = "index.html";
      template = templates.index;
      inherit feed; (3)
      posts = take conf.postsOnIndexPage posts; (4)
      archivePage = head archives; (5)
    };

    about = {
      href = "about.html";
      template = templates.about;
      breadcrumbs = [ index ]; (6)
    } // (parsePage conf.pagesDir "about.md"); (7)
1 Declaring the pages attribute set. It is important that this set holds only valid pages or list of pages. The rec keyword make the set recursive, so it is possible to refer set attributes in other attributes.
2 Declaring an index page containing the basic title, href and template attributes.
3 Inheriting the feed page, this is equal to feed = feed;. feed is a non-standard page attribute and is declared to fit contents needs.
4 This also set a non-standard attribute, posts set to the first conf.postsOnIndexPage items of the post page list.
5 Another non-standard attribute, archivePage set to the first page of the archives page list.
6 Setting page breadcrumbs, see the Breadcrumbs for details.
7 Fetching page content and title from a markdown.
Pages section 2/2
    archives = splitPage { (1)
      baseHref = "archives/posts";
      template = templates.archive;
      items = posts;
      itemsPerPage = conf.postsPerArchivePage;
      title = "Posts";
      breadcrumbs = [ index ];
    };

    feed = { (2)
      posts = take 10 posts;
      href = "feed.xml";
      template = templates.feed;
      layout = id;
    };

    posts = let  (3)
      substitutions = { inherit conf; }; (4)
      posts = getPosts { inherit substitutions; from = conf.postsDir; to = "posts"; }; (5)
      drafts = optionals renderDrafts (getDrafts { inherit substitutions; from = conf.draftsDir; to = "drafts"; }); (6)
      preparePosts = p: p // { template = templates.post.full; breadcrumbs = with pages; [ index (head archives) ]; }; (7)
    in sortPosts (map preparePosts (posts ++ drafts)); (8)
  };

  pagesList =
    let list = (pagesToList pages); (9)
    in map (setDefaultLayout templates.layout) list; (10)
1 Declaring an archives list of pages by splitting items trough multiple pages. See [splitPage] for details.
2 A simple page declaration. As the feed template is using conf.siteTitle in place of title, it is not required to set a title in this special case. Also, as the feed page does not need a layout, the layout function is set to id, see Layout templates for details.
3 Declare the list of posts, this is the most complex page declaration presented in this section.
4 Adding conf to the substitutions, see Substitutions for details.
5 Fetching the posts and setting their output path to posts.
6 Fetching the drafts only if renderDrafts is true. (by using the Styx command --drafts flag)
7 Declaring a preparePost function that take a post and extends it by setting a template and breadcrumbs.
8 Finally merging the posts and drafts in a list, setting the template and breadcrumbs to each, and sorting the list so the posts are in chronological order.
9 generateSite needs a list of pages, so we convert the pages attribute set to a pagesList list with the pagesToList function.
10 Then, setDefaultLayout is used to set a layout template to all the pages that don’t set the layout attribute.

6. Content

6.1. Pages

Pages is the most basic content unit. Every content in Styx is a page (posts and drafts are a special types of pages).

A page in Styx is an attribute set following a set of rules:

  • It must define at least the href, title, layout and the template keys.

  • The template key is a function that take the page attribute set as a parameter and return the page attribute set augmented with a content key representing the result of the template.

  • The layout key is a function take a page attribute set with a content key, returned by the the template key, and render the final page source.

  • The href key is the path of the generated page relative to site root.

It is possible to extend a page attribute set at will for more complex use cases.

Page definition example
  pages.about = {
    href = "about.html";
    template = templates.about;
    title = "About";
    layout = templates.layout;
  };
The layout being common to most of the pages, the default layout is usually set with a map function when the page attribute set is converted to a list of pages.
Extending a page attribute set
  pages.about // { breadcrumbs = [ pages.index ]; }

Page content can be directly set in the template, or imported from an external file with the parsePage function:

Loading a markdown file
  about = {
    href = "about.html";
    template = templates.about;
    breadcrumbs = [ index ];
  } // (parsePage { dir = conf.pagesDir; file = "about.md"; });
parsePage return a set with title and content, the converted HTML source of the page.

6.2. Posts

Posts are a special type of pages that defines some extra attributes.

By default, Styx read files in markdown format from conf.postsDir, but it is possible to specify a custom directory to the getPosts function.

Post files should follow the YYYY-MM-DD-TITLE.md convention to be loaded. During build, Styx with display a message if it cannot load a post file.

Post attribute sets generated by the parsePost function have the following attributes:

  • title: Post title

  • content: Post content in HTML format.

  • href: Relative URL to the post.

  • timestamp: Timestamp of the post in the YYYY-MM-DD-TITLE format.

  • id: Name part of the post file name.

The getPosts function does not set template and layout keys. So posts generated by it are imcomplete pages, but these keys can be set afterwards.

6.3. Drafts

Drafts are a special type of posts that are generated when the --drafts flag is passed to the Styx command.

By default, Styx read files in markdown format from conf.draftsDir, but it is possible to specify a custom directory to the getDrafts function.

Drafts attribute sets generated by the parseDraft function have the following attributes:

  • title: Post title

  • content: Post content in HTML format.

  • href: Relative URL to the post.

  • timestamp: Timestamp of the post in the YYYY-MM-DD-TITLE format.

  • id: Name part of the post file name.

  • isDraft: set to true.

The only difference between posts and drafts is the presence of the isDraft attribute.

6.4. Substitutions

Subtitutions are a way to use some variables of site,nix in mardown files.

Substitutions are a set that must be passed to the getPosts, getDrafts or parsePage arguments.

Setting substitutions in default.nix
  posts = let
    substitutions = { inherit conf; }; (1)
    posts = getPosts { inherit substitutions; from = conf.postsDir; to = "posts"; }; (2)
    drafts = optionals renderDrafts (getDrafts { inherit substitutions; from = conf.draftsDir; to = "drafts"; }); (3)
    preparePosts = p: p // { template = templates.post.full; breadcrumbs = with pages; [ index (head archives) ]; };
  in sortPosts (map preparePosts (posts ++ drafts));
1 Creating a subtitution set containing conf. { inherit conf; } is a shorhand for { conf = conf; }.
2 Pass the substitutions to getPosts argument set.
3 Pass the substitutions to getDrafts argument set.

In the markdown file, substitutions are used by surround it by @.

It impossible to use any nix expression in the substitution.
Using a substitution in a mardown file
  Learn more in the [Styx 0.1.0 Documentation](@conf.siteUrl@/documentation-v0-1-0.html). (1)
1 As conf is in the substitution set, it is possible to access any of its values by surrounding it by @.

6.5. Metadata

It is possible to set metadata to markdown files that will be merged to the page attribute set. File metadata must a valid nix set between {--- and ---}.

Adding metadata to a markdown file
{---
{
  title = "Hello World!";
}
---}

Lorem ipsum ...

7. Themes

Themes are used handle templates and static files and are the main way to customize Styx sites.

Styx comes with a simple default theme.

7.1. Structure

Themes are stored in conf.themesDir, themes by default, and every theme is stored in its own directory.

Anatomy of a Styx theme
themes
└── NAME (1)
    ├── files (2)
    └── templates (3)
1 Name of the theme. The name should be a valid folder name.
2 files is a folder holding static files for the themes. All the files in this folder will be copied in the generated site.
3 templates is a folder storing all the templates files.

Every template in the templates will be accessible by its file basename in the templates attribute set. Folders are converted to nested sets.

Example of a template directory structure
├── archive.nix
└── post
    ├── full.nix
    └── list.nix
Generated attribute set
templates = {
  archive = ./archive.nix;
  posts = {
    full = ./posts/full.nix;
    list = ./posts/list.nix;
  };
};

7.2. Themes in site.nix

Themes are declared as a list in the themes variable.

Declaring used themes
  themes = [ "default" ]; (1)
1 The themes variable is a list of theme names, it is possible to set multiple themes. In that cases, themes at the head of the list have a higher priority.

Themes related files are automatically loaded in site.nix via the lib.themes.loadTemplates and lib.themes.loadFiles functions.

Loading theme related files
  templates = lib.themes.loadTemplates { (1)
    inherit themes defaultEnvironment customEnvironments;
    themesDir = conf.themesDir;
  };

  files = lib.themes.loadFiles { (2)
    inherit themes;
    themesDir = conf.themesDir;
  };

  themes = [ "default" ];
1 Load themes templates. See loadFiles for details.
2 Load themes files. See loadTemplates for details.

7.3. Combining Themes

In site.nix, themes are declared as a list. If multiple themes in the list provide the same file or template, the one from the first theme to declare it will be used.

This allows to "extends" themes without modifying them.

For example, to use the default theme but only change the layout template. It is possible to create a new theme, and copy the layout.nix template in the new theme templates folder and change only this file.

Creating a new foo theme
$ mkdir themes/foo (1)
$ mkdir themes/foo/{templates,files} (2)
$ cp themes/{default,foo}/templates/layout.nix (3)
1 Create the theme directory.
2 Create the theme required directories.
3 Copying default theme layout.nix to foo theme.

After a new theme has been created, it must be load in the site.nix to be used.

Using foo and default themes in site.nix
  themes = [ "foo" "default" ]; (1)
1 This will use foo and default theme, with foo having a higher priority than default.

8. Templates

Styx templates are functions that return text or page attribute sets when fully evaluated.

Templates are divided in two types:

  • Layout templates, responsible for the final rendering of a page, it must return text. (page attribute set layout key)

  • Partial templates, responsible for the partial rendering of a page, it should return a page attibute set, but in some special cases can return text. (page attribute set template key)

The template evaluation flow is:

  • The partial template evaluate the page attribute set and generates a partial result that is stored in the page attribute set content key.

  • The layout template evaluate the page attribute set returned by the partial template and produce the final source of the page.

8.1. Text handling basics

Most of the work in template is done by manipulating text.

This introduce the basics of text handling in the templates:

  • multi-line text, delimited by ''.

    Multi-line text
    ''
      Hello world!
      Hello Styx!
    ''
  • single line text, delimited by ".

    Multi-line text
    "Hello world!"

Nix expressions can be included in text in enclosed in ${…​}.

Expression antiquotation
let name = "world"; in
"Hello ${name}!"

8.2. Layout templates

The layout template is responsible for rendering the final source of the page. The layout template function usually takes a template environment, and a page attribute set with a content. (There are exceptions)

In a HTML context, the layout template is usually responsible of the HTML code that is not directly related to the content, like the head tag.

Layout template example
env:
page:
''
  <html>
    ...
  <body>
    ...
    ${page.content}
    ...
  </body>
  </html>
''
Layout templates are just functions, in case the partial template return the full page source like in the rss feed case, it is possible to set the page layout to the id function. This will make the layout evaluation transparent and return the template result.

8.3. Partial templates

Partial templates are similar to the layout templates, with the only difference that their result will be evaluated by the layout template. The partial template should set or update the content attribute of the page attribute set so the layout template can render the final source.

Partial templates can also add other attributes to the page attribute to fit any special need.

Example of a partial template
{ templates, ... }:
page:
let
  content =
    ''
      <h1>${page.title}</h1>
    '';
in
  page // { inherit content; }
In some cases, it is useful to have the partial template to return the final source of the page. By setting the page layout to the id function, it is possible to bypass the layout template and have the partial template result being the final source source of the page.

8.4. Template environment

The template environment is the first parameter of the template function. It is defined when loading the template in site.nix.

The default template environment consists in:

  • conf: the configuration attribute set

  • lib: the library attribute set, it contains Styx and nixpkgs functions.

  • state: the state attribute set, by default it only holds the timestamp of the generation

  • templates: the templates attribute set

It is possible to extend the default template environment to fit custom needs.

It is possible to set a specific template environment to a specific template by declaring it in the customTemplateEnvironments set.

Setting custom template environments
  customEnvironments = {
    layout = defaultEnvironment // { inherit navbar; feed = pages.feed; }; (1)
  };
1 The environment passed to the layout template is the default environment extended with feed and navbar variables.

8.4.1. Template environment in templates

There are two ways of writing the environment in the template, as a set or as a deconstructed set.

Environment as a variable
environment: (1)
page:
''
  ${environment.conf.siteTitle}
''
1 environment is used as a set, and its key can be accessed with ..
Environment as a deconstructed set
{ conf, lib, ... }: (1)
page: (1)
''
  ${conf.siteTitle}
''
1 environment is deconstructed in its keys values. The last …​ means all others keys and is required if the set contains more keys than the keys deconstructed.

8.5. Calling templates in templates

It is possible to call templates in a template by accessing to the templates attribute of the template generic environment.

Calling a template in a template
{ templates, ... }:
page:
''
  ${templates.foo}
''
The loadTemplateWithEnv function, or calling the loadTemplate with an environment will partially evaluate the template function. This means that the template function will be become a single argument function (page).
Trying to call the current template will trigger an infinite loop and make the site generation fail.

8.6. Applying templates to multiple contents

The mapTemplate function can be used to map a template to a list of contents.

Applying a template to multiple contents
{ templates, ... }:
page:
''
  ${mapTemplate templates.post.list page.posts}
''

9. Library

The library contains various functions that are used through Styx source. The functions are grouped in namespaces, but are also all included in the top-level scope to be used in an easy way.

9.1. generation

This namespace contains functions related to content generation.


generateSite
Description

Generate a site with a list of pages. This is the function returned by site.nix.

Parameter Type

Set

Parameters
  • files: A list of folders to copy in the site.

  • pagesList: A list of pages to generate.

  • preGen (optional): A set of commands to execute before generating the site.

  • postGen (optional): A set of commands to execute after generating the site.

Return

A static site.

Example
generateSite { inherit conf pagesList; }

pagesToList
Description

Convert an attribute set of pages to a list of pages. Useful to convert the pages attribute set in site.nix to a page list for generateSite. Parameter Type: Standard

Parameters
  • pages: An attributes which every key value is a page attribute set or a list of page attribute sets.

Return

A list of pages.

Example
pages = {
  about = {
    href = "about.html";
    template = templates.about;
  } // (parsePage conf.pagesDir "about.md");
};

pagesList = pagesToList pages;

splitPage
Description

Split a page in multiple pages according to parameters. Used for pagination like pages.

Parameter Type

Set

Parameters
  • baseHref: The href of the archive pages, the first page href will be baseHref.html, following pages href will be baseHref-i.html where i is the index number of the page.

  • items: Items to be split through the pages.

  • template: The template used by the split pages.

  • itemsPerPage: Maximum number of items displayed on each page.

  • Any extra arguments will be included in the split pages attribute set.

Return

A list page attribute sets.

Example
archives = splitPage {
  baseHref = "archives/posts";
  template = templates.archive;
  items = posts;
  itemsPerPage = conf.postsPerArchivePage;
  title = "Posts";
};

9.2. nixpkgs

This namespace include the nixpkgs library and builtins functions.

9.3. content

This namespace contains functions to manipulate content, especially posts.


getPosts
Description

Fetch all the posts from a postDir.

Parameter Type

Attribute Set

Parameters
  • from: Path to the folder containing the posts.

  • to: Part before the name of the post attribute set href. Should not contain leading and trailing /.

  • substitutions: An attribute set containing substitutions (Optional). For details, see Substitutions.

Return

A list of post attribute sets.

Example
posts = getPosts { from = conf.postsDir; to = "posts"; };
The posts attribute sets href depends on the post file name and the outDir. For a post in a file 2016-09-12-welcome-to-styx.md and an outDir set to posts, the generated post href will be posts/2016-09-12-welcome-to-styx.html.

getDrafts
Description

Fetch all the posts from a postDir. This function is similar to getPosts, but add a isDraft = true attribute to every draft attribute set.

Parameter Type

Attribute Set

Parameters
  • from: Path to the folder containing the posts.

  • to: Part before the name of the post attribute set href. Should not contain leading and trailing /.

  • substitutions: An attribute set containing substitutions (Optional). For details, see Substitutions.

Return

A list of draft attribute sets.

Example
posts = getDrafts { from = conf.draftsDir; to = "drafts"; };

parsePage
Description

Parse a markdown file to a partial page attribute set.

Parameter Type

Attribute Set

Parameters
  • dir: Path to the folder containing the page.

  • file: Page file name.

  • substitutions: An attribute set containing substitutions (Optional). For details, see Substitutions.

Return

An attribute set containing content (the page HTML source) and title.

Example
  about = {
    href = "about.html";
    template = templates.about;
    breadcrumbs = [ index ];
  } // (parsePage { dir = conf.pagesDir; file = "about.md"; });

parsePost
Description

Convert a post file into a post attribute set.

Parameter Type

Standard

Parameters
  • postDir: Path to the folder containing the post.

  • filename: Post file name.

Return

A post attribute set.

Example
myPost = parsePost conf.postsDir "2016-09-12-welcome-to-styx.md";
parsePost is also used for drafts as posts and drafts have similar structures.

sortPosts
Description

Sort a list of posts chronologically.

Parameter Type

Standard

Parameters
  • postList: A list of posts to sort.

Return

The sorted list of posts.

Example
sortedPosts = sortPosts (getPosts conf.postsDir "posts");

9.4. template

This namespace contains functions useful in templates.


htmlAttr
Description

Generate an HTML attribute.

Parameter Type

Standard

Parameters
  • attrName: The attribute name.

  • value: The attribute value, can be a list.

Return

An HTML attribute.

Example
htmlAttr "class" "foo"
=> class="foo"

htmlAttr "class" [ "foo" "bar" ]
=> class="foo bar"

mapTemplate
Description

Map a template to a list of items.

Parameter Type

Standard

Parameters
  • template: The template function.

  • list: A list of items passed to the template function.

Return

Resulting HTML.

Example
mapTemplate templates.post.list page.posts

prettyTimestamp
Description

Convert a timestamp to a prettier format.

Parameter Type

Standard

Parameters
  • timestamp: A timestamp in the format YYYY-MM-DD.

Return

A timestamp in format DD MMM YYYY.

Example
prettyTimestamp "2016-09-26"
=> "26 SEP 2016"

9.5. themes

This namespace contains functions to load themes data.


loadFiles
Description

Load a themes set static files.

Parameter Type

Attribute set

Parameters
  • themes: List of themes names to load static files from.

  • themesDir: Directory of the themes.

Return

List of static files folders.

Example
  files = lib.themes.loadFiles {
    themes = [ "default" ];
    themesDir = conf.themesDir;
  };

loadTemplates
Description

Load a theme set templates.

Parameter Type

Attribute set

Parameters
  • themes: List of themes names to load static files from.

  • themesDir: Directory of the themes.

  • defaultEnvironment: The default environment to load templates with.

  • customEnvironments: A set of with a similar structure to the template set which values are environment to pass to the template. Any template that is not in customEnvironments will use the defaultEnvironment.

Return

List of static files folders.

Example
  templates = lib.themes.loadTemplates rec {
    themes = [ "default" ];
    themesDir = conf.themesDir;
    defaultEnvironment = { inherit conf state lib templates; };
    customEnvironment = {
      layout = defaultEnvironment // { inherit navbar; feed = pages.feed; };
    };
  };

9.6. utils

This namespace contains various utility functions.


overrideConf
Description

Extend the configuration attribute set.

Parameter Type

Standard

Parameters
  • conf: The configuration attribute set.

  • override: The override configuration set.

Return

Overridden configuration.

Example
conf = overrideConf (import ./conf.nix) args;

setDefaultLayout
Description

Set a layout to a page attribute set. Does nothing if the page attribute set has already a layout.

Parameter Type

Standard

Parameters
  • layout: The layout template.

  • page: A page attribute set.

Return

A page attribute set with layout set.

Example
  pagesList =
    let list = (pagesToList pages);
    in map (setDefaultLayout templates.layout) list;

setTemplate
Description

Set a template to a page attribute set.

Parameter Type

Standard

Parameters
  • template: The template function.

  • page: A page attribute set.

Return

The template function partially evaluated.

Example
map (setTemplate templates.post.full) (posts ++ drafts)

10. Cookbook

10.1. NavBar

There is an example of NavBar setting in the default site.nix. Because the NavBar is a site wide feature is should be applied to the layout template (layout.nix).

Setting a Navbar consists in two steps:

  1. Extending the base template environment to include a list of pages that should be in the NavBar.

    Example from site.nix:

      navbar = let (1)
                 archive = (head pages.archives) // { title = "Archives"; }; (2)
               in [ archive pages.about ]; (3)
    
      customEnvironments = { (4)
        layout = defaultEnvironment // { inherit navbar; feed = pages.feed; }; (5)
      };
    1 Declaring a navbar variable.
    2 Declare an archive variable in the local scope. pages.archives is a list of pages so we extract the first page with head pages.archive, then we extends this page by setting a title using the // operator.
    3 The navbar value is a list containing the first archive page and the about page.
    4 Declares custom template environments. Custom environements are a set mimicking the templates atteibute set, ut where the value is the environment to apply to the template.
    5 defaultEnvironment is the default template environment, but as we want to pass the navbar variable to the template, we extends the environment with navbar.
    { inherit navbar; } is a shortcut to { navbar = navbar; }
  2. Using the NavBar template.

    Styx provides a template for generating the Navbar, navbar.main.nix.

    Example, calling the NavBar template in a template:

    ${templates.navbar.main navbar} (1)
    1 navbar must be a list of pages as showed in the previous section.
    The brand part of the NavBar displays conf.siteTitle by default. To set the NavBar brand to something different than conf.siteTitle, it is recommended to directly edit and change the navbar.brand.nix template.

10.2. Pagination

The pagination.nix template provide a generic way to generate a pagination.

Using in a page generated by the splitPage function
templates.pagination { pages = page.pages; index = page.index; }

The Styx library provide a splitPage function that can be used to split a page in multiple pages according to a list of items and a number of items to display per page.

Its arguments are:

  • baseHref: href of the archive pages, the first page href will be baseHref.html, following pages href will be baseHref-i.html where i is the index number of the page.

  • template: template used by the split pages.

  • items: items to be split through the pages.

  • itemsPerPage: maximum number of items displayed on each page.

Splitting posts into multiple archive pages
archives = splitPage {
  baseHref = "archives/posts";
  template = templates.archive;
  items = posts;
  itemsPerPage = conf.postsPerArchivePage;
  title = "Posts";
};

It is then possible to use the previous snippet in the used template to add a pagination.

The pagination is only displayed if there is more than one page to display.

10.3. Breadcrumbs

Breadcrumbs are enbaled by adding a breadcrumbs attribute with the list of pages to include in the breadcrumbs to a page attribute set. A page attribute set without a breadcrumbs attribute will not display breadcrumbs.

Adding breadcrumbs to a page
about = {
  href = "about.html";
  template = templates.about;
  title = "About";
  breadcrumbs = [ index ];
};

Breadcrumbs are generated with the breadcrumbs.nix template. The default base template include this template.

The text of the breadcrumb will be the page title. To set a breadcrumb title that is different of title, it is possible to use the breadcrumbTitle attribute.

11. Deployment

11.1. GitHub pages

Styx support basic deployment to GitHub pages.

This is a two step process, initialization og the gh-pages branch and update of the gh-branch with the built site.

Setting a Styx site for GitHub pages
$ styx new mysite && cd mysite (1)
$ git init && git add . && git commit -m "Initializing Styx site" (2)
$ styx deploy --init-gh-pages (3)
$ styx deploy --gh-pages (4)
1 Creating a new styx site and entering the new site folder.
2 Initializing a git repository with all the files and commiting.
3 Creating an empty gh-pages branch.
4 Building the Styx site and commiting the changes to gh-pages

Then it is just a matter to push the gh-pages branch to your GitHub repository and the site will be published.

styx deploy --init-gh-pages and styx deploy --gh-pages involve git checkouts. Every time git make a checkout, the files timestamp change. This means that two successive styx deploy --gh-pages will create changes, namely every part of the Styx site that depends on the lastChange argument. (Feed by default)

11.2. Other

Styx does not yet provide a universal deployment method, but rsync can be used to deploy a Styx site to a remote server via ssh.

12. Release Notes

12.1. Styx 0.2.0 - 2016/10/10

Highlights:

New features:

  • cli command

  • new preview subcommand to preview a site locally

  • new live subcommand to preview and automatically reload changes

  • serve subcommands new flags:

  • --detach to launch the server in a background process

  • --server-host to specify the server listening hostname

  • --siteUrl to override conf.siteUrl

  • new -target flag to specify the Styx site folder

  • content substitutions (Substitutions)

  • themes (Themes)

  • metadata (Metadata)

  • 404 error page template

Incompatible changes:

  • default.nix was renamed to site.nix

  • site.nix previewMode was renamed to renderDrafts

  • cli --preview flag has been renamed to --drafts

  • lib.content: getPosts, getDrafts and parsePage arguments have changed

  • lib.generation: generateSite arguments have changed

  • lib.utils: loadTemplateWithEnv function was removed

Bug Fixes:

  • nix link in the default theme layout template

  • styx new is working when called in empty folders

  • default theme archive title is not hardcoded

  • default them pagination is displayed only when there is more than one page

This release bring many major changes that make updating from 0.1.0 non-trivial.

To update, it is recommended to generate a new site, create a new theme with customized templates and static files, and update site.nix accordingly.

12.2. Styx 0.1.0 - 2016/10/07

Initial release of Styx.