Build an EPUB from your fiction project. Compiles chapters, metadata, and optionally a cover image.
Compiles fiction project chapters and metadata into an EPUB file.
/plugin marketplace add howells/fiction/plugin install fiction@howellsThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Build an EPUB file from the current fiction project.
ls chapters/*.md 2>/dev/null | wc -l | tr -d ' 'ls covers/cover.* 2>/dev/null | head -1 || echo "no cover found"chapters/ in orderepub.css (if present)covers/ (if specified)builds/ directory/fiction:build # Build dated epub (archive mode)
/fiction:build --sync # Build for Apple Books sync (preserves highlights)
/fiction:build --cover cover.png # Include specific cover image
/fiction:build /path/to/project # Build specific project
If arguments provided: $ARGUMENTS
Outputs: builds/YYYY-MM-DD/project-name-YYYY-MM-DD.epub
--sync)Outputs: builds/project-name.epub
Look for README.md, chapters/ directory. Support both flat and part-based structures:
Flat structure:
chapters/01-chapter.md
chapters/02-chapter.md
Part-based structure:
part-1-name/chapters/01-chapter.md
part-2-name/chapters/10-chapter.md
Extract from README.md:
Create a stable identifier for the EPUB:
com.author-name.project-name
This identifier is what Apple Books uses to recognize "same book, updated" — preserving highlights and reading position between builds.
Read all markdown files from chapters/ in order:
Look in covers/ for:
cover.png or cover.jpg (default)--cover argument to specifyLook for epub.css in project root. If present, include in epub.
Create a metadata file with the stable identifier:
---
title: "Book Title"
author: "Author Name"
identifier: "com.author-name.book-title"
lang: en-GB
---
Use pandoc to compile:
pandoc chapters/*.md \
--metadata-file=/tmp/metadata.yaml \
-o "builds/project-name.epub" \
--epub-cover-image=covers/cover.png \
--css=epub.css \
--split-level=1 \
--toc \
--toc-depth=1
Key options:
--split-level=1 — Only break chapters on H1 headings (avoids empty pages)--toc — Include table of contents--toc-depth=1 — Only show chapter titles in TOCWrite builds/YYYY-MM-DD/metadata.yaml:
title: "Book Title"
author: "Author Name"
identifier: "com.author-name.book-title"
built: "2026-01-18T21:30:00Z"
chapters: 18
word_count: 75000
cover: "cover.png"
Output build summary:
## Build Complete
**File:** builds/project-name.epub
**Size:** 8.4 MB
**Chapters:** 18
**Word count:** ~75,000
Cover: covers/cover.png included
Styles: epub.css applied
To open in Apple Books:
open -a 'Books' builds/project-name.epub
builds/
├── 2026-01-15/
│ ├── project-name-2026-01-15.epub
│ └── metadata.yaml
└── 2026-01-18/
├── project-name-2026-01-18.epub
└── metadata.yaml
builds/
└── project-name.epub # Always same file, updated in place
For highlights to persist between builds:
identifier field in metadata must stay constant--sync mode for consistent namingHow it works: Apple Books uses the EPUB's dc:identifier (stored in the OPF file) to recognize books. When you import a new build with the same identifier, it updates the existing book rather than adding a duplicate.
Caveat: Highlights are tied to text position. Major edits (adding/removing paragraphs) may shift or orphan highlights in that area. Minor edits (typos, word changes) are fine.
covers/
├── cover-01-concept.png # Early iterations
├── cover-02-revised.png # Refinements
├── cover-final.png # Selected cover
└── cover.png # Symlink or copy of final (used by build)
Store all cover iterations. The build uses cover.png by default.
Requires pandoc for epub generation:
brew install pandoc
--sync for daily reading while writingcovers/ directory is for iterations; cover.png is what gets built--sync modeIf you see blank pages between chapters:
page-break-after: always in epub.css — remove or change to auto\newpage in markdown files--split-level=1 is set (breaks only on H1)Minimal CSS that avoids empty page issues:
body {
font-family: Georgia, serif;
line-height: 1.6;
}
h1 {
page-break-before: auto;
margin-top: 2em;
}
p {
text-indent: 1.5em;
margin: 0;
}
p:first-of-type {
text-indent: 0;
}
Use when working with Payload CMS projects (payload.config.ts, collections, fields, hooks, access control, Payload API). Use when debugging validation errors, security issues, relationship queries, transactions, or hook behavior.