Introduction

Header image with template and query

Snowman is a static site generator for SPARQL backends.

Snowman's templating system comes with RDF- and SPARQL-tailored features and takes its data from SPARQL queries. Snowman has first-class support for RDF concepts like: Language-tagged literals, IRIs, and XSD datatypes.

Jump right in

Background

Ever seen a project that models its data in RDF, but then uses a non-RDF technology to render it?

Snowman is designed to address this by allow RDF-based projects to use SPARQL in the user-facing parts of their stack, without sacrificing preformance. Today, Snowman is used to render everything from simple SKOS vocabularies to entire knowledge bases.

Snowman is not a high-level web-framework, actually, turns out people use it for a lot of things like data transformation and APIs! As a result, Snowman is rather unopinionated about how you structure your project, transforming data directly in SPARQL queries? or with the template engine? or both? It's up to you, that said, we have a style guide and some best practices to help you get started.

Installation

Snowman ships as a single binary, and is available for the most commons architectures and operating systems. Check out the releases page for the latest version. Once downloaded, you should rename it to snowman and install it by moving it to a directory in your PATH.

Using multiple versions

If you need to use multiple versions of Snowman, you can either rename the binary to something like snowman-0.5.0 and then symlink it to snowman in your PATH or use it directly by specifying the path to the binary(./path/to/snowman).

Installing from source

If you would want to compile from source, you can do so:

git clone https://github.com/glaciers-in-archives/snowman
cd snowman
go build -o snowman

For all possible target operating systems and architectures, see the the following table.

Quick start

snowman new  --directory="best-project-name-ever"
cd best-project-name-ever
snowman build && snowman server

This will create a new Snowman project in the directory best-project-name-ever, build it, and start a local server. You can now visit http://localhost:8080 to see the built site. To get you started it fetches a few triples from Wikidata, gives you a basic layout, and a static file.

The project structure

The project structure upon using the snowman new command is as follows:

best-project-name-ever
├── queries # your SPARQL queries go here, create subdirectories to organize them
│   └── index.rq
├── static # static files go here, they are copied to the root of the build directory, make subdirectories to modify the output path
│   └── style.css
├── templates # your templates go here, create subdirectories to organize them, go beyond HTML!
    ├── includes # common name for components and partial templates
    │   └── footer.html
    ├── layouts # layouts are special templates that wrap other templates
    │   └── default.html
    ├── static.html # a page not feed by SPARQL but with full access to the template engine
    └── index.html # a page feed by SPARQL
├── snowman.yaml # core configuration go here, like the SPARQL endpoint and site metadata
└── views.yaml # all your views go here, a view connects a template to a SPARQL query, look for the index.html and static.html in this file

CLI

Snowman's command line interface (CLI) is the primary way to interact with a Snowman project. The CLI provides a set of commands to manage and build a Snowman project. The CLI is intended for development and continuous integration/delivery purposes.

build

The build command is used to build a Snowman project. It reads the configuration(snowman.yaml) file and the views file(views.yaml), then it fetches the data from a SPARQL endpoint, and finally it renders the templates. The output is written to the site directory.

snowman build

Flags

  • --cache (-c) Sets the cache strategy. "available" will use cached SPARQL responses when available and fallback to making queries. "never" will ignore existing cache and will not update or set new cache. (default "available")
  • --config (-f) The path to the configuration file. (default "snowman.yaml")
  • --snowman-directory (-d) The path to your Snowman directory. (default ".snowman")
  • --help (-h) Shows help for the command.
  • --verbose (-v) Enables verbose output.
  • --static (-s) Only update static files, do not fetch data or render templates.
  • --timeit (-t) Print the time it took to build the site.

cache

The cache command is a powerful tool used to manage the query cache of a Snowman project. By defualt, Snowman will cache SPARQL responses to avoid making the same query multiple times even across multiple builds. This command allows you to inspect and clear all or subsets of the cache.

snowman cache [optional-query] [optional-query-arguments]

Flags

  • --invalidate (-i) Invalidates the cache for the given scope. If no query is given, the entire cache is invalidated. If a query but no query arguments are given, the cache for all queries using the given query file is invalidated.
  • --unused Sets the scope to all queries not used during the last build.
  • --snowman-directory (-d) The path to your Snowman directory. (default ".snowman")
  • --help (-h) Shows help for the command.
  • --verbose (-v) Enables verbose output.
  • --timeit (-t) Shows the time it took to execute the command.

completion

The completion command generates shell completion scripts for the Snowman CLI.

snowman completion <shell>

Arguments

  • bash Generates a bash completion script.
  • zsh Generates a zsh completion script.
  • fish Generates a fish completion script.
  • powershell Generates a powershell completion script.

Flags

  • --help (-h) Shows help for the command if used in combination with an argument it will show installation instructions for the completion script.

new

The new command is used to scaffold a new Snowman project by setting up a basic project structure and configuration files.

snowman new  --directory="best-project-name-ever"

See the quick start for more information about the generated project structure.

Flags

  • --directory (-d) The name of the directory to create the project in. (default "my-new-project")
  • --help (-h) Shows help for the command.

server

The server command is used to start a local server to serve the built site. It's only intended for development purposes.

snowman server

Flags

  • --address (-a) The address to listen on. (default "127.0.0.1")
  • --help (-h) Shows help for the command.
  • --port (-p) The port to listen on. (default "8000")

version

The version command prints the version of Snowman.

snowman version

Format

The output is a single line consisting of three parts separated by spaces:

Snowman 0.5.0-development linux/amd64
  1. The name of the application, allways Snowman.
  2. The version of the application(semver).
  3. The operating system and architecture the binary was built for.

Flags

  • --help (-h) Shows help for the command.

Template syntax

Snowman uses Go templates to render the output of a Snowman project. While Go provides their own documentation on how to use its templatings systen we do the same here but with a focus on how to use it with Snowman.

Variables

Variables can be defined inside of templates by using a keyword prefixed with $:

{{ $my_variable := "this is a string" }}

To change the value of a existing variable:

{{ $my_variable = "this is a new string" }}

Variables initiated by a control-structure(such as a range statement) is accessed by the special variable .:

{{ range $my_list }}
    Current list item: {{ . }}
{{ end }}

Fields can be assesed by suffixing your variable name with . followed by the field name:

{{ $my_other_variable.A_field }}

A variable’s scope extends to the end action of the control structure in which it is declared, or to the end of the template if there is no such control structure.

Comments

Comments are not rendered in the output. They are useful for adding notes to the source code that are not meant to be displayed in the output.

{{/* my very important comment */}}

Comments can span multiple lines.

{{/*
  This is a comment
  that spans multiple lines
*/}}

Comments can also contain trim markers to remove surrounding whitespace. To learn more about trim makers see the chapter on whitespace control.

{{- /* this is a comment with trim markers */ -}}

Whitespace control

Snowman templates renders everything between code blocks and comments including whitespace and line feeds. As a result the output can look messy. To control the extra white whitespace in the output you can use trim markers.

Considering the following example.

<ul>
{{ range .foos }}
    <li>list item</li>
{{ end }}
</ul>

The {{ range .foos }} and {{ end }} blocks are sourrounded line breaks which will be rendered in the output. To remove the extra whitespace you can use trim markers.

<ul>
{{- range .foos -}}
    <li>list item</li>
{{- end -}}
</ul>

The - is optional and can be placed on either side of the block. The following example will render in the same way as the previous example.

<ul>{{ range .foos -}}
    <li>list item</li>
{{- end }}</ul>

You can also use trim markers with comments:

{{- /* this is a comment with trim markers */ -}}

Loops

This page is a stub. You can help by expanding it.

Conditionals

This page is a stub. You can help by expanding it.

Indexing

This page is a stub. You can help by expanding it.

Includes

This page is a stub. You can help by expanding it.

Layouts

This page is a stub. You can help by expanding it.

Pipes

This page is a stub. You can help by expanding it.

Template functions

While Snowman is built on top of Go's templating system it do provide its own set of template function to make it easier to work with RDF data and RDF defined data types.

Math

add

The add function preforms addition on two numbers.

{{ add 5 6 }}

sub

The sub function subtracts two given integer values.

{{ sub 10 5 }}

mul

The mul function multiplies two given integer values.

{{ mul 5 6 }}

div

The div function divides two given integer values.

{{ div 10 2 }}

mod

The mod function returns the modulus of two given values.

{{ mod 5 2 }}

add1

The add1 function increments the given integer by 1.

{{ add1 3 }}

rand

Given two values, the rand function returns a random integer between them.

{{ rand 5 10 }}

Boolean

and

The and function returns true if all of the given boolean values are true, otherwise it returns false.

{{ and $variable1 $variable2 }}

or

The or function returns true if any of the given boolean values are true.

{{ or $variable1 $variable2 }}

not

The not function returns the negation of the given boolean value.

{{ not $variable }}

eg

The eg function returns the boolean truth of arg1 == arg2.

{{ eg $variable1 $variable2 }}

ne

The ne function returns the boolean truth of arg1 != arg2.

{{ ne $variable1 $variable2 }}

lt

The lt function returns the boolean truth of arg1 < arg2.

{{ lt $variable1 $variable2 }}

le

The le function returns the boolean truth of arg1 <= arg2.

{{ le $variable1 $variable2 }}

gt

The gt function returns the boolean truth of arg1 > arg2.

{{ gt $variable1 $variable2 }}

ge

The ge function returns the boolean truth of arg1 >= arg2.

{{ ge $variable1 $variable2 }}

Strings

print

The print function formats using the default formats for its arguments and returns the resulting string. Spaces are added between arguments when neither is a string.

{{ print $variable1 $variable2 }}

printf

The printf function formats according to a format specifier and returns the resulting string.

{{ printf "%s %s" "hello" "world" }}

println

The println function formats using the default formats for its arguments.Spaces are always added between operands and a newline is appended.

{{ println $variable1 $variable2 }}

join

The ´join´ function which takes a separator and any number of strings and concatenates them, separating each with the separator string.

{{ join ", " "apple" "orange" "banana" }}

split

The split function splits a string into a list of substrings separated by a delimiter.

{{ split "hello world" " " }}

replace

replace function replaces substrings in a string with a given string.

The first argument is the string to which the replacement is to be applied, the second argument is the substring to be replaced, the third argument is the substring to replace with and finally the fourth argument is the number of replacements to be made. If the fourth argument is is set to -1 then all occurrences will be replaced.

{{ replace "hello world" "world" "earth" -1 }}

replace_re

The replace_re function replaces substrings in a string with another string using a regular expression.

{{ re_replace "Hello world" "world$" "Snowman" }}

ucase

The ucase function converts a string to uppercase.

{{ ucase "hello world" }}

lcase

The lcase function converts a string to lowercase.

{{ lcase "HELLO WORLD" }}

tcase

The tcase function formats a string accoring to title case rules.

{{ tcase "hello world" }}

has_prefix

The has_prefix function tests whether the given string begins with the given prefix.

{{ has_prefix "hello world" "hello" }}

has_suffix

The has_suffix function tests whether the given string ends with the given suffix.

{{ has_suffix "hello world" "world" }}

trim

The trim function removes leading and trailing whitespace from a string.

{{ trim "  hello world  " }}

contains

The contains function returns true if the string contains the substring, otherwise false.

{{ contains "hello world" "hello" }}

Typing

type

The type function returns the type of the value passed to it.

{{ type 42 }}

uri

The uri function takes a string and casts it to a URI.

{{ uri "https://schema.org/Person" }}

JSON

to_json

The to_json function takes a value and converts it to an JSON string.

{{ to_json "Alice" }}

from_json

The from from_json function takes a string and parses it as JSON.

{{ from_json "{\"name\": \"Alice\"}" }}

HTTP

query

The query function allows for the issuing of SPARQL queries or parameterized SPARQL queries from within templates. The function takes one or more parameters. The first is the name of the query, and the following parameters, optionally, is are strings to inject into the query. The given injection strings will replace instances of {{.}} in their given order.

{{ query "name_of_parameterized_query.rq" "param" }}
{{ query "name_of_query.rq" }}

get_remote

The get_remote function fetches the content of a remote URL and returns it as a string.

{{ get_remote "https://example.com" }}

get_remote_with_config

The get_remote_with_config function fetches the content of a remote URL and returns it as a string. It takes a configuration object as an argument, which can be used to set custom HTTP headers.

{{ get_remote_with_config "https://example.com" $config }}

Templates

include

The ìnclude` function can be used to insert another HTML template at its position during rendering. The function takes a mandatory argument, the path to the template which should be included, as well as any number of additional arguments which will be passed to the included template.

{{ include "includes/profile-picture-element.html" $pictureURI $pictureAltText }}

include_text

The ìnclude_text` function can be used to insert another text template at its position during rendering. The function takes a mandatory argument, the path to the template which should be included, as well as any number of additional arguments which will be passed to the included template.

{{ include_text "includes/description.txt" $description }}

Utilities

now

now returns the current date and time in the requested format. The function takes a format string as an argument.

{{ now.Format "2006-01-02" }}
{{ now.UTC.Year }}

This function is derived from the Go time.Now function. For more on how to format dates, see the official Go documentation.

env

env allows you to access environment variables from within your templates. env takes the name of the environment variable as an argument and returns its value as a string.

{{ env "PATH" }}

config

Snowman exposes your site's configuration through the function config. The following example illustrates how to retrieve your SPARQL endpoint:

{{ config.Client.Endpoint }}

safe_html

The safe_html function allows you to render an HTML string as-is, without the default escaping performed in HTML/unsafe templates.

{{ safe_html "<p>This renders as HTML</p>" }}

Note that you should only use with content you trust and control, as it can expose your site to cross-site scripting attacks.

read_file

The read_file function reads the contents of a file and returns it as a string.

{{ read_file "relative/path/to/file.txt" }}

Note that the path must be relative to the root of the project and that Snowman do not have access to files outside of the project directory.

current_view

The current_view function return the configuration of the view being rendered.

{{ current_view }}

Note that thecurret_viewfunction isn't available when used inside of templates included using theincludeorinclude_texfunctions. You can however pass the value ofcurrent_view` as an argument to the included template:

{{ include "includes/child-template-aware-of-the-view.html" $current_view }}

version

The version function returns the Snowman version used to build the page.

{{ version }}

len

len returns the integer length of its argument.

js

js returns the escaped JavaScript equivalent of its arguments.

index

index returns the item at the given position from a slice, array or map.

index $my_map 0

Configuration

This page is a stub. You can help by expanding it.

snowman.yaml

snowman.yaml contains the core configuartion needed to build your project such as the SPARQL endpoint you are targeting and project specific metadata.

A typical snowman.yaml looks like this, however only the SPARQL client and its endpoint is mandatory:

sparql_client:
  endpoint: "https://query.wikidata.org/sparql"
  http_headers:
    User-Agent: "example Snowman (https://github.com/glaciers-in-archives/snowman)"
metadata:
  production_setting: "a config value"

Note that while Snowman will look for snowman.yaml by default you can point to other files when building your project:

snowman build --config=production-snowman.yaml

This is useful if you need to build your proejct in various environments such as development, CI, and production.

views.yaml

views.yaml connects you queries with your templates and assignes an output path to each pair. You can think of it as Snowman's router or controller.

Snowman have two different types of views. One which outputs a single file and forwards all of the query results to the template.

views:
  - output: "index.html"
    query: "index.rq"
    template: "index.html"

The second outputs one file per SPARQL result(row) and takes one of the returned SPARQL-variables as a path argument. The following would therefore need a query which returns a ?id variable for each row. Only the row is forwarded to the template.

views:
  - output: "entities/{{id}}.html"
    query: "entities.rq"
    template: "entity.html"

Non-HTML templates

By default Snowman uses HTML-aware templates which escapes <, >, etc as well as CSS and JavaScript. To disable this behaviour for a given view you can set the unsafe option.

You should never use this for HTML templates, instead you should use the safe_html template function to manage unsafe injections on a case-to-case basics.

views:
  - output: "sitemap.xml"
    query: "entities.rq"
    template: "sitemap.xml"
    unsafe: true

Style guide

This page is a stub. You can help by expanding it.

CLI autocompletion

The completion command can generate autocompletion scripts for the most common shells. It's recommended that you don't use these scripts directly as you would need to update them each time you update Snowman. Instead you should make your shell call this function.

To examplify, in the Fish shell you would use the following for autocompletion:

snowman completion fish | source

Working with multiple environments

If you need different snowman.yaml configurations for different environments you can use the config build flag to build your project using configurations other than the default snowman.yaml.

snowman build --config=production-snowman.yaml

You can also read environment variables using the built-in template function env.

Managing cache

This page is a stub. You can help by expanding it.

Timing builds

Sometimes when you work on large sites, it can be useful to time your build processes to measure the impact of changes. All Snowman commands, therefore, have a flag named timeit. This prints a command's execution time to the console. While this is mostly useful for measuring build times, all Snowman commands support it.

snowman build --timeit

Multilangual RDF labels

When a RDF literal has a associated language you can access it by prefixing your template variable with .Lang.

<span lang="{{ .name.Lang }}">{{ .name }}</span>

Rendering JSON

This page is a stub. You can help by expanding it.

Rendering XML

This page is a stub. You can help by expanding it.

Fetching files

This page is a stub. You can help by expanding it.

Reading local files

This page is a stub. You can help by expanding it.

Retrieving and parsing JSON

This page is a stub. You can help by expanding it.

Site metadata

This page is a stub. You can help by expanding it.

Reading environment variables

This page is a stub. You can help by expanding it.

Parameterized queries

This page is a stub. You can help by expanding it.

Building with Github Actions

This page is a stub. You can help by expanding it.

Building with Gitlab CI

This page is a stub. You can help by expanding it.