Kindle-Ready eBooks from Markdown

I've found creating eBooks from Markdown to be a nice way to learn away from the computer. Here are a few notes on how to set up a workflow for generating Kindle-ready EPUBs from Markdown files.

The Setup

Install pandoc via Homebrew:

brew install pandoc

Then add a script to your package.json. I'm assuming here you are using a Node.js project with pnpm, but similar instructions apply to different setups; there is very little that is actually Node.js-specific.

{
  "scripts": {
    "book:epub": "pandoc book/*.md --epub-cover-image=book/cover.png -t epub3 --metadata uuid='a3f1c820-4b2e-4d91-8c77-1e9f3d5b6a04' --metadata author='AUTHOR' --metadata title='TITLE' -o 'TITLE - AUTHOR.epub'"
  }
}

Run it with pnpm book:epub.

What Each Flag Does

book/*.md globs your chapter files in filename order, so a naming convention like 01-intro.md, 02-chapter.md keeps things tidy.

--epub-cover-image points to your cover art. JPEG is recommended, but PNG works fine too. I'd suggest a 3:4 aspect ratio, for example 1200x1600px, as that works well on most eBook readers. You can use something like Gemini or ChatGPT to generate the image.

-t epub3 targets EPUB 3, which Kindle handles well.

--metadata uuid sets the unique identifier that EPUB requires. Generate a fresh one for every new book at uuidgenerator.net and never reuse one between titles, as the whole point is that it is unique. This seems to be the most important detail for the Send to Kindle service to work at all.

--metadata title and --metadata author are technically optional, but they populate the eBook's metadata fields and make the Send to Kindle app behave more reliably. Pandoc also uses the title for the table of contents, so it's worth setting.

Naming the Output File

Avoid a generic name like book.epub. The Send to Kindle desktop app will not pick up the title or author from metadata. Use something descriptive:

'TITLE - AUTHOR.epub'

Where TITLE might be PyTorch Notes. Though if you use the web client to send (see below), it is best to go with TITLE.epub, as the filename is used as the displayed title even when the metadata title is set. So a full example would be PyTorch Notes.epub.

AI-Generated Content

Some suggestions:

  • Ask for each chapter as a separate file, drop them into your book/ directory, and run the script.
  • Request files named like 001-intro.md, 002-chapter.md to ensure alphabetical ordering and an easier time with pandoc globs.
  • Ask the LLM to generate a single markdown file per source code file. Ask for code snippets and specific extra chapters. Ask for background, questions for reflection, multiple choice questions at the end of the chapter, and so on.

Sending to Kindle

Once you have the .epub, the easiest route is Send to Kindle. You can either download the desktop app or use the web version.