A minimal Twine 2 story format designed for people who already know JavaScript and CSS
Clone or download
Latest commit 4f7525f Dec 15, 2018



Snowman is a minimal Twine 2 story format designed for people who already know JavaScript and CSS. It's designed to implement basic functionality for playing Twine stories and then get out of your way.

Snowman includes jQuery and Underscore for you.

Changes From The Norm

Snowman uses Markdown formatting in its passage syntax. Instead of invoking macros with <<double angle brackets>>, it uses Underscore templating to provide interactivity. Specifically, passages are rendered onscreen with this process:

  1. The passage source is run through Underscore's _.template() method. Code in <% blocks %> receive two special variables:

    • s, which is a shorthand for window.story.state
    • $, which acts like jQuery's $ method but with one exception. If you pass it a single function, this function is run when the passage appears onscreen, with it bound to the passage DOM element.
  2. Comments inside /* inline blocks */ are removed, as are // line comments. // comments remove their line break, so that:

The die comes up...

// TODO: randomize this properly

is rendered as:

The die comes up...


Line comments (that is, ones that start with //) may be used at the very start of a line. This is to avoid problems when URLs appear in the text, which might otherwise accidentally trigger a comment.

  1. <div> elements are created from text formatted like this:
This appears onscreen.

The opening bracket must be the only text on the line, and the closing bracket must be the first character of the line it's on. The newlines between the brackets are removed from the rendered <div>, but otherwise spacing is kept intact. You can add as many classes as you like, e.g. {.class1.class2}, and leave off an ID. You can specify an empty <div> with this code:


And if you would like the <div> to start hidden (that is, with the CSS property display: none), put a minus sign (-) as the first character after the curly brackets. This can be useful if you'd like to manually control when the <div> is shown -- for example, making it visible after a delay or some other event has taken place. The syntax to do so looks like this:

This message is hidden!
  1. <span> elements are created from text [formatted like this]{#id.className}. Apart from the brackets staying on the same line as the text, the same rules as for <div> elements apply.

  2. All double-bracketed links ([[passage]], [[displayed->passage]], and [[passage<-displayed]] are converted to functional links.

  3. Finally, the result of this is rendered with the Marked Markdown parser.

By default, clicking a passage link does not add an entry to the reader's browser history. See story.checkpoint() for how to do this.

Building From Source

Run npm install to install dependencies. npm run build will create a Twine 2-ready story format under dist/, as well as a guide to Snowman features at dist/guide.html. npm start will start a file watching process that updates the story format as changes are made under src/.

To check for style errors, run npm run lint. To run unit tests, run npm test. Please ensure that both run cleanly before submitting a pull request.