cards.py
Operations Manual
This document provides an entry point for using cards.py to build printable cards for your games.
It assumes that you already have cards.py installed and ready for use.
If you don't, please look here for installation instructions.
Introduction
With cards.py you get a small, focused, card-making machine using a specialized templating engine that allows you to iterate on your data without worry and use your web skills to create nice-looking cards for your game.
See those cards on the right? That's what you can get it to do.
That's the introduction; now let's make some cards!
To start building your own cards, you only need two things:
- A cards datasource
- A card template
Project Structure
First of all, however, cards.py works off your local files, so you should settle on an organizational structure for your game files.
You can have your project structured any way you want, but here's a suggestion:
Tip: take a look at the source for the game Dungeon Deck to see an example of project structure
my-game/
resources/
data/
cards.csv
templates/
template-fragments/
footer.html
card.html
definitions.csv
With that out of the way; now let's make some cards!
Cards
Datasource
Your cards datasource must be a CSV file, and should look something like this:
Tip: take a look at the included example for a full datasource
| rank | text |
|---|---|
| 1st | My first prototype card! |
Note that the table above is just a visually pleasing representation of data that actually looks like this:
Tip: you can export a Google Sheets document as a CSV file
cards.csv
rank,text
1st,My first prototype card!
At this point you can actually already make your cards, but they won't look great without your personal touch!
To add that personal touch, you use templates.
Templates
Layout
To define the layout and look of your cards, you use a template file.
A template file is just a plain-text file that uses HTML/CSS to create a visual layout, and can contain any number of template fields that becomes populated by content from your datasource.
1st
My first prototype card!To start using templates for your cards, you just extend your datasource with a new column:
Tip: the order of columns does not matter; you can have any order you prefer!
| @template | text | rank |
|---|---|---|
| templates/card.html | My first prototype card! | 1st |
This tells cards.py that the card on that row should be rendered using that specific template.
As an example, using this datasource with the template below, you get the card shown to the right.
templates/card.html
<div style="text-align: center; font-family: Garamond;">
<h1>{{ rank }}</h1>
<div>{{ text }}</div>
</div>
It's as simple as that!
Images
Of course, you'd often want more complicated designs. Luckily, that's not a problem.
Keep in mind that templates are really just tiny little webpages, so any valid HTML goes. That gives you a ton of options, and if you ever get stuck, help from the entire Internet is just a search away.
1st
Let's try adding an image, and place it slightly below the text:
Tip: use the Developer Tools from your favorite browser to tweak and edit your templates until they look just right!
templates/card.html
<div style="text-align: center; font-family: Garamond;">
<h1>{{ rank }}</h1>
<div style="margin-bottom: 10mm;">{{ text }}</div>
{{ resources/cards-icon.svg:100x100 }}
</div>
Images are important and useful components to any great looking cards. Just by adding that one image, suddenly our card became much more interesting.
Icons
Many card games also use images as icons inline with the card text. This is a clever way to reduce larger amounts of text and make cards more succinct. Let's try adding an inline icon to our card text.
1st
Since we're only going to be editing the text, we can keep using the same template and only update the datasource:
Tip: use SVG for icons so you can scale to any size; alternatively, use unicode symbols instead of images
| @template | text | rank |
|---|---|---|
| templates/card.html | My first {{ resources/cards-icon.svg:16x16 }} prototype card! | 1st |
Pretty easy, right?
Though, sometimes you might have several cards that need to use the same icon, or maybe the icon just appears more than once in the text, and having to put down the entire image reference again and again starts to seem unnecessary. That's because it is!
Definitions
There's a feature called definitions, which acts like a shared datasource. In this datasource, you can store commonly used content; for example, icons that you use in more than one place.
So, let's say that our definitions.csv file looks like this:
| @definition | @value |
|---|---|
| cards_icon | {{ resources/cards-icon.svg:16x16 }} |
That would allow us to update our datasource to just reference the icon definition and still get the same result:
| @template | text | rank |
|---|---|---|
| templates/card.html | My first {{ cards_icon }} prototype card! | 1st |
Looks better, doesn't it?
This also has the added benefit that, should you ever want to use a different image, you only have to change the image path in one place.
Taking it even further, you could create definitions for different icon sizes so icon sizing becomes consistent across your cards:
| @definition | @value |
|---|---|
| small | 16x16 |
| large | 100x100 |
| cards_icon | {{ resources/cards-icon.svg:small }} |
Definitions even work inside templates:
templates/card.html
<div style="text-align: center; font-family: Garamond;">
<h1>{{ rank }}</h1>
<div style="margin-bottom: 10mm;">{{ text }}</div>
{{ resources/cards-icon.svg:large }}
</div>
Conclusion
By now, I hope you have a better understanding of what cards.py can do for you and your card game.
There's plenty more useful features available, but what you've read so far is the gist of it. If you're looking for more information, following is a detailed overview of the various features and how you can use them.
Columns
This section covers the three special columns you can extend your datasource with to get the most out of cards.py.
1) Count
Use the @count column to specify how many copies of a card should be generated.
Defaults to 1 copy of each card if the column is left out.
Tip: you can set a count of 0 to skip the card
| @count | text |
|---|---|
| 1 | Make 1 copy of this card |
| 2 | Make 2 copies of this card |
2) Template
Use the @template column to specify a path to the template file that should be used when generating the front of a card.
Note that the path is relative to the path of the datasource. You can also specify an absolute path.
| @template | text |
|---|---|
| templates/card.html | A templated card |
Additionally, this column can be used to specify the size of the card. If a size is specified, that size will override the default card size (but only for this datasource).
| @template:domino | text |
|---|---|
| templates/card.html | A templated domino-sized card |
Available sizes (ordered by smaller to larger):
| Size Name | Size |
|---|---|
| token | 0.75x0.75 inches |
| domino | 1.75x3.5 inches |
| standard | 2.5x3.5 inches (default) |
| standard-landscape | 3.5x2.5 inches |
| jumbo | 3.5x5.5 inches |
3) Template-back
Use the @template-back column to specify a path to the template file that should be used when generating the back of a card.
This column works exactly like the @template column, except that it
cannot be sized; a card back is always the same size as its front.
| @template | @template-back | text |
|---|---|---|
| templates/card.html | templates/card-back.html | A card with a custom back |
A back template does not have access to any columns except those suffixed by the @back-only descriptor.
Similarly, a front template does not have access to @back-only columns.
| @template | @template-back | text | back-text@back-only |
|---|---|---|---|
| templates/card.html | templates/card-back.html | A card with a custom back | This goes on the backside! |
Template Fields
This section covers all the template fields you can use in your templates or data to reference content.
Column Field
Column fields can reference content from any column in the datasource
A column field typically looks like this: {{ my_column }}, and can be resolved in both templates and data.
A column field can even reference the content of a column in a different row. For example, if you wanted to reference the content of my_column, but from the card at row number seven, you just add the row number at the end. Like this:
{{ my_column #7 }}
Image Field
Image fields transform image paths into images
todo: {{ image.png }} and @copy-onlyInclude Field
Include fields allow you to embed re-usable content (template fragments) into any template
An include field takes a path to a file, and puts the contents of that file into place of the field.
It looks like this: {{ include 'template-fragment.html' }}, and it can be used in any template. It will be resolved automatically, and follows the same rules as any other template.
Note that paths should be relative to the template that the fragment is embedded within.
Typical example
Your project has many different templates, but each of those templates has the same copyright notice at the bottom.
Sometimes you may want to slightly tweak how it appears, or change the text. This quickly becomes annoying, because you have to go through each and every template with this notice at the bottom.
You could avoid this annoyance by pulling it out into a template fragment.
Consider this template:
templates/card.html
<div style="text-align: center; font-family: Garamond;">
<h1>{{ rank }}</h1>
<div style="margin-bottom: 10mm;">{{ text }}</div>
<div style="position: absolute; bottom: 1.25mm; right: 2mm; text-align: right; font-size: 7pt;">
Copyright 2016, Great Games Incorporated {{ icon_set }} {{ _card_index }}
</div>
</div>
Here, the bit with the copyright could easily become a template fragment, so that content is only editable in one place.
templates/template-fragments/copyright.html
<div style="position: absolute; bottom: 1.25mm; right: 2mm; text-align: right; font-size: 7pt;">
Copyright 2016, Great Games Incorporated {{ icon_set }} {{ _card_index }}
</div>
With this fragment, it can be embedded like so:
templates/card.html
<div style="text-align: center; font-family: Garamond;">
<h1>{{ rank }}</h1>
<div style="margin-bottom: 10mm;">{{ text }}</div>
{{ include 'template-fragments/copyright.html' }}
</div>
Definition Field
Definitions
This section covers the concept of definitions.
A definition is content that is commonly used in your project, and may even be used across several datasources.
FAQ
A collection of frequently asked questions.
Feel free to contact me if you can't find your question answered here.
Why shouldn't I just use nanDECK?
You should! It has a visual interface and has helped a lot of people get their games ready. This program is simply an alternative.