Using Storyform with a custom CMS

This guide will help you setup Storyform on your blog or site and begin using its features. It requires that you know a bit of HTML and have access to modify your blog's markup. If you are using WordPress, we recommend using our plugin. See Using Storyform with WordPress.

Setting up Storyform

Setting up Storyform on your blog or CMS is pretty simple. You just need to utilize the following HTML code for each post, replacing the appKey with the appKey found in your dashboard.

<!DOCTYPE html>


<link href="" rel="stylesheet" />
var _template = {
    version: 'v0.6',
    group: 'Puget',
/*-- START RENDER SCRIPT --*/!function(a){function b(a,b){var c=new XMLHttpRequest;c.onreadystatechange=function(){4===c.readyState&&(c.status>=200&&c.status<300?b(null,c):b(c),c.onreadystatechange=function(){})},"GET",a.uri,!0),c.send()}document.documentElement.className+=" js";var c=void"//",d=_template.version||"v0.6",e=_template.generator?"&generator="+_template.generator:"",f=c+"/"+d+"/render/""?appKey="+encodeURIComponent(_template.appKey)+"&uri="+encodeURIComponent(document.location.href)+"&lastModified="+encodeURIComponent(document.lastModified)+"&title="+document.title.substr(0,200)+"&width="+window.innerWidth+"&height="+window.innerHeight+"&deviceWidth="+window.screen.width+"&deviceHeight="+window.screen.height+e;a.App=a.App||{},a.App.Data=a.App.Data||{},a.App.Data.render={callback:function(){},data:null,uri:f},b({uri:f},function(b,c){if(c){var;a.App.Data.render.callback(null,d),a.App.Data.render.callback=function(){}}else a.App.Data.render.error=b,a.App.Data.render.callback(b),a.App.Data.render.callback=function(){}})}(this);/*-- END RENDER SCRIPT --*/
<script src=""></script>
<!-- END PASTE-->

<article data-content>
    <h1>This is the title of the article</h1>
    <post-publisher data-publisher>Article Author</post-publisher>
    <time data-published datetime="March 18, 2014">March 18, 2014</time>

    ...content of the article goes here...


<header class="navbar navbar-minimized navbar-left horizontal-links" role="navigation" data-win-control="UI.NavBar">
    <div class="navbar-toggle">
        <div class="navbar-lines-button">
          <span class="navbar-lines"></span>
    <div class="navbar-content">
        <a class="navbar-logo" href="/" rel="home">
            <h2 class="navbar-site-title">This is my site title</h2>
            <img src="/logo.png" alt="logo" />
        <div class="navbar-title">
            <h6><a href="#">Title of the article</a></h6>
        <div class="navbar-controls">
            <a class="navbar-icon" data-win-control="UI.FacebookShare" href="#"></a>
            <a class="navbar-icon" data-win-control="UI.TwitterShare" href="#"></a>
            <a class="navbar-icon" data-win-control="UI.GooglePlusShare" href="#"></a>
            <a class="navbar-icon" data-win-control="UI.FullScreenButton" href="#"></a>
        <nav class="navbar-nav navbar-links">
            <ul id="menu-all-pages" class="menu">
                <li><a href="/pageA">Page A</a></li>
                <li><a href="/pageB">Page B</a></li>
<div class="navbar-overlay"></div>

<div class="primary-content">
    <div class="magazine" data-win-control="Controls.FlipView">
        <div data-win-control="UI.ProgressBar"></div>
        <div data-win-control="UI.PageNumbers"></div>

NOTE: Like with the WordPress plugin, you may want to selectively choose which posts you wish to apply Storyform.


Versioning enables you to ensure that Storyform works with your markup even as the platform evolves. The latest version as of this writing is 'v0.6'. As new versions become available, you may adjust the _template variable.

var _template = {
    version: 'v0.6',

Choosing your template

Alter the _template variable to choose the specific templates you want. Enter the template id not the template name. To determine what templates are available for you to use, visit, where APP_KEY is your application key.

var _template = {
    group: 'Puget'

Like with WordPress you may want a different template group per article. That's up to you to specify per page the group to use.

Specifying your app key

Specify an appKey on the _template variable, by copy and pasting the appKey from your dashboard.

var _template = {
    appKey: 'INSERT_IT_HERE'

Pointing to your content

In order for the Storyform code to accurately pick up the content of the article, specific data- attributes must be added to HTML elements. An article with a cover page must include a title, publisher and published date. The data-content attribute is used to mark the containing article content. The data-publisher and data-published are used to mark their corresponding resources.

<article data-content>
    <h1>This is the title of the article</h1>
    <post-publisher data-publisher>Article Author</post-publisher>
    <time data-published datetime="March 18, 2014">March 18, 2014</time>

Adding a Navigation bar

Storyform optionally supports a customizable navigation bar. You can create your own if you like, but to use ours just include the above snippet of HTML before the magazine viewer.

There are a few options that you can use to alter the layout of the navigation bar. This is done by adding the following classes to the NavBar element.

navbar-minimized - Lays out the navbar as a small hamburger menu overlay in the corner of the screen.
navbar-full - Lays out the navbar to the full width of the page.

Applys to navbar-minimized only.
navbar-left - Places the overlay on the left side of the screen.
navbar-right - Places the overlay on the right side of the screen.

vertical-links - Places your site links in a vertical sidebar that gets revealed on tap of the hamburger button.
horizontal-links - Places your site links horizontally inline with the rest of the bar.

Note: Be sure to include the <div class="primary-content"> container for the magazine in order to shift the magazine appropriately when using vertical links.

To customize the bar we recommend using a modification of the following styling:

.navbar-title a, 
.navbar-links a {
    color: #FFF;

.navbar-title {
    border-left: 1px solid rgba(255, 255, 255, 0.5);

    color: #FFF;
    border-left: 1px solid rgba(255,255,255,0.1);

.navbar-minimized.vertical-links .navbar-controls {
    border-top: 1px solid rgba(255,255,255,0.1);

.fullscreen-icon:visited {
    color: #FFF;    

.fullscreen-icon:hover {
    color: #FFF;    
    background-color: rgba(255,255,255,0.3);

.navbar-controls {
    background-color: #242424;

.navbar-lines, .navbar-lines:before, .navbar-lines:after {
    background: #FFF;

.navbar-full {
    border-bottom: 1px solid #FFF;

.navbar-minimized .navbar-toggle {
    background-color: #242424;

.navbar-full .navbar-toggle {
    background-color: rgba(255,255,255,0.05);
.navbar-full .navbar-toggle:hover {
    background-color: rgba(255,255,255,0.3);

.navbar-content {
    background-color: #242424;

.vertical-links .navbar-nav {
    top: 51px;

.navbar-full.vertical-links .navbar-nav {
    background-color: #242424;

.navbar-minimized.vertical-links .navbar-content {
    background-color: #242424;


Adding the magazine container

Now, don't forget to include the actual magazine container. Typically this will be expanded to fill the window, but it can be placed in some smaller space, such as to accomodate your navigation bar.

Note: The <div class="primary-content"> is only necessary when doing vertical links in your navbar. Otherwise you can just include magazine div.

Optionally, you may also include the ProgressBar and PageNumber controls by placing them within the magazine element.

<div class="primary-content">
    <div class="magazine" data-win-control="Controls.FlipView">
        <div data-win-control="UI.ProgressBar"></div>
        <div data-win-control="UI.PageNumbers"></div>

Migrating to Version 0.6

If you already have a custom CMS solution using version 0.5, follow these steps to upgrade to version 0.6.

  1. Modify the JavaScript _template.version variable to 0.6
  2. Remove the data-layout-type="..." attribute from the root article element.
  3. Change all data-decorational="article" media elements to data-decorational="section" and ensure media is distributed throughout the article.
  4. Replace <map> elements with data-area-crop and data-text-overlay attributes on the media itself.
  5. Move page breaks to <section> elements.

Authoring an article

This guide will help you get the most out of your article by utilizing the various authoring features of Storyform from inserting images, video, pullquotes, subtitles, etc.

Adding a subtitle

To display a subtitle, add the (<h2>) tag immediately after the published time in the HTML.

<article data-content>
    <h1>This is the title of the article</h1>
    <post-publisher data-publisher>Article Author</post-publisher>
    <time data-published datetime="March 18, 2014">March 18, 2014</time>
    <h2>This is the subtitle of the article</h2>

Inserting Images

Images are automatically matched to appropriate layouts. In order to get rich fullscreen or partial full-bleed image layouts, Storyform requires images to be at least 80% as wide or tall as a user's screen. We therefore recommend images at least 1600px wide or 960px tall. It's important that the image size is present in the HTML so that matching can occur before downloading the image. Be sure that all images include the width and height attributes.

<img src="kayak3.jpg" width="630" height="960" data-sources="kayak3_cropped.jpg 1x 630w 600h"/>

Responsive Images

(similar to srcset and picture element)

Multiple image sizes (used for things like faster download times on mobile devices) and art direction based croppings may be specified for each image. This enables Storyform to choose the most appropriate image for the device and context.

Storyform currently supports two different formats for responsive images, first using the standard img tag and second using the newer picture and source elements.

Img element

Each additional image candidate may be specified on the data-sources attribute of the img. The format is a comma separated list of <url> <pixelDensity>x <image-width>w <image-height>h.

<img src="kayak3.jpg" width="630" height="800" data-sources="kayak_mobile.jpg 1x 900w 602h, kayak_cropped.jpg 1x 1800w 12024" />

Picture element

Alternatively, you may use the new picture element to specify multiple photo candidates. Each candidate should be specified on the data-sources attribute on a source element. The value should follow the format <url> <pixelDensity>x <image-width>w <image-height>h and a fallback image should be specified for users who have turned off JavaScipt in their browser.

    <source data-sources="kayak3.jpg 1x 630w 800h" />
    <source data-sources="kayak_mobile.jpg 1x 900w 602h" />
        <img src="fallback.jpg" />

NOTE: The srcset attribute is not used here as the height and width specification is actually used to describe the image, not the viewport for which it should be used. This is because the image may be placed in completely different layouts at runtime and not displayed at the same size for each. The content should not describe the layout, but describe itself.

Pinning / Unpinning Media

Pinning media allows you to force an img, picture, video, or iframe to display exactly where it is in the text flow. Therefore a “pinned” piece of media won’t allow for any later content to be displayed until after it has itself been rendered. Unpinning an image essentially allows the image to be rendered later in the article than its current position. This enables the image to be larger and more full-bleed more often, by allowing it to not be squeezed onto a page, but be placed on the next page without leaving whitespace on the first page. You can still control the pacing of the media in the story because media is only rendered after their content position.

Depending upon which layout you use, your media will either be pinned or unpinned (section) by default. In order to manually pin / unpin an image, you’ll need to add the data-decorational tag to your media elements.

// Pins media to a specific position in the article
<img data-decorational="pinned" src="/image.jpg" alt="description" />

// Unpins media and allows it to be rendered later in the article
<img data-decorational="section" src="/image.jpg" alt="description" />


Adding a caption to an image is a great way to describe the photo to the reader.

Storyform uses the standard HTML5 figure element and figcaption element.

    <img src="kayak3.jpg" width="630" height="800" data-sources="kayak3_cropped.jpg 1x 630w 600h"/>
    <figcaption>A beautiful kayak ride down the bay.</figcaption>

Smart cropping

Storyform takes advantage of the entire browser window real estate to maximize impact and maintain a full bleed experience. In order to handle the infinite number of device and window sizes and orientations, from small smartphones to large desktop monitors, Storyform will, by default, crop your images at most 10% on each side. In order to achieve even more flexibility and control, authors can specify the subject of a photo, so as to identify the area of the photo to not crop out. Storyform will first optimize for displaying an image as large as possible and then optimize to display as much of the image as possible, without cropping the subject of the photo out. This is useful if the subject is in the corner of the image to crop from the other sides instead of center cropping or when trying to maintain a full bleed or full screen experience across different screen sizes or orientation. It is recommended to make the subject as small as possible in order to give as much flexibility to the system as possible.

Specifying the subject or crop zone is done via a data-area-crop attribute. In order to support both responsive images and smart cropping, the picture element is required.

    <source data-sources="kayak3.jpg 1x 630w 800h" data-area-crop="rect 0 0 180 400" />
    <source data-sources="kayak_mobile.jpg 1x 900w 602h" data-area-crop="rect 0 0 280 420" />
        <img src="fallback.jpg" />

The standard img tag is also supported, but the data-sources attribute cannot specify a different usemap per candidate.

<img src="kayak3.jpg" data-area-crop="rect 0 0 180 400" />

Text Overlays

Storyform supports the ability for captions to lie on top of an image without any opaque panel, gradient or text shadow. However, the provider of the image must specify where on the image the text may overlay. This can be done with a data-text-overlay attribute. Each area can specify whether the area is dark in color or light in color, telling Storyform to use light or dark text.

Overlay text on an image

In order to support both responsive images and overlaid text, the picture element is required.

    <source data-sources="kayak3.jpg 1x 630w 800h" data-text-overlay="rect 0 0 180 400 dark-theme, rect 160 400 300 800 light-theme" />
    <source data-sources="kayak_mobile.jpg 1x 900w 602h" data-text-overlay="rect 0 0 280 420 dark-theme, rect 160 400  300 600 light-theme" />
        <img src="fallback.jpg" />

The standard img tag is also supported.

<img src="kayak3.jpg" data-text-overlay="rect 0 0 280 420 dark-theme" />

Inserting Video

Storyform supports Youtube, Vimeo, and HTML5 video, which can all be used as both a background and as a major element within your story. To use insert Youtube and Vimeo video, enter a custom element for the youtube or vimeo video. simply paste the the iframe code into your page source.

  1. Use the videoid attribute to specify
  2. Optionally include an autopause attribute to avoid autoplaying the video when the user flips to the page.
  3. Optionally include a controls attribute or nocontrols attribute to force play/pause and other video controls to appear (defaults to being based on the particular layout).
<youtube-video videoid="4533e2e02-1" width="1024" height="576"></youtube-video>
<vimeo-video videoid="4533e2e02-1" width="1024" height="576"></vimeo-video>

Note: Traditional iframe embeds are also supported, but not recommended as the custom element solution allows the loading of the video to be delayed until the user is actually within a few pages of the video, thus speeding up the load of the page.

If you'd like to use HTML5 video you'll need to provide all of the required HTML5 elements and follow the instructions below.

  1. First, convert your original video into both a mp4 and a webm format. For an easy video encoder, download the VLC player.
  2. Use the video element, being sure to include the width, height and poster attributes.
  3. Optionally include the loop attribute to loop the video.
  4. Optionally include an autopause attribute to avoid autoplaying the video when the user flips to the page.
  5. Optionally include a controls attribute or nocontrols attribute to force play/pause and other video controls to appear (defaults to being based on the particular layout).
<video poster="cover-image.jpg" width="1024" height="768" loop>
    <source src="video.webm" type="video/webm">
    <source src="video.mp4" type="video/mp4">

Note: To use video as the background to your title page, place it at the beginning of your content.


Pullquotes are a great way to reiterate a point and draw attention to some particular point in your article as they scan the article. Unlike blockquotes, pullquotes are repeated pieces of content drawn out of the normal flow of the article.

Pullquotes can be specified on spans of text by adding a pullquote class.

    This is a paragraph describing something amazing. <span class="pullquote">This is a pullquote that will be repeated in some templates in a more emphasized way.</span>

Page Breaks

Page breaks allow you to force later content onto its own page, giving you a lot more control over the flow of the article. Page breaks should be applied to <section> elements with the data-break-before tag.

<section data-break-before="page">
    Content here...