Creating a Dynamic Character Sheet Template (DST)

BE YE WARNED - This is an advanced feature and subject to change. It's much more stable now than it was at the start, but we're still tweaking things here and there. If you have thoughts or ideas, please let us know in the forum.

Assumed Technical Knowledge

It's assumed that you have an understanding of HTML and CSS. This guide is intended for people who have used HTML and CSS and know how to use them to make things look nice on the web. You don't have to be an expert, but positional CSS skill will be required to make your DST look good at all.

Assumed Design Knowledge

It's also assumed that you have an eye for design and can make things look good. I (Micah, head guy at Obsidian Portal) definitely have problems with this. If you're like me (more programmer, less designer), then making a DST might not be for you, since the vast majority of creating a DST is styling and CSS. Still, if there's an existing DST that could use some javascript to make it more automatic, that'd be a good place to pitch in.

Quick Start

For those too impatient to read everything...

The Goal

We want Obsidian Portal to support characters from each and every game system ever designed. A lofty (and challenging) goal, but with the help of the community, we think it's possible. Dynamic Sheet Templates (DSTs) are our first stab at this.

A DST is a set of files that lays out a nicely formatted interactive character sheet. This guide is designed to help experienced HTML/CSS designers create their own DST.

What it's not

These are not intended to be fully-featured ultimate auto-calculating online playable character sheets. Keep things simple, and focus on making the sheet look nice, as opposed to having a lot of bells and whistles. Specifically, DSTs should not attempt to enforce any system rules on the character. If someone wants to give their character 99999 strength, then let them. If they want to have a derived value that's completely incorrect, let them do that too. Basically, they should be able to edit whatever they want.

The Reward

If you create a DST and it gets accepted, you've done us a huge favor. We really appreciate how tedious and difficult it is to create something like this. To reward you, we're offering 6-months of Ascendant membership free to anyone who creates a DST and it gets accepted. What would prevent one from being accepted? If it's buggy, ugly, incomplete, breaches copyright somehow, or is a ripoff of an existing DST.

DST Overview

A DST allows for marking up the underlying structured metadata for an RPG character. At least in the beginning, we will be reducing every character down to a set of key-value pairs. For example, here's a highly simplified D&D character expressed as a set of key-value pairs:

  "name" : "Tordek",
  "race" : "Dwarf",
  "class" : "Fighter",
  "level" : 12

A DST simply takes a set such as this and makes it look nice, and possibly auto calculates some of the values. We're not trying to make the ultimate character builder (like Herolab, PCGen, or otherwise). Instead, we just want to make it easier to create pretty character sheets that are viewable on the Web.

HTML template

The first piece of any DST is the HTML template. This is simply an HTML file that lays out the entire character sheet. The only special thing to note here is that certain elements will need special classes. That's how our system recognizes a DST, by HTML classes. Here's an example HTML template for Tordek, from above:

<div class="basic_info">
    <span class="dsf dsf_name"></span>
    <span class="dsf dsf_race"></span>
    <span class="dsf dsf_class"></span>
    <span class="dsf dsf_level"></span>

The obvious class to look for is dsf which stands for dynamic sheet field. The system will find all the span elements with the dsf class and automatically fill them with the correct value for that field. How does it know what value to fill with? That's where the dsf_ class comes in. This class is dsf_FIELDNAME. When the sheet loads, we will insert all the correct values using javascript. Here's what Tordek's sheet would look like after fully loading:

<div class="basic_info">
    <span class="dsf dsf_name">Tordek</span>
    <span class="dsf dsf_race">Dwarf</span>
    <span class="dsf dsf_class">Fighter</span>
    <span class="dsf dsf_level">12</span>

The fields

Our backend can handle pretty much any set of fields. If one game system has level and another has rank, that's fine. Just define the fields you need when making your HTML template, by creating spans with the correct dsf class. There's no need to pre-define or enumerate them anywhere. Any span with the class of dsf will be assumed to be a field, and the field name will be extracted from the *dsf* class on that same element.

Use existing field names!!! If there's a DST for your game system already, USE IT! This ensures maximum compatibility between DSTs, and will allow users to switch back and forth to find one they like. Otherwise, if an existing DST has level and you create one with lvl, then they're incompatible. Anyone that switches from one to the other will lose (or at least won't be able to see) the value for that field.

Naming Conventions

To ensure maximum compatibility between DSTs, follow these conventions when naming fields. You may hate or disagree, but the universe will end when programmers finally agree on styling rules.

  • ASCII alphanumeric (and underscore) only. We don't want to deal with encoding schemes right now.
  • Use **full words**, when possible.
  • Use **established abbreviations** (ie. str, dex, thac0). If you're not sure, use the full word
  • Connect words with underscores, not camelCase or anything else: armor_class, not armorClass or ArmorClass
  • All lowercase.

Required Fields

There are some fields that will be common to all characters (name, player name, campaign, etc.). These will be handled separately from the DST fields as far as editing and saving are concerned. However, they will behave normally for display and positioning. Note! These fields are required! Your DST must have a place to display each of these fields.

Required Fields

Field Field Name Class Notes
Character Name dsf_name A link to the character (ie. link to the current page). It will have an additional class of *dst_character_name_link* that can be used for styling.
Player Name dsf_player A link to the player's profile page. Can be empty, like for an NPC. It will have an additional class of *dst_player_link* that can be used for styling.
Campaign Name dsf_campaign A link to the campaign. A link to the character's campaign. It will have an additional class of *dst_campaign_link* that can be used for styling.
DST Author dsf_dst_author A link to the profile page for the DST author (you!). It will have an additional class of *dst_dst_author_link* that can be used for styling.
Character Bio dsf_bio This is HTML and can be very long. Make sure to fit it into your DST in such a way that it can grow to any length.


Since checkboxes (or similar) are a very common feature for character sheets, we have added support for easily adding checkboxes to a DST. Simply add the checkbox class to a dsf span and it will automatically get converted. Here's an example:

<span class="dsf dsf_trained checkbox"></span>

The checkbox field will have a value of "1" if checked, or a value of "0" if not. It also works as normal with the dataChange javascript callback.

HTML ids are not allowed!

Do not insert any HTML ids into your template! There may be multiple character sheets displayed at one time, and if the DST template contains ids, then it would be invalid HTML due to id duplication. So, only classes are allowed. NO IDs!!

Readonly fields

If, for some reason, you need to prevent certain fields from being edited (like, for example, they're auto-calculated by javascript), you can add a class of "readonly" to the field. This will prevent it from being editable.

However!! In most cases we recommend letting the user override any auto-calculated value. The DSTs are not intended to enforce any particular rules for a system. Let the users put in whatever value they want. It's their character, after all.

The Styling

Once your HTML template is created, you've got all the markup, but it probably doesn't look very good. The obvious solution here is to style it up with CSS.

Each DST needs a CSS file styling up the markup. You're welcome to make your own classes as necessary to help with styling the HTML.


All your CSS must be namespaced! This means prefixing your CSS rules so that they only affect your particular DST and not the site's layout as a whole. This is actually quite easy to do, as each sheet will be contained inside a div with a class of ds_SLUG where SLUG is the slug for your DST. For example, sheets using the minimal4e DST will always be contained in a div with class dst_minimal4e.

To create CSS rules for the minimal4e DST, I would do like so:

.minimal4e table {
  /* This applies to all tables in my DST */

.minimal4e a {
 /* This applies to all links in my DST */

If you need to define your own classes to use in your DST, that's fine. However, in order to prevent issues with the overall site's CSS, it is strongly recommended that you namespace your classes as well. For example:

<span class='my_class'>Some value here</span>

should be...

<span class='minimal4e_my_class'>Some value here</span>

Namespacing of your HTML classes is not required, but be warned that we change our CSS regularly, and it's a good bet that eventually your DST will break due to these changes.


In addition, you may want to have images for use as backgrounds, corners, textures, or otherwise. For now, simply reference the images externally (on another server). We will figure out a way to pull them to our main server and serve them from there, but that process hasn't been solidified yet.


Javascript is NOT required!! - If you just want a pretty sheet and don't want a bunch of fancy javascript in it, that's fine. An HTML/CSS layout for a specific system is still 1000 times better than the current generic layout.

If you want to add javascript support, read the comments in characters.js and look at the example javascript in the devkit. That should get you started.


We use jQuery extensively, and it is available for use in your DST's javascript, so feel free.

No external javascript!

Including external javascript files from other servers would be a huge security risk. Therefore, all your javascript must be pasted into the javascript textarea.

Keep a local copy!

It is strongly recommended that you keep a local copy of your HTML template, CSS, and Javascript. Our server database is backed up regularly, but there is always a chance that your DST code will get lost or corrupted on the server. Having a local copy means you can simply copy & paste the code back in.

Backups are your friend.

Developer's Kit

The developer's kit is part of the DST repository on github. If you're not familiar with git, then just click on the Download Sources button in the top right. This will allow you to download the files without messing with git.

The developer's kit is a set of files that replicates how the DST will work in real life. Play with this on your own machine and get your DST working with it. We highly recommend using Firefox/Firebug

Editing the sheet

Editing the values for the sheet is done via javascript. When an authorized editor (ie. the GM or a player) goes into edit mode, the values become clickable. On click, they are replaced with an input field. The editor types in the new value, hits enter (or the Ok button) and it updates the value. When they're happy, they click save and the whole sheet is saved.

You don't need to worry about edit mode, except to make sure that your CSS leaves enough room for editing things.


By submitting a DST, you are agreeing to let Obsidian Portal members use it. We give full attribution of authorship to you, the author, but by submitting a DST, you are giving us a royalty free license to copy, modify, and distribute it. Essentially, all submitted DSTs are assumed to be under an open source license. If you wish, you can include an explicit license statement. I highly suggest using the MIT license. Any license not recognized by the OSI as being open source will not be accepted.

Copyright (c) [year] [copyright holders]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.



As this is still in beta, I'm sure there are issues. Let's try to enumerate here...

  • Array values? How do we represent something like feats, where there is an unbounded list?
  • Textareas? Is there a way to mark a field as a textarea instead of a simple text input?
  • Can we make things look good on iPhone/Mobile/iPad? I'd like to pay more attention to that going forward.