The code and open-source tools I used to produce a science fiction anthology
For technical teams, the notable pattern here is not publishing itself but the architecture of the workflow. A single text-based source of truth, with YAML for metadata and content state, reduces handoff friction and makes every editorial decision inspectable in Git. That approach is especially relevant when one person has to manage selection, tracking, and production without a separate CMS or project system.
The bigger engineering lesson is reproducibility. By generating both print and ebook outputs from the same managed inputs, the pipeline avoids divergence between editions. That keeps late-stage layout changes safer because the book can be rebuilt from source rather than patched in place. For teams that maintain documentation, reports, or knowledge products, the same pattern can lower technical debt and make release timing more predictable.
There is also an integration boundary worth noting. The workflow depends on conversion between authoring formats, typesetting, and EPUB packaging, so each step must preserve structure such as titles, bylines, and navigation. That creates a trade-off: the more automated the pipeline becomes, the more important it is to define formatting conventions early and keep transformation scripts simple enough to debug when source material arrives in inconsistent formats.
In practice, the value is operational control. Plain files, command-line tooling, and version control make the production process transparent enough to adjust quickly without losing confidence in the final artifacts. That is a useful model for any content-heavy system where repeatability, auditability, and format interoperability matter more than visual tooling alone.
- Git-friendly: Every decision I made was tracked in version control
- Human-readable: I could open any file in a text editor and understand what I was looking at
- Easy to build scripts around: I wrote several Python functions to do different kinds of metadata introspection that I’ll go through
data/
story-progress.yaml # Central tracking file
markets.yaml # Magazine metadata
themes.yaml # Theme occurrence tracking
subgenres.yaml # Subgenre tallies
stories/
clarkesworld-magazine/
nelson_11_24.yaml # Individual story files
pak_06_24.yaml
reactor-magazine/
larson_breathing.yaml
...
title: "Twenty-Four Hours"
author: H.H. Pak
market: clarkesworld-magazine
url: https://clarkesworldmagazine.com/pak_06_24/
word_count: 4540
year: 2024
slug: pak_06_24
summary: ...
story-progress.yaml tracks editorial state:
clarkesworld-magazine-nelson_11_24:
title: "LuvHomeโข"
author: Resa Nelson
market: clarkesworld-magazine
status: accepted # or: not_started/relevant/rejected
date_added: '2024-09-08T08:22:47.033192'
se.py) to help me navigate all this data. Since I do all this work at night after my kids go to sleep, I wanted something fast that mirrored a lot of the other work I do on the command line. The tool is simple:
python se.py โhelp
usage: se.py [-h] {markets,stories,relevant,decide,accepted,compile} ...
Story Evaluator CLI
positional arguments:
{markets,stories,relevant,decide,accepted,compile}
Available commands
markets List markets
stories Manage stories
relevant List URLs for stories marked as relevant
decide Make accept/reject decisions on relevant stories
accepted Manage accepted stories
compile Show anthology compilation statistics
optional arguments:
-h, โhelp show this help message and exit
compile command ended up being really useful โ it gave me instant feedback on anthology size and composition:
ANTHOLOGY COMPILATION STATISTICS
============================================================
Total Stories: 16
Total Word Count: 115,093 words
Average Word Count: 7,193 words
Unique Authors: 16
Markets Represented: 4
STORIES BY MARKET:
analog-magazine: 2 stories (12.5%)
asimovs-magazine: 2 stories (12.5%)
clarkesworld-magazine: 10 stories (62.5%)
reactor-magazine: 2 stories (12.5%)
memoir document class. Here’s what I liked about this approach:
- Reproducible: I can rebuild the entire book from source in a few seconds, and I can use the same templates next year
- Professional typography: LaTeX handles ligatures, kerning, and line breaking better than I could manually
- Custom fonts: I used Crimson Pro for body text and Rajdhani for titles
- Again, version control that I’m used to: The entire book is just text files in Git
\documentclass[final,11pt,twoside]{memoir}
\usepackage{compelling}
\begin{document}
\begin{frontmatter}
\include{title}
\tableofcontents
\end{frontmatter}
\begin{mainmatter}
\include{introduction}
\include{death-and-the-gorgon}
\include{the-best-version-of-yourself}
% ... 14 more stories
\include{acknowledgements}
\end{mainmatter}
\end{document}
compelling.sty, a custom style package. Here’s a link to the full, messy file. Some highlights:
% 6x9 inch trade paperback size
\setstocksize{9in}{6in}
\settrimmedsize{9in}{6in}{*}
% Margins
\setlrmarginsandblock{1.00in}{0.75in}{*}
\setulmarginsandblock{0.75in}{0.75in}{*}
% Typography nerding
\usepackage[final,protrusion=true,factor=1125,
stretch=70,shrink=70]{microtype}
% Custom fonts loaded from local files
\setromanfont[
Ligatures=TeX,
Path=./Crimson_Pro/static/,
UprightFont=CrimsonPro-Regular,
BoldFont=CrimsonPro-Bold,
ItalicFont=CrimsonPro-Italic,
BoldItalicFont=CrimsonPro-BoldItalic
]{Crimson Pro}
\setsansfont[
Path=./Rajdhani/,
UprightFont=Rajdhani-Bold,
BoldFont=Rajdhani-Bold,
ItalicFont=Rajdhani-Bold,
BoldItalicFont=Rajdhani-Bold
]{Rajdhani}
% Chinese font family for CJK characters
\newfontfamily\chinesefont{PingFang SC}
microtype package does a lot of subtle work with character spacing and line breaking that makes the text look professionally typeset.
I wanted story titles in bold sans-serif with author names underneath in a lighter gray. Here’s how I set that up:
\renewcommand{\chapter}[2]{
\pagestyle{DefaultStyle}
\stdchapter*{
\sffamily
\LARGE
\textbf{\MakeUppercase{#1}}
\\
\large
\color{dark-gray}
{\MakeUppercase{#2}}
}
\addcontentsline{toc}{chapter}{
\protect\parbox[t]{\dimexpr\textwidth-3em}{
\sffamily#1
\\
\protect\small
\protect\color{gray}
\protect\textit{#2}
}
}
\def\leftmark{#1}
\def\rightmark{#2}
}
chapter command to take two arguments, the title and byline, and sets up both the chapter formatting, TOC formatting, and makes sure that the title and byline are printed in the headers on alternating pages.
Now every story file just says:
\chapter{Death and the Gorgon}{by Greg Egan}
[story content]
# Convert LaTeX to EPUB
pandoc 2025.tex -o Think_Weirder_2025.epub \
โtoc \
โepub-cover-image=cover_optimized.jpg \
โcss=epub-style.css \
โmetadata title="Think Weirder" \
โmetadata author="Edited by Joe Stech"
def modify_toc(nav_content, authors):
"""Add author bylines to TOC entries."""
pattern = r'<a href="([^"]+)">([^<]+)</a>'
def add_author(match):
href, title = match.group(1), match.group(2)
chapter_id = extract_id_from_href(href)
if chapter_id in authors:
author = authors[chapter_id]
return f'<a href="{href}">{title}<br />\n' \
f'<em>{author}</em></a>'
return match.group(0)
return re.sub(pattern, add_author, nav_content)
se.py to save metadata in the moment that could be sliced and diced later was so important.
Reproducible builds were a lifesaver. I made changes to the book layout right up until the week before publication. Because I could rebuild the entire book in seconds, and everything was backed up in git, I could experiment freely without worrying about breaking things.
Simple file formats made me comfortable. When something went wrong, I could always open a YAML file or look at the LaTeX source and understand what was happening. I never hit a point where the tools were a black box.
I didn’t need to understand everything up front. I learned LaTeX details as I went (arguably I still don’t really understand LaTeX). Same with Pandoc. I got something basic working first, then incrementally improved it.
Can you do this too?
If you’re thinking about publishing a book โ whether it’s an anthology, a novel, or a collection of technical writing โ I think this approach is worth considering. There’s something motivating about having a detailed understanding of every step in the production process. If you have questions feel free to reach out, I love talking about this hobby! You can email me at [email protected].
Enjoyed this article? Sign up for our newsletter to receive regular insights and stay connected.
