top of page
Search

Building a Digital Character Sheet

Writer: The Archivist
The Archivist
Jun 18
13 min read

(No blog post next week, seeing as how it's the 13th week.)


Statblocks

When I first downloaded Obsidian and began using the ITS Theme, I avoided one of the primary features that makes it a powerhouse for TTRPGs: the statblocks callout.



First, many of its elements centered around D&D mechanics, which Daggerheart renders irrelevant, such as the Initiative and Death Saves.

Second, the code block intimidated me:


> [!statblocks]
> ![Char Image|cover right circle htiny wtiny lp]()
> 
> # Name
> > Description
> *Basics*
> *Basics*
> 
> ---
| HP | AC | Initiative |
|:---:|:---:|:---:|
| | | |
>
| STR | DEX | CON | INT | WIS | CHA |  |
|:---:|:---:|:---:|:---:|:---:|:---:|:--- |
|  |  |  |  |  |  |  |
|  |  |  |  |  |  | **Mod** |
|  |  |  |  |  |  | **Sav** |
> 
|  |  |
| ---:|:--- |
| **Speed** |  |
| **Passive Perception (WIS)** |  |
| **Proficiency Bonus** |  |
| **Darkvision** |  |
>
> ---
>> [!checks|no-t] 
>> - **Death Saves**
>>	- ❌
>>	- [ ] 
>>	- [ ] 
>>	- [ ] 
>>	- ✔
>>	- [ ] 
>>	- [ ] 
>>	- [ ] 
>
> ###### Traits
| | |
| --- | --- |
| **Class** | |
| **.** | |
| **Racial Traits** | |
| **Feats** | |

Table rendering in pure markdown fills me with insurmountable dread. There are so, so many vertical line separators (|), and up until now I've been able to get away with editing tables directly in the live preview mode, which renders them as actual tables instead of as code blocks.



However, as far as I'm aware, when you have a table inside of a Callout, you have to add rows and columns and edit the text inside of the table directly via the code block itself.

Since my partner and I aren't using D&D as the medium to tell our story, I swept the Statblocks feature under the rug because I didn't trust myself to hack away at it. Besides, I'd spent many hours drafting and iterating upon a physical character sheet for my partner and I to use.



Why would I want to bother with creating a digital copy?


Because I can, that's why.


How It Began: Tracking the Master Inventory

It started on a whim Sunday afternoon/evening. I decided to build a Master Inventory List of items that we had collected in Pathfinder 2e so I could puzzle through Daggerheart-ifying them, since 2 out of our 5 PCs were about to embark on their most dangerous mission yet by infiltrating Tzah'dya Zui'hien Mai, also known as Shadow Ezada, in the Plane of Shadow.



I wanted to ensure those PCs were as prepared as they could feasibly be for the mission ahead of them, and had we still been using Pathfinder 2e as our story medium, I would have taken advantage of every item still in our collection. Maintaining the narrative is critical to me, and there were items in our possession that I'd been holding back for this kind of situation since our early Pathfinder days, so it wouldn't have sat right with me to conveniently forget we'd ever received them just because parallels don't exist in Daggerheart. They had finally become relevant to the story, so I doctored what I could to match the new system while staying true to portions of their old mechanics.


While working on this list, I developed a deeper understanding of the Meta Bind plug-in, at least the surface-level commands. My partner and I decided that some items could only be activated once per rest or once per long rest, and though I had physical cards for a few of these items already, we had neither the table space nor the tokens available to splay them all out like I wanted.


Well, what if I could keep track of this in Obsidian? That could help clear up some space in our gaming table as well, because my side is rather cramped.


Thus began my explorations into toggling with Meta Bind.



While working on the Meta Bind elements, I started considering other abilities and spells that allow for a certain number of activations between rests. While I love tracking all of those pieces physically on cards and plan to continue doing so...



...controlling 3 PCs and trying to read the text on all of those cards, especially the handwritten ones, has become something of a headache. (No, really, I somehow manage to develop a headache after each and every session, and I have only theories as to why. My leading theory is that it's a tension headache.)


Monday evening, after working some more on the Master Inventory List and letting the other cards continue to simmer in the back of my mind, I thought, 'Well, if I'm going to create a more legible digital version of the cards to navigate, then I might as well try my hand at making a full statblock. I already have the level-up sheet that Claude and I developed. I might as well put the knowledge I gained from that to the test.'


Hacking Away at the Statblock

Here it is again for reference.



I sized it up first. What would I need to keep? What could I redact? What did I need to add?

Death Saves could go. The description, basics, initiative, saves, darkvision, passive perception, speed.... Actually, most of these elements could go.


I could replace the Description and Basics with portions of the official Daggerheart character sheet: Heritage, Community, etc. That seemed easy enough to swap out, so I started there.


(The Meta Bind text boxes came later.)
(The Meta Bind text boxes came later.)

Then, I found the Death Saves section and deleted everything from there down.

The tables though...ugh.


Okay, don't focus on them quite yet, just narrow it all down to the most necessary pieces, then pick the tables apart piece by piece.

> ---
| HP | AC | Initiative |
|:---:|:---:|:---:|
| | | |
>
| STR | DEX | CON | INT | WIS | CHA |  |
|:---:|:---:|:---:|:---:|:---:|:---:|:--- |
|  |  |  |  |  |  |  |
>
> ---

So, tables don't follow the same rules as other Callout lines. Whereas every other line requires the > symbol to remain within the Callout, even the horizontal line breaks ---, tables just need their usual formatting.


The first row of vertical line pairs must be where the names of each column go: HP, AC, Initiative. That must also serve to show how many columns should exist in the table. Straightforward enough, but what about the |:---:|? What do the colons do?


I didn't find this out until later, because the ITS Theme example on the site doesn't show the table borders, but the colons tell the table how to format the titles. In this case, HP, AC, and Initiative should be centered in their cells.


That final row though. If the first row represents the header titles, the second the formatting, then the third must be where the text goes, but it would be tedious to edit the block every single time I want to change any numbers, so what if I made this part easier on myself? Will Meta Bind work inside a Callout table? Time to find out!



Hee hee hee. Perfect~


Now, Evasion, Proficiency, and Thresholds....


I don't want it to be a giant wall of text. Splashes of color help draw the eye to specific areas. The best way to add color would be to use another type of Callout inside the Statblock callout, but I also don't want to scroll endlessly to navigate the statblock, so what if I used the ITS column callout? Maybe something like...


> ---
>
>> [!column|flex 2 no-t] 
>>> [!evade|ws-med] Evasion
>>> `INPUT[number(class(input-w-full)):evade]`
>>
>>> [!attack|ws-med] Proficiency
>>> `INPUT[number(class(input-w-full)):prof]`
>
> ---

I'll use the Callout Manager plug-in to make my own "evade" and "attack" callout boxes, that way I can choose the colors and symbols I want. Since the Statblock callout starts the whole chain, I'll need to nest these callouts, using >> for the column callout and >>> for the other two.



I worked through the list, using the ITS checks callout to build the Armor, HP, Stress, and Hope sections, spending way, way too long on trying to figure out how to center the checkboxes within the Hope box. None of the styling commands I tried worked, as if the checkboxes follow their own rules, and I currently don't have the knowhow to work around it. I can deal with it for now; it just offends some part of my brain to see it uncentered.

Ahh, but we were coming up on the fun part: Experiences, Traumas, and Bonds.


Experiences are a core part of the ruleset, but Traumas and Bonds are mechanics that my partner and I discussed and implemented after watching Derik ramble on about them in one of his Daggerheart videos on his Knights of Last Call channel.


Throughout the game, your character gains 5, starting with two and gaining another each time they level into a new Tier. Each Experience allows the player to add a +2 to their roll, as long as they use a Hope and state beforehand that they're adding it. So, I needed a column for the name of the Experience and a column for the Bonus. Again, to cut down on endless scrolling, I wanted to set the Experiences and Traumas side-by-side, and I already had in mind to use two different Callouts to do so.


The thing is, we decided PCs should only have 3 Traumas max, and you know how I sure do like my uniformity.


Well, I'd cross that bridge when I came to it. The current challenge was to actually render the formatting correctly, and this is where I ran into issues.


Meta Bind was definitely the way to go for each text box, but the Meta Bind elements for the number input was so needlessly huge, it offended me. I don't need such a huge box for numbers! I want bigger text boxes for the actual text!


I could not for the life of me figure out how to resize the boxes, so I searched online after tinkering with it for an hour or more, and I found a post on Reddit from someone detailing a similar problem they were experiencing. Why, they were even using the ITS Theme!


Oh, they're using CSS....


A little more digging online led me to a github discussion page from which I yoinked the CSS snippet to use in my sheet. The Markdown in combination with very basic HTML for the line breaks...


> ---
>> [!columns|no-t s-mg] 
>>> [!info|no-i s-mg] ###### EXPERIENCES
| | |
| --- | --- |
| `INPUT[text:expT1]` | `INPUT[number(class(input-w-full)):expN1]` |
| `INPUT[text:expT2]` | `INPUT[number(class(input-w-full)):expN2]` |
| `INPUT[text:expT3]` | `INPUT[number(class(input-w-full)):expN3]` |
| `INPUT[text:expT4]` | `INPUT[number(class(input-w-full)):expN4]` |
| `INPUT[text:expT5]` | `INPUT[number(class(input-w-full)):expN5]` |
>>
>>> [!info|no-i s-mg] ###### TRAUMAS
>>> <br>
>>> 
|                                             |                          |     |
| ------------------------------------------- | ------------------------ | --- |
| `INPUT[text:traumaT1]` | `INPUT[number(class(input-w-full)):traumaN1]` |     |
| `INPUT[text:traumaT2]` | `INPUT[number(class(input-w-full)):traumaN2]` |     |
| `INPUT[text:traumaT3]` | `INPUT[number(class(input-w-full)):traumaN3]` |     |
>>
> ---

...yielded this rendering:



I didn't think about this until just now, but I'll probably alter the color for the Traumas callout. I think in the moment it was one of those instances where I went, "Eh, I'll work out those details later. I just need it to display correctly first," and then promptly forgot afterward.


Almost to the end, just one more section to go, and boy was it a pain in my backside!

So, the system from which we stole Bonds as a mechanic was a TTJRPG called Fabula Ultima designed and developed by Ema Galletto and Need Games. For Daggerheart, we simplified it, and we decided that Bonds form from Tier 2 onward, since Tier 1 is canonically a single level.


All the boxes start as dotted. When you enter Tier 2, you solidify the outline of the box. As you form bonds with your fellow players (or even NPCs/antagonists), you can check that box. If a check relevant to the character with whom you're bonded pops up, you can use that bond to add to your roll, either a +1/+2/+3 respectively depending on your Tier, as long as you spend an additional Hope (this extra cost is something my partner and I are still discussing).


How to go about this section....


I knew from the get-go I wanted them to be in a single row, but would 4 Callouts fit side-by-side using the checks callout system?


Simple in theory, difficult in execution, and really, it was these later sections that informed the earlier ones. The CSS snippet I used for the Experiences and Traumas numbers, for example, if you scroll back up further in the post, you'll see I used the (class(input-w-full)) elsewhere as well. Until this point also I hadn't bothered with adjustment styles, but when necessity calls, this is how you get to the end result you want!


(I'm screwed if I add a 5th bond...but at that point, I'll probably organize it so that it's 3-2.)
(I'm screwed if I add a 5th bond...but at that point, I'll probably organize it so that it's 3-2.)

And, for good measure, here's the Markdown.


> ---
> 
> ###### BONDS
>> [!column|flex 4 no-t s-mg txt-s]
>>> [!checks|bg-c-blue wfit content-padding-small txt-s] Kosris
>>> - [x] %% %%
>>> - [x] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-green wfit content-padding-small txt-s] Knit
>>> - [x] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-brown wfit content-padding-small txt-s] Raelor
>>> - [x] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-orange wfit content-padding-small txt-s] Lynn
>>> - [ ] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%

Since we're at Tier 3, I've stricken out the final box. The dash rendering appropriately was one of those small triumphs that made me happier than it had any right.


A Wending Road

Perhaps the greatest farce within this post is how straightforward I made the problem solving sound when it was anything but.


So much of the process was trial and error, switching between the editing and read-only modes to check that my understanding matched the outcome. Most of the time it didn't. I fumbled with the Meta Bind syntax often in the beginning, though that eventually became easier than remembering Callout formatting. I didn't even think to use Meta Bind for the general descriptive elements at the top of the sheet until the end when I went to edit Cael's "Pronouns" and thought, 'Wow, switching to the Callout syntax is really tedious when all I want to do is edit this one field.'


I rearranged sections, like placing the Thresholds beneath the Evasion/Proficiency instead of above; I played with Header styles; I messed with Callout colors. There are places I want to tinker with further, but I'm ecstatic with how good everything looks and how I was able to build it all using what I myself have learned.


Would it have gone faster had I asked Claude to build it? Certainly, and the time saved would have been valuable, but the catharsis I experienced by personally digging my hands in the dirt couldn't compare.


I'll finish this post by presenting to you the full character sheet for Cael (minus the weapons/items).



I'll also include the working Markdown.


> [!statblocks|full]
> ![[Cael Laughing.png|cover right circle htiny wtiny lp]]
> 
> # Cael
> **Pronouns:** `INPUT[text:prounouns]` 
> **Heritage:** `INPUT[text:heritage]` 
> **Class / Subclass:** `INPUT[text:class]` / `INPUT[text:subclass]` (with homebrew)
> **Multiclass / Subclass:** `INPUT[text:multi]` / `INPUT[text:subMulti]` 
> **Tier:** `INPUT[number:tier]`
> **Level:** `INPUT[number:lvl]`
> 
> ---
> | Agility | Strength | Finesse | Instinct | Presence | Knowledge |  |
|:---:|:---:|:---:|:---:|:---:|:---:|:--- |
| `INPUT[number(class(input-w-full)):agility]` | `INPUT[number(class(input-w-full)):strength]` | `INPUT[number(class(input-w-full)):finesse]` | `INPUT[number(class(input-w-full)):instinct]` | `INPUT[number(class(input-w-full)):presence]` | `INPUT[number(class(input-w-full)):knowledge]` |  |
> ---
>
>> [!column|flex 2 no-t] 
>>> [!evade|ws-med] Evasion
>>> `INPUT[number(class(input-w-full)):evade]`
>>
>>> [!attack|ws-med] Proficiency
>>> `INPUT[number(class(input-w-full)):prof]`
>
> ---
> > ##### Thresholds
> <br>
>
>> **<p style="text-align: center;"> MINOR `INPUT[number(class(input-w-q)):minDmg]` MAJOR `INPUT[number(class(input-w-q)):majDmg]` SEVERE </p>**
>
> <br>
>
> ---
> 
>> [!checks|bg-c-yellow no-i] **Armor**
>> - [ ] %% %% 
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %% 
>> - [ ] %% %%
>> - [ ] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
 >
>> [!checks|bg-c-pink no-i]  **HP**
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
 >
>> [!checks|bg-c-green no-i] **Stress**
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [-] %% %%
>> - [-] %% %%
>> - [-] %% %%
 >
>> [!checks|bg-c-white text-center no-i] **Hope**
>> ***Make a Scene:*** **Spend 3 Hope** to temporarily *Distract* a target within Close Range, giving them a -2 penalty to their Difficulty
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [ ] %% %%
>> - [-] %% %%
>> 
>
> ---
>> [!columns|no-t s-mg] 
>>> [!info|no-i s-mg] ###### EXPERIENCES
| | |
| --- | --- |
| `INPUT[text:expT1]` | `INPUT[number(class(input-w-full)):expN1]` |
| `INPUT[text:expT2]` | `INPUT[number(class(input-w-full)):expN2]` |
| `INPUT[text:expT3]` | `INPUT[number(class(input-w-full)):expN3]` |
| `INPUT[text:expT4]` | `INPUT[number(class(input-w-full)):expN4]` |
| `INPUT[text:expT5]` | `INPUT[number(class(input-w-full)):expN5]` |
>>
>>> [!info|no-i s-mg] ###### TRAUMAS
>>> <br>
>>> 
|                                             |                          |     |
| ------------------------------------------- | ------------------------ | --- |
| `INPUT[text:traumaT1]` | `INPUT[number(class(input-w-full)):traumaN1]` |     |
| `INPUT[text:traumaT2]` | `INPUT[number(class(input-w-full)):traumaN2]` |     |
| `INPUT[text:traumaT3]` | `INPUT[number(class(input-w-full)):traumaN3]` |     |
>>
> ---
> 
> ###### BONDS
>> [!column|flex 4 no-t s-mg txt-s]
>>> [!checks|bg-c-blue wfit content-padding-small txt-s] Kosris
>>> - [x] %% %%
>>> - [x] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-green wfit content-padding-small txt-s] Knit
>>> - [x] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-brown wfit content-padding-small txt-s] Raelor
>>> - [x] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%
>>
>>> [!checks|bg-c-orange wfit content-padding-small txt-s] Lynn
>>> - [ ] %% %%
>>> - [ ] %% %%
>>> - [-] %% %%

Summary of Notable Accomplishments:

  • Sessions Transcribed:

    • 126.2 - .5 (~3 hours)

    • All of 127 (~4 hours)

    • All of 132 (5 hours)

    • Total: ~12 hours

  • Built With Science:

    • Restructured to a 3-day split

    • Quads

    • Upper B + Lower Finisher

    • Active Rest workouts

    • Upper A + Lower Foundation

  • Imported the blog posts I lost from the May 7th Wipe back into the Vault (still have yet to recollect the photos)

  • Created Echo's sheet

  • Started building a Master Inventory list

  • Built character sheets for Cael, Lynn, and Knit using a combination of Callouts, the Meta Bind plugin, the ITS Theme, tables, and more

  • Finished "His Dark Materials" trilogy

    • The first book was honestly my favorite; the third book I found profoundly disappointing



Real Talk:

  • What's something you've built recently that you're proud of? Feel free to share!


This Week's Obligatory Cat Pic: Mura & Qiri


 
 
 

Comments


Every upload is a little surprise, sometimes even to me! Let's see what's to come, shall we?

Thanks for subscribing!

bottom of page