Getting Away With Murder is a card based TTRPG I co-created with TTRPG partner in crime Joe. It released over five years ago, and is available as a print-at-home pdf from DriveThruRPG that can also be played online using the website. Earlier in April we launched a premium, high quality poker card set available via print-on-demand. This blog post tells the story of how that happened.

AI Disclosure
Because it is such an emotive topic, I want to be clear on AI use up front:
❌ This blog post is not AI generated or edited
❌ This blog post is not about AI
❌ Getting Away With Murder, rules and website, were created without AI assistance
❌ The pipeline was not “vibe coded”
✅ AI was used during the development of this pipeline
ChatGPT, and Claude, and VSCode local agents were used to get me started with LaTeX, understand error messages, and as web-search-proxies when searching for solutions to specific problems. LLMs do not appear to be particularly effective in this domain. Generated results while informative, were often incorrect, & I lent heavily on my existing programming experience to find solutions.
January 2026
ConTingency is a great little TTRPG convention held on the Essex coast at the end of January, and an opportunity for me to meet up with old friends.
I ran a few Getting Away With Murder sessions, for friends and at open tables, and I am reminded of what a delight it is to play, and how quickly new players pick it up. My good friend Claire pressed me, again, on why I have not created a print edition yet.
We had taken a run at a print edition in 2025, and found the tutorials were geared towards people with experience with DTP, using tools we didn’t own and were unfamiliar with. We thought we’d solve that by hiring someone, but we were just trading one area of inexperience for another.
I explained it wasn’t really creative graphic design we needed help with, but the technical understanding of how to create a print-ready pdf, from playing card data we have as Json, formatted correctly for playing cards. Laying out over 150 cards by hand just didn’t seem like a sensible way to do this.
Claire suggested LaTeX & Python. I’d never used LaTeX but the idea of solving this problem using programming appealed to me.
February 3rd
After an evening of research and experimentation I had proof of concept pipeline:

- existing card-back svgs are processed for embedding using Inkscape
- existing cards text content json gets processed into latex commands using a short script written in python
- handwritten and generated latex is converted to a pdf using xelatex
- the pdf is then flattened and colour space converted to print-ready “PDF/X-1a CMYK” using GhostScript (gs)
- and tying it all together: a gnu make based build system
I was working on macOS. All of these tools are available for free, and installed using brew.
This core structure survives all the way to the end, but with hindsight, two early project hygiene steps would have made life easier:
- earlier validation that the final pdf was fully to spec
- better separation of source assets from build products & intermediate files

February 4th
Feeling like I’ve got a viable route to “finished” I work on the layout and flow. LaTeX is very keen to hyphenate, which I don’t like. Controlling hyphenation turns into a rabbit hole, and I end up adding mbox wrappers around individual words in titles, during the python cards to tex step.

I also have my eye on doing some fancy frames in LaTeX:
https://www.overleaf.com/latex/templates/fancy-frames-template/hkyrtmdvfdfr
February 5th
We continue work on the layout and the text flow. This is when we introduce the use of 2 font sizes for description text, so our more wordy cards, notably Alias’ fit on the cards, without having to make the less verbose cards appear too sparse. We rejected fully variable font sizes and too visually noisy when cards seen together.

desc = tex_escape(card["desc"])
variant = desc_font_variant(desc)
if variant == "large":
desc_tex = r"\descLarge{" + desc + "}"
else:
desc_tex = r"\descSmall{" + desc + "}"February 6th
We tidy up how we are handling font files, do the card back plumbing, and introduce the info cards:

February 7th
We switched the colour definitions to CMYK. Because we have no printed reference for this, we’re forced to use the web, which isn’t the greatest way to do this because of monitor colour reproduction issues. We maybe should have sourced some print reference. Fortunately, the colours turned out OK?
We also added a title card, and duplicated the info cards, so every player can have their own. Loops in LaTeX:
\newcounter{perplayercards}
\loop
\infocard
{Setting Your Scene}
{
% ...
}
\infocard
{Playing A Scene}
{
% ...
}
\stepcounter{perplayercards}
\ifnum\value{perplayercards}<4
\repeatFebruary 8th
We start work on decorative frames, landing on art deco as it’s both period appropriate, and plausible to procedurally generate. I am at war with LaTeX at this point, it is deeply frustrating to work with, and AI tools can’t solve the problem either.

February 9th
We adjust the frames so they colour match with the card backs.
We put the QA code onto the title card. Pleasant surprise LaTeX makes that easy:
\usepackage{qrcode}
% ...
\qrcode{https://gawm.link}
February 11th
Our battle with colour profiles begins in earnest. We start using the one provided by the print company, and add a verification step to check the print ready pdf is actually to-spec. The verification does not pass. The title card has a TAC (Ink Coverage) problem:
% make verify Verifying CMYK TAC ≤ 240%... FAIL page : 365.0% (C 100.0 M 100.0 Y 100.0 K 65.0)
February 16th
We add the innocent and guilt tokens (to be cut out) to the deck, initially 6 per card, but we switch to 4 per card later. I do some 2-sided test prints at home to check alignment. I am not confident about the flip direction for front and back for final print, so we settle on a token layout that should work flipped horizontally and vertically:

February 17th
We add the text, and decorative frames to the tokens and switch to white text for innocence, to improve contrast.

February 18th
Support for passing line breaks through the pipeline for in detail descriptions is fixed, as it is needed on 2 cards.
February 19th
I am still struggling to fix the TAC issue.
Having reviewed the print specs, I decide I need to convert all the PNGs to TIF. I was probably wrong. But I now have a real mess of intermediate files after running the pipeline, so I set up a .gitignore.
In the end the TAC issue is fixed by:
- converting the sepia photo to greyscale
- changing the MURDER drop shadow from RichBlack to default black (K only).
- turning off transparency on the drop shadow
With all 3 of these changes in place, the verify step passes.
February 21st
We update the layout code to support both EU and US poker card sizes. In the end we use US only:

February 22nd – 24th
We start trying different ways to improve the card backs. The card backs we are using so far are the same SVGs we created for the print-at-home and digital editions. They were scanned from out of copyright vintage cards we purchased, scanned, and vectorized, then edited to add detail category labels using Inkscape.
So far they have been embedded as PNGs, but Inkscape supports SVG to PDF vectors, so we do that, and explore alternative ways for framing the detail type text on the card backs:



February 26th
We settle on a design and bake the text onto the card back (svgs) using Inkscape.


We are also reviewing new bonus card texts and making small text corrections.
February 27th
We colour both sides of the tokens, not just the backs, and increased the padding between text and frame edges:


February 28th
Almost done, we explore variable spacing between the lines the title box:


March 1st
Rolled back the variable spacing in the title box, but kept the better fixed positioning discovered during the process:


March 5th
Blank details cards are added as spares or write ins completing the work.
This is the version sent to the printers!
April 4th & 5th
With the test print finally back, and unboxed:
We update the website and reorganised the files somewhat ready to merge.
The full pipeline is available on github: