Skip to main content

How to use Springheel

This is a walkthrough for getting Springheel working, setting up a comic site, and updating it. (Using an FTP program, registering a domain name, creating an SSH key, etc. are outside the scope of this guide.)

Get Springheel

Springheel requires at least Python 3.7. Versions before Springheel 7.0 require Python 3.5. No version will work with Python 2.

To install from PyPI, simply run

$ pip install springheel

To install from source, you’ll need the following dependencies:

The following dependencies are optional, but are needed to build documentation:

Navigate to the springheel directory, start up your virtual environment if you’re using one, and run setup.py install. (You may need to run this with su -c or --user depending on the type of Python install you have).

Important: If you’re on Windows and get an error about Visual C++ while installing dependencies (lxml especially), do not panic! Just use PyPi to install that specific library directly, then try to install springheel again.

After updating Springheel to a new version, you should generally re-initialize any existing comic sites in case there were changes to the themes or template files. For major versions in particular, check conf.ini against the default one in your install directory (it’s easier with a graphical merge tool like Meld) and add any new configuration options. (springheel-init doesn’t alter or replace configuration files.)

Limitations

Springheel is designed to be as simple and bare-bones as possible, so there are some features it doesn’t have (or just doesn’t have yet). E.g.:

  • The RSS feed may list items out of order if multiple comics have the same posting date.

  • Page commentaries and character descriptions are plain text only (no HTML). This is because parsing markup in those blocks would be much more complicated and slow.

  • Templates have not been translated into many languages yet, and the ones for languages I don’t personally speak may be inaccurate.

  • It’s not possible to have a single site with multiple languages; you can only generate separate sites for each language and display links to the other sites.

  • There is no out-of-the-box support for ads or analytics. See “Extending Springheel Sites” below.

  • Feeds are sitewide (as opposed to one for each individual series out of many) and bare-bones. RSS feeds don’t display thumbnails of the comic, the strip itself, or anything along those lines. (But this may actually be your desired behavior for RSS feeds, in which case, super!)

  • Pages do not use any kind of modernizer or polyfill, so they will not look exactly the same in older browsers that they do in bleeding-edge new ones. They’ll still be perfectly usable, just a bit less fancy. Remember, it doesn’t have to look the same.

  • There is no support for responsive image loading with srcset or similar yet.

Building a site for Wuffle

I’ve provided a sort of “sample site” pack based on a few strips from Wuffle, a cute comic which is public domain. Download it here and let’s walk through the process of using it, step-by-step.

Initialization

To start off, make a directory for this project, and navigate there in your terminal of choice. (You should probably put the ZIP file here to make sure you don’t lose it.)

Next, we’ll run the initialization script. On GNU/Linux this is simply springheel-init.

On Windows, add Python’s Scripts directory to your system path (if you haven’t already), restart as needed, and run springheel-init.exe.

If all goes well, some debug info will appear explaining what is going on: the script locates where Springheel was installed, grabs the templates and other base assets, and copies them to your current directory.

Now unzip the contents of the Wuffle pack, springheel-wuffle-sample-site-pack.zip, into the current directory. Everything in it except the wuffle_conf.ini file should go into input. Remove the current conf.ini file and rename wuffle_conf.ini to simply conf.ini.

Your directory should now look something like this:

.
..
arrows/
input/
socialbuttons/
templates/
themes/
conf.ini

Let’s look at each of these in more detail. You can also skip right down to “Trying to build” and work out this stuff once you already have a generated site to compare it to; the choice is yours.

Base directory

This holds the sitewide configuration file and the input and output folders.

conf.ini is a sitewide configuration file. You’ll definitely want to modify it before building, as we’ve done here – some of the defaults are deliberately silly or non-working.

Asset folders

arrows holds the navigation buttons – they follow the scheme {theme}_{direction}. You can easily make your own if you don’t like the defaults.

Social buttons are 24x24 icons that are used to link to social media sites, like Twitter or Pump. These are also simple to customize. Adding a site that isn’t supported is a bit more involved but still entirely possible.

Input

As per the name, this holds the comic files (images and metadata). Site banners and such go here as well. Right now, this should contain:

  • 10 comic images

  • 10 .meta files

  • 10 .transcript files

  • 1 .conf file

  • 1 .chars file

  • 2 heading/banner images

Templates

These are the templates used to generate the finished pages. One is a JSON file that contains all the translations, and the rest are HTML files.

As long as they’re not based on machine translations, improvements to any language and pull requests for languages I haven’t provided are welcome!

Themes

Themes determine the look and feel of your site. I’ve tried to include a variety of default themes, while also keeping each theme small (even counting graphic assets, more than half of all themes and subthemes are under 15 KiB; only one is over 100 KiB, and none are significantly bigger than that) and simple enough to make your own themes that hook into the existing code easily. They also use color schemes that pass WCAG AAA-level standards for text contrast (no thin cyan text on a white background here), and should also look fine on most small screens.

Our Wuffle example uses the plain theme for simplicity, but it’s by no means the only option. See Themes for more info.

Rolling your own

Creating your own styles is simple enough. Here’s what you must do:

  1. Go to the themes directory, and make a folder there with the title of your theme. It must be a unique name, all lowercase, and without spaces.

  2. Create a file there called style.css. How you create style.css does not matter, as long as it is called that and in the right place. For neatness and ease of memory, I usually use Sass to make a .scss file in themes, and have it compile to a style.css in a matching directory (e.g. themes/plain.scss:themes/plain/style.css). If you’re using any, put all other assets, like images, in the same directory as style.css too.

  3. Design your cool CSS theme. This is the easy part. :)

  4. Make a set of navigation arrows and put them in arrows. For compatibility with Springheel’s code, they should be like this (even if you want the arrows to point the other way, just follow this schema, open up conf.ini, and set navdirection to rtl):

  • {yourtheme}_first.png (pointing left)

  • {yourtheme}_prev.png (pointing left)

  • {yourtheme}_next.png (pointing right)

  • {yourtheme}_last.png (pointing right)

  1. Test out your theme. Run your colors through WebAIM’s Color Contrast Checker. See what it looks like when zoomed in or out really far. If you can, check what it looks like on different browsers and devices, or with automatic image-loading turned off. Ask friends for help if you need to. Try to validate your stylesheet; it doesn’t necessarily have to follow W3’s official specification, but there ought to be a good reason why it doesn’t.

  2. No, really, actually do #5. Your readers will thank you.

  3. Set site_style to the theme name you decided on in step 1 and run Springheel to regenerate your comic. Your comic site will now be themed with your own, custom theme!

One thing to keep in mind that you may have noticed already: each theme’s CSS is wrapped in an ID selector, and pages that use a given theme set the ID of html to that theme’s name. (So, a page that uses the “plain” style will have “<html lang="[whatever]" id="plain">”, and plain’s style.css only applies to elements within #plain.) If you don’t do the same, and your site uses multiple themes, it won’t display correctly at all and will look very weird.

Setting comic metadata

The comic images and their metadata will end up in input. Springheel decides a file is a comic page if it has 1. a matching metadata file and 2. one of the following extensions (case insensitive):

  • .png

  • .gif

  • .jpg or .jpeg

  • .svg

  • .webp (not recommended as many browsers do not support it yet, but use your own judgement)

The metadata file has the same name as the comic image, just with the extension .meta. If the comic has a transcript file (strongly encouraged), that will similarly have the extension .transcript.

(In JSON mode, the extensions are .meta.json and .transcript.json, respectively.)

Comic series as a whole (rather than individual strips) also have metadata files. The main one required is a configuration file that ends with .conf. You can optionally declare a .chars file that will generate a series character page. And if your comic is divided into chapters, you can also add a .chapters file that maps chapter numbers to chapter titles. We’ll discuss these more shortly.

The strip .meta file will have various key metadata about the comic (and the author’s commentary, if applicable), while the .transcript is, as the name suggests, a textual transcript of the comic’s action and dialogue. The .conf file contains important preferences about the series. The syntax for these files is fairly straightforward.

For this example, let’s use a specific Wuffle comic – look for Wuffle_2012-03-21-2012_0004_Aunty.jpg and its related files in the input directory.

Here’s what Wuffle_2012-03-21-2012_0004_Aunty.meta looks like:

---
  title: Wuffle and Aunty Pinky
  author: Piti Yindee
  email: <expunged>
  date: 2012-03-21
  tags: 4 panel series 1, Aunty Pinky, Wuffle
  conf: Wuffle.conf
  category: Wuffle
  page: 4
  height: 1429
  width: 1000
  language: en
  mode: default
  chapter: 1
  alt: This is a test of the extra text system.
---
Meet the new Wuffle's neighbor, Aunty Pinky aka the money hunger!

Here’s the transcript file, Wuffle_2012-03-21-2012_0004_Aunty.transcript:

(Wuffle paints a fence as Aunty Pinky looks on.)

Wuffle
  It's done, ma'am.

Pinky
  Thanks, sweetie.

(Pinky offers Wuffle a wad of money. He looks sheepish.)

Wuffle
  Oh, it's fine, ma'am. Please keep your money.

Pinky
  Oh, well. More for me.

(Pinky begins eating the money.)

And finally Wuffle.conf, the configuration file for the Wuffle series in general:

[ComicConfig]

category = Wuffle
author = Piti Yindee
email = <expunged>
header = WuffleHeader.jpg
banner = WuffleHeader.jpg
language = en
mode = default
status = complete
chapters = Wuffle.chapters
desc = Public domain funny animal comic
chars = Wuffle.chars
license = To the extent possible under law, Piti Yindee has waived all copyright and related or neighboring rights to Wuffle Comic.
license_uri = http://creativecommons.org/publicdomain/zero/1.0/

In .meta files, the metadata is sandwiched between the --- lines; below that is the author’s commentary. The strictly needed fields are:

  • title (the title of this specific strip or page)

  • author (you! or rather, whoever is supposed to get the credit for posting a page)

  • email (your email address – this is needed for RSS feed generation)

  • date (the strip’s publication date, in ISO 8601 (YYYY-MM-dd) format)

  • category (the comic/series title)

  • page (this strip’s page number)

  • language (ISO 639-1 code)

You can also add a chapter number if this strip is part of a chapter; alt_text for an extra line or two that will appear below the comic; and/or source (version 7+) if the comic is based on an existing work and you want to link to the original.

The .transcript has the character names, their dialogue indented by 2 spaces, and actions offset by parentheses. As long as it follows this scheme, it’ll be parsed by the HTML transcript generator.

The .conf file has fields that are required for accurate copyright statements, RSS feed generation, and general series organization:

  • category (the name of the series)

  • author (again: you!)

  • email (your email address)

  • header (a header image that will appear at the top of this series’ pages)

  • banner (a banner to identify this series; can be the same as the header or different)

  • language (ISO 639-1 code)

  • chapters (whether or not the comic is divided into chapters. If you set this to True or the name of a .chapters file, the archives page will automatically be separated by chapter)

  • desc (a description of the comic; used for the index page and RSS feeds)

  • status (whether the series is finished or not; accepted values are in-progress, complete, and hiatus)

  • chars (optional; the filename of a .chars file. If characters_page in conf.ini is set to True, this will generate a characters page based on the linked file.)

  • about (optional; if about pages are enabled in conf.ini, a string or HTML snippet that describes this comic.)

Automating the addition of new strips

(New in version 7)

You can use the springheel-addimg script to automatically generate metadata files for images in input.

You can provide information like title and page number when prompted, or you can do so as command line arguments:

-i INPUT, --input INPUT

The strip’s image filename.

-c CONF, --conf CONF

The category .conf file to use.

-t TITLE, --title TITLE

The strip’s title.

-n NUM, --num NUM

The strip’s page number.

-k CHAPTER, --chapter CHAPTER

The strip’s chapter number.

-a ALT, --alt ALT

Extra text for the strip.

-s SOURCE, --source SOURCE

The strip’s source URL.

-j, --json

Output metadata as a .meta.json file (for JSON mode).

--commentary COMMENTARY

Commentary on the strip.

For example:

$ springheel-addimg -i input/test.jpg -c input/Wuffle.conf -t "Test" -n 11 -k 1 -a "Test extra text" -j --commentary "Test commentary"

…might generate the following test.meta.json:

{
   "metadata": {
       "title": "Test",
       "author": "Piti Yindee",
       "email": "notreallyyindeesemail@notareal.tld",
       "date": "2021-03-23",
       "conf": "Wuffle.conf",
       "category": "Wuffle",
       "page": "11",
       "height": 1429,
       "width": 1000,
       "language": "en",
       "mode": "default",
       "commentary": ["Test commentary"],
       "chapter": "1",
       "alt": "Test extra text"
    }
}

Other notes:

  • addimg checks for date-like patterns in the filename, and if it can’t find any, defaults to the last-modified time reported by Python’s os.stat().

  • It can’t yet add tags or pieces (see below); you’ll have to edit those in manually.

Webtoon Mode

(New in version 7)

If you want to make long-strip comics in the style of South Korean “webtoons”, where comic pages are made of multiple image files, you can enable webtoon mode.

Create a .meta file for the first image. In both the category’s .conf file and the .meta file, set mode to webtoon.

Then add a pieces field to the metadata file that lists all the page image files in order, starting from the second one.

It will look something like this:

mode: webtoon
pieces: longstrip001_002.jpg, longstrip001_003.jpg

In JSON mode, pieces will be a list, just like tags:

"mode": "webtoon",
"pieces": ["longstrip001_002.jpg", "longstrip001_003.jpg"],

This is all that’s needed; Springheel will automatically copy and rename the images listed as pieces, and they’ll appear on both comic and chapter pages.

Chapter view will not display pages from webtoon chapters side-by-side, no matter how wide the screen is.

Character pages

Webcomics are notorious for having out-of-date character pages, so I made them as easy as possible for Springheel. Here’s all you have to do:

  1. Make a file to hold your character markup in input. I’d recommend calling it with the name of the series and the file extension .chars to make it easy to remember. Let’s use Wuffle.chars for this example.

  2. Add the category and language to the top of the characters file, followed by a line with “---”.

    category: Wuffle
    lang: en
    ---
    
  3. Add characters! The syntax is very simple. Mark character names with name: and a short description or blurb with desc:. You can optionally add a picture of the character with img: image_filename.ext. (If you don’t want an image, use img: None instead.) Add a line with just --- after each character to separate them.

  4. The default attributes – name and description, and optionally an image – will be fine for a basic characters page. But you can add any other, custom text attributes you want, and they’ll be displayed too! All you have to do is type the attribute label you want, followed by a colon, and then the value (one attribute per line). Let’s suppose I want to include a “species” field because the Wuffle characters are anthropomorphized animals. For Wuffle himself, I’d add Species: Wolf. Simple! All custom attributes are put into their own little subsection in the compiled page.

  5. Add a line to the comic’s configuration file (Wuffle.conf in this case) pointing to the character file:

    chars = Wuffle.chars
    
  6. Run Springheel as normal. You’re done! The character page will now be generated.

So this character file:

category: Wuffle
lang: en
---
name: Wuffle
desc: Wuffle is a wolf with a big heart. Currently he's living as a farmer in a barn that is on a hill near Gingerbread Village. He never turns away from people who need a helping hand. He is also willing to help them out without expecting anything in return. However, Wuffle tends to be naïve and too trusting, which often brings him unexpected trouble.
img: char-wuffle.jpg
Gender: Male
Species: Wolf
---
...

Would generate a character page like this:

<div class="char">
    <h2>Wuffle</h2>
    <img src="char-wuffle.jpg" alt="" />
    <dl>
        <dt>Gender</dt>
        <dd>Male</dd>
        <dt>Species</dt>
        <dd>Wolf</dd>
    </dl>
    <p>Wuffle is a wolf with a big heart. Currently he's living as a farmer in a barn that is on a hill near Gingerbread Village. He never turns away from people who need a helping hand. He is also willing to help them out without expecting anything in return. However, Wuffle tends to be naïve and too trusting, which often brings him unexpected trouble.</p>
</div>
...

Which looks like this in the Plain style:

Character example

A simple character profile for Wuffle.

Of course, if you don’t want a character page, simply set chars in your comic’s .conf file to “False”.

Chapter titles

If you want your work to be divided into chapters, you’ll need a .chapters file. As described above, add a chapters: Wuffle.chapters line to Wuffle.conf, then create a file called Wuffle.chapters. In theory, all you need to put in that file is a list of chapter numbers (one on each line), but you can also add titles to the chapters.

Suppose we want the first chapter to be called “4-Panel Series 1”. We’ll add the following line to Wuffle.chapters:

1 = 4-Panel Series 1

That’s it! That title will appear on the archive page, as well as in the headings for all pages that are marked as being part of chapter 1.

Note that series’ chapter settings are currently an either/or thing: you can’t have some pages that are part of a chapter and some that are not. If you have ones that don’t fit anywhere, I would recommend putting them all into a “miscellaneous” chapter, or even converting to a multi-series site and treating them as a separate (non-chaptered) series.

Extras

Springheel allows you to create a page to hold various extras. The main use case I was imagining was for guest art, wallpapers, textual side-stories, etc., but you can really put anything you want there.

To create an extras page, pop open conf.ini and set extras_page to True. Then put a JSON file called Extra.json in input. Here’s an example extras file for my sister’s comic, Brutus:

{
    "Fanart": [{
            "title": "Alucanth",
            "desc": "The very first Brutus fanart was a wonderful Alucanth by garrick!",
            "type": "image",
            "files": ["garrick_fanart_01.png"]
        },
        {
            "title": "Brutus MS Paint Poster",
            "desc": "Also by garrick: a big poster!",
            "type": "image",
            "files": ["garrick_fanart_02.png"]
        },
        {
            "title": "Just As Brutus'd",
            "desc": "Bardum contributes an amusing parody...",
            "type": "image",
            "files": ["bardum_fanart_01.png"]
        }
    ],
    "Comic": [{
        "title": "Brutus Comic Book Archive",
        "desc": "CBZ files for offline viewing. Read them with most any modern document viewer.",
        "type": "file",
        "files": [{
            "path": "Brutus_-_1-8.cbz",
            "link": "Brutus Chapters 1–8"
        }, {
            "path": "Brutus_Gaiden.cbz",
            "link": "Brutus Gaiden [incomplete]"
        }]
    }]
}

That will generate an extras page with Comic and Fanart as the second-order headings. file-type items will appear as textual links, and image-type ones will appear as image elements with figcaptions.

Springheel adds file size indicators to links for file-type downloads automatically:

<h2>Comic</h2>
<h3>Brutus Comic Book Archive</h3>
<p>CBZ files for offline viewing. Read them with most any modern document viewer.</p>
<ul>
    <li><a href="Brutus_-_1-8.cbz">Brutus Chapters 1–8 [2.2 MiB]</a></li>
    <li><a href="Brutus_Gaiden.cbz">Brutus Gaiden [incomplete] [132.7 KiB]</a></li>
</ul>

Licensing

You are by no means required to relinquish the copyright of a comic simply because you built the site for it with Springheel. The licensing of your work is entirely your decision.

That being said, I want to promote Free Cultural Works in general, so Springheel comes with some tools to make it easier to indicate the rights that readers have.

First off, there is a field, license, in conf.ini. By default it is “All rights reserved”. But if you want to release your comic into the public domain, as Piti Yindee did for Wuffle, you could do something like this:

license = To the extent possible under law, Piti Yindee has waived all copyright and related or neighboring rights to Wuffle Comic.

Note: if you are releasing your comic into the public domain, please make sure to edit country in conf.ini to list the country you are publishing from! This is very important because different countries have different laws about the ability of authors to waive copyright.

If you’d rather use a Creative Commons license, you could add the HTML snippet from their license chooser, as I do on my own site:

license = <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons License" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/80x15.png" /></a> These <span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/StillImage" rel="dct:type">works</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Garrick</span> are licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.

We add info on the license to the comic’s .conf file as well. For public domain works this will be the waiver from before, as well as a U.R.I. In Wuffle’s case this might be:

license = To the extent possible under law, Piti Yindee has waived all copyright and related or neighboring rights to Wuffle Comic.
license_uri = http://creativecommons.org/publicdomain/zero/1.0/

For a Creative Commons license, it will be the license’s name and U.R.L.:

license = Creative Commons Attribution-ShareAlike 4.0
license_uri = http://creativecommons.org/licenses/by-sa/4.0/

Now your comic will be nicely marked up with human- and machine-readable license info!

Zero-padding

(new in version 5)

By default, Springheel pads page numbers in URLs with zeros: “page_0001”. Notably (to avoid breaking existing links), this isn’t automatically updated if the total number of pages goes above 1000. If you’re planning ahead and think you’ll need more digits, or (conversely) if four digits is too much, just edit the zero_padding option in conf.ini. If you want to turn off zero-padding entirely, simply set it to False.

Linking multi-language sites

(new in version 5.2)

Let’s say you have a comic in both English and French, and you want to handle both with Springheel. You generate a site for the English comics and the French ones…but how will French-speakers who go to the English site know that the French one even exists? With multilang, you can put a link to each site’s other language variations.

Open up your conf.ini and uncomment the line beginning with multilang. It should then look like this:

multilang = xx=http://sample-springheel-comic.notarealtld/alanguage,xb=http://sample-springheel-comic.notarealtld/anotherlanguage

(If your conf.ini doesn’t have this option, no problem. Either update your configuration based on the one that comes with the latest Springheel version, or just add this line.)

Let’s say that we’re working on the English site’s conf.ini, and we want to add the French version, which is located at the URL https://fr.sample-springheel-comic.notarealtld. We’ll modify the line to:

multilang = fr=https://fr.sample-springheel-comic.notarealtld

And in the French site, we’ll add a link to the English one in the same way:

multilang = en=https://en.sample-springheel-comic.notarealtld

Visitors to the English site will then see a link labeled “français” in the footer, which goes to the French site – and the French site will have an “English” one which goes to, well, the English one. Simple!

As in the default value, we can add links to multiple languages as well. Just separate them with a comma (no spaces). For example, if we made a German site too:

multilang = en=https://en.sample-springheel-comic.notarealtld,de=https://de.sample-springheel-comic.notarealtld

Springheel pulls the appropriate language autonyms from the project’s strings.json. If your desired language isn’t in the default list, you can either add it to that file or, in the multilang string, simply use the language’s name instead of a two-letter code.

JSON Input

(new in version 7.0)

By default, Springheel expects metadata, transcript, and character files to use a YAML-like syntax. However, there is a setting in conf.ini called json_mode. If you set this value to True, instead of reading .meta and .transcript files, Springheel will look for .meta.json and .transcript.json files, and it will default to parsing character files as JSON as well. The output of JSON-based input files is exactly the same as with the regular format.

Here are some example files to show the syntax.

Example meta.json
{
    "metadata": {
        "title": "Wuffle and Aunty Pinky",
        "author": "Piti Yindee",
        "email": "notarealemail@notareal.tld",
        "date": "2012-03-21",
        "tags": ["4 panel series 1", "Aunty Pinky", "Wuffle"],
        "conf": "Wuffle.conf",
        "category": "Wuffle",
        "page": "4",
        "height": "1429",
        "width": "1000",
        "language": "en",
        "mode": "default",
        "chapter": "1",
        "commentary": ["Meet the new Wuffle’s neighbor, Aunty Pinky aka the money hunger!"]
    }
}

The main element is called “metadata”. Items that can have multiple elements, even if they do only have one in a given file (like the commentary in this case), are enclosed in brackets. (If there is more than one item in a list, they are separated by commas.) Everything that isn’t a list, including boolean values like “False”, should have quotation marks.

Example transcript.json
{
    "transcript": [{
        "line": "Wuffle paints a fence as Aunty Pinky looks on."
    },

    {
        "speaker": "Wuffle",
        "line": "It's done, ma'am."
    },

    {
        "speaker": "Pinky",
        "line": "Thanks, sweetie."
    },

    {
        "line": "Pinky offers Wuffle a wad of money. He looks sheepish."
    },

    {
        "speaker": "Wuffle",
        "line": "Oh, it's fine, ma'am. Please keep your money."
    },

    {
        "speaker": "Pinky",
        "line": "Oh, well. More for me."
    },

    {
        "line": "Pinky begins eating the money."
    }
    ]
}

The root element is “transcript”. Lines are dictionaries. Speakers are identified with “speaker”, and dialogue with “line”. If a line doesn’t have a speaker, it’s parsed as an action/description line. You don’t need to wrap it in parentheses (Springheel will do this automatically when building).

Example JSON character file
[
    {
        "name": "Wuffle",
        "img": "char-wuffle.jpg",
        "desc": "Wuffle is a wolf with a big heart. Currently he's living as a farmer in a barn that is on a hill near Gingerbread Village. He never turns away from people who need a helping hand. He is also willing to help them out without expecting anything in return. However, Wuffle tends to be naïve and too trusting, which often brings him unexpected trouble.",
        "Gender": "Male",
        "Species": "Wolf"
    },
    {
        "name": "Puipui",
        "desc": "A hedgehog who seems to be able to complain at anything he ever lays his eyes upon, though he never means any harm. Hot-headed and impatient, but surprisingly, Puipui is Wuffle's best friend and co-worker. It was Wuffle's idea that working on a farm might help Puipui with his anger management. Though honestly, he prefers eating and sleeping.",
        "img": "char-puipui.jpg",
        "Gender": "Male",
        "Species": "Hedgehog"
    }
]

This is not substantially different from the conventional format. Because the characters file is specified with chars in the comic’s configuration file, you can name it whatever you like, regardless of format. (However, it is recommended that you use the .json extension for JSON-formatted character files anyway, just to avoid confusion.) If JSON-mode Springheel is unable to load a character file as JSON, it will attempt to load it as YAML format instead; this will undoubtedly cause issues if the actual problem is invalid JSON, so be careful.

About Pages

(new in version 7.0)

The index page contains descriptions of each comic on the site, but you might want to include more detailed information—for example, to credit type foundries or crowdfunding patrons, or just to talk about the comic’s history or plot with more than one line. For that, you can set an About page, and it will appear in the site’s top navigation.

To enable about pages, open up conf.ini and set about = True. Then open the .conf file(s) for the comic(s) you want to describe. Define the about block like thus:

about = This is an example of the about page system.\nYou can add multiple lines of text.

Building produces about.html, which contains blocks for each comic on the site (including their banners and summaries from the index, so you don’t have to repeat the information from the latter). The example above would generate a block like this:

<h2>[comic title]</h2>
<img src="[comic banner]" alt="">
<p class="author">by [author]</p>
<p>[index summary]</p>
<p>This is an example of the about page system.</p>
<p>You can add multiple lines of text.</p>

You can also use some HTML, although it gets sanitized with html-sanitizer. Note that lines are only wrapped in paragraph tags if no HTML tags are present, so you’ll have to add them manually in this case.

about = <p>Helscome my wobsite. If you <span style="bold">want</span> to, you can use <a href="https://example.com">hyperlinks</a> and such.</p><script type="text/javascript" src="http://xn--ndu.xn--zckzah/some-malicious-script.js"></script>

Results in:

<h2>[comic title]</h2>
<img src="[comic banner]" alt="">
<p class="author">by [author]</p>
<p>[index summary]</p>
<p>Helscome my wobsite. If you <strong>want</strong> to, you can use <a href="https://example.com">hyperlinks</a> and such.</p>

The following tags are accepted:

  • a

  • h1

  • h2

  • h3

  • h4

  • h5

  • h6

  • strong

  • em

  • p

  • ul

  • ol

  • li

  • br

  • sub

  • sup

  • hr

  • i

  • b

  • ruby

  • rt

  • rb

  • date

  • dl

  • dt

  • dd

  • code

  • del

  • ins

Trying to build

Whew! That was quite a bit of text without actually getting to do much. For now, let’s just try building the site with the configurations and preferences already present in the Wuffle sample pack’s files. It should work out of the box, after all.

You run springheel-build in much the same way as springheel-init:

On GNU/Linux, it’s $ springheel-build

On Windows it’s <Your Python install path>\Scripts\springheel-build.exe

Now just sit back and wait for the site to compile.

Checking the output

If springheel-build didn’t return any errors, your site should appear in output/.

Let’s look at the same strip as before. Here’s a navigation block, the type that appears above and below the comic:

<ul class="cominavbox" id="topbox">
    <li><a href="wuffle_0001.html#topbox"><img src="arrows/plain_first.png" alt="First Page" /><br />First</a></li>
    <li><a href="wuffle_0003.html#topbox"><img src="arrows/plain_prev.png" alt="Previous Page" /><br />Previous</a></li>
    <li><a href="wuffle_0005.html#topbox"><img src="arrows/plain_next.png" alt="Next Page" /><br />Next</a></li>
    <li><a href="wuffle_0139.html#topbox"><img src="arrows/plain_last.png" alt="Last Page" /><br />Last</a></li>
</ul>

(This one goes above the strip; the one underneath would have id="botbox".)

You don’t have to calculate any of this yourself; it’s generated automatically!

Meanwhile, the .transcript will generate the following HTML:

<div role="region" id="transcript"><h2>Transcript</h2>
<p class="action">(Wuffle paints a fence as Aunty Pinky looks on.)</p>
<p class="line"><span class="charname">Wuffle</span>:
<span class="linedia">It's done, ma'am.</span></p>
<p class="line"><span class="charname">Pinky</span>:
<span class="linedia">Thanks, sweetie.</span></p>
<p class="action">(Pinky offers Wuffle a wad of money. He looks sheepish.)</p>
<p class="line"><span class="charname">Wuffle</span>:
<span class="linedia">Oh, it's fine, ma'am. Please keep your money.</span></p>
<p class="line"><span class="charname">Pinky</span>:
<span class="linedia">Oh, well. More for me.</span></p>
<p class="action">(Pinky begins eating the money.)</p>
</div>

Which will look something like this in the wild (again, with the Plain style):

Transcript example

Nicely formatted, easy-to-parse dialogue and action.

From here on

That should be that; you should have a usable site with all of Springheel’s basic features. At this stage, you can fiddle around with the settings, make your own themes or assets, and use the Wuffle files as a sort of template for what your own comic files should look like. When you have a site you’re satisfied with, you can upload it to your webserver with the FTP/SSH/etc. client that you like best.

Updating

Updating your Springheel site is simple. Just add the new strip(s) and metadata files to input, then run springheel-build again. Then you can re-upload your newly-updated site and marvel at your RSS feed.

NOTE: Springheel rebuilds all pages in output/ when you update – if you’ve made any changes to those files, they’ll be overwritten. Conversely (to reduce unnecessary disk rewrites), theme assets and stylesheets are not altered if they exist in output/. Delete output/assets and output/arrows if you do want to overwrite these files.