EPUB Conversion Pitfalls: Chapter Order Can't Be Guessed—The Spine Is the Only Truth

Core lesson from an EPUB conversion tool: reading order is determined by the spine, not by file lists or tables of contents.
This article shares development experience from an EPUB-to-Markdown tool, revealing a common beginner mistake: iterating files in alphabetical or manifest order leads to scrambled chapters. The author points out that EPUB reading order must be determined by parsing the spine element in the OPF file, and that TOC files (toc.ncx or nav documents) may not match. Additionally, linear extraction loses nonlinear content like footnotes and sidebars, which should be inlined at reference points. The tool also needs to support different navigation formats in EPUB2 and EPUB3 via a shim. The final output is structured Markdown organized by chapter headings, enabling accurate references in RAG pipelines. The core takeaway: searching for reading order in a file list is futile—find the control file that expresses intent and follow it.

Building an EPUB-to-Markdown tool seems like it should be a clean pipeline: unzip, parse, iterate files, output Markdown. But one developer's firsthand experience shows it's far from simple. He initially iterated through the manifest in alphabetical order, and the output chapter order became Chapter 1, Chapter 10, Chapter 2, Chapter 3… Readers even thought he was deliberately trolling them.
EPUB Is Not Just a ZIP: The Difference Between Manifest and Spine
An EPUB is essentially a ZIP package containing a bunch of XHTML files plus a control file named content.opf. The manifest lists all entries by ID, while the spine lists those IDs in reading order. The key issue: alphabetical order, manifest order, and even ID naming do not guarantee the actual human reading order. The author has seen ch1.xhtml, chapter_01.xhtml, part1.xhtml, intro.xhtml and various other naming conventions mixed together.
The fix is embarrassingly simple: parse the spine, and for each itemref, resolve its ID to the corresponding manifest entry, then read the file. If a spine entry points to a non-XHTML resource, skip it gracefully. That's it.
OPF (Open Packaging Format) is the core metadata file in the EPUB specification, typically named content.opf, and is essentially an XML document. It consists of several key parts: metadata defines the book's title, author, language, etc.; manifest lists all resources in the package (XHTML, images, CSS, etc.), each with a unique id and corresponding href; spine references the ids from the manifest via itemref elements, arranged in linear reading order, and can specify linear="no" to indicate the resource is not part of the main reading flow (e.g., footnote popups). Additionally, the guide element can provide references to key structural locations (such as cover, table of contents). Understanding the OPF structure is fundamental to correctly parsing EPUB, since reading order and resource location depend on it.
The Table of Contents Is Not the Structure—The Spine Is Authoritative
The "table of contents" perceived by readers comes from a second file (toc.ncx or the EPUB3 nav document), which may not match the spine. The author ultimately gave up on being clever and honestly followed the spine. This lesson is universal: a file list is not reading order, and a table of contents is not structure. Find the list that expresses intent and follow it.
toc.ncx is the navigation control file defined in EPUB2 (NCX stands for Navigation Control File for XML), in XML format, containing navMap, navPoint, and other elements to build a hierarchical table of contents. EPUB3 introduced an HTML5-based navigation document (typically named nav.xhtml), using <nav epub:type="toc"> elements to define the TOC structure, which is more in line with Web standards. The two are semantically similar but differ significantly in format. Note that the primary purpose of these navigation files is to provide a TOC interface for reading systems, and their content may not fully align with the spine order—for example, they may include reference pages not in reading order or external links. Therefore, the TOC file cannot be equated with the book's linear structure during parsing.
Linear Extraction Destroys Nonlinear Books
The second lesson: linear text extraction destroys nonlinear books. Footnotes, sidebars, and pull quotes are separate XHTML files referenced inline in the main text. The first version silently dropped them. Now the author inlines footnote content at the reference point, prefixed with > [^n]:, so the Markdown remains self-contained in LLM contexts. Sidebars become block quotes. Not perfect, but honest.
Nonlinear content in EPUB is typically marked in the spine with the linear="no" attribute, indicating these resources are not part of the main reading flow but may be referenced via hyperlinks in the main text. Common nonlinear content includes footnotes, endnotes, sidebars, pull quotes, glossaries, etc. These often exist as separate XHTML files; simply extracting text in spine order would miss them or incorrectly insert them into unrelated positions. The correct approach is to identify links pointing to these resources (e.g., <a href="footnote.xhtml#fn1">) when parsing the main text, and inline the target content near the reference point while maintaining Markdown's readability and self-containment.
Compatibility with EPUB2 and EPUB3: The Shim Is Worth It
EPUB2 and EPUB3 use different navigation files. Supporting both means two parsers plus a shim. The author believes the shim is worth it—half of the "broken" reports he received were EPUB2 books with .ncx but no nav document.
Shim in software engineering refers to a small piece of code that converts between different interfaces or data formats, so upper-level logic doesn't need to care about underlying differences. In EPUB parsing, the shim's role is to unify navigation data access between EPUB2 and EPUB3: for EPUB2, parse toc.ncx to extract the TOC structure; for EPUB3, parse the <nav> elements in nav.xhtml; then convert to a unified internal representation (e.g., chapter list). This way, core extraction and conversion logic can be reused, with only the entry point selecting the appropriate parser based on EPUB version. Although the shim adds a small amount of code, it significantly improves tool compatibility and robustness, especially for mixed-version EPUB files (e.g., EPUB3 that contains both NCX and nav) which can also be handled gracefully.
Output Structured Markdown to Serve RAG Pipelines
The final result provides the RAG pipeline with clean Markdown organized by chapter structure: # Chapter 3: The Thing That Happened as the heading, body text below, footnotes inlined. When an agent references "chapter 3," it means the third chapter.
The author packaged the entire tool as a single-call API that accepts a URL or base64 bytes and returns Markdown preserving chapter structure.
Takeaway: Find the Intent in the Control File
If you're building anything involving EPUB, internal package documents, or any "ebook format," this lesson generalizes: a file list is not reading order, and a table of contents is not structure. Find the list that expresses intent and follow it.
The author ends with a question: what's the weirdest "obvious thing hidden in a control file" bug you've encountered in a format you thought you understood?
One-line Summary
Core lesson from an EPUB conversion tool: reading order is determined by the spine, not by file lists or tables of contents.
Paragraph Summary
This article shares development experience from an EPUB-to-Markdown tool, revealing a common beginner mistake: iterating files in alphabetical or manifest order leads to scrambled chapters. The author points out that EPUB reading order must be determined by parsing the spine element in the OPF file, and that TOC files (toc.ncx or nav documents) may not match. Additionally, linear extraction loses nonlinear content like footnotes and sidebars, which should be inlined at reference points. The tool also needs to support different navigation formats in EPUB2 and EPUB3 via a shim. The final output is structured Markdown organized by chapter headings, enabling accurate references in RAG pipelines. The core takeaway: searching for reading order in a file list is futile—find the control file that expresses intent and follow it.
Related articles

Amphibious Transforming Drone: Beyond 100x Power Savings, What Are the Real Needs?
Is the amphibious transforming drone just a gimmick? Starting from the 100x power difference of the M4 Morphobot, explore real application scenarios and thesis topic ideas, analyzing boundary conditions where pure drones and pure ground robots both fail.

Warhound Raises $200 Million: Genetically Engineered "War Dogs" Paired with Anduril Gear
Warhound raises $200M, backed by Ben Lamm and Palmer Luckey, to genetically engineer dogs for military and law enforcement use and equip them with Anduril gear. This article analyzes its technology direction, funding logic, and ethical controversy.

Claude API Comes to Google Cloud: IAM Integration and SDK Access Guide
Anthropic hosts the full Claude API on Google Cloud with IAM-controlled permissions and unified billing. This guide covers the Vertex AI and Anthropic-hosted entry points, IAM role configuration, and SDK access.