EPUB 3.3 Photo Book Generator
Generate EPUB 3.3 photo books from Lightroom Classic collections via the Go package at internal/epub/.
EPUB 3.3 Spec Essentials
Container Structure
mimetype ← first file, uncompressed, no extra fields
META-INF/
container.xml ← points to OEBPS/content.opf
OEBPS/
content.opf ← package document
toc.xhtml ← EPUB 3 navigation document
toc.ncx ← EPUB 2 backward compat
styles/
book.css
text/
cover.xhtml
title.xhtml
photo_001.xhtml ...
map.xhtml ← optional
images/
cover.jpg
001.jpg ... NNN.jpg
map.png ← optional
mimetype File
Must be:
- First entry in the ZIP archive
- Uncompressed (stored, no deflation)
- No extra field data in the local file header
- Content:
application/epub+zip(no trailing newline)
OPF Package Document
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://www.idpf.org/2007/opf" version="3.0" unique-identifier="pub-id">
<metadata xmlns:dc="http://purl.org/dc/elements/1.1/">
<dc:identifier id="pub-id">urn:uuid:...</dc:identifier>
<dc:title>...</dc:title>
<dc:creator>...</dc:creator>
<dc:language>en</dc:language>
<meta property="dcterms:modified">2024-01-01T00:00:00Z</meta>
</metadata>
<manifest>
<item id="nav" href="toc.xhtml" media-type="application/xhtml+xml" properties="nav"/>
<item id="ncx" href="toc.ncx" media-type="application/x-dtbncx+xml"/>
<item id="css" href="styles/book.css" media-type="text/css"/>
<item id="cover" href="text/cover.xhtml" media-type="application/xhtml+xml"/>
<!-- ... -->
</manifest>
<spine toc="ncx">
<itemref idref="cover"/>
<itemref idref="title"/>
<!-- photo pages -->
</spine>
</package>
Required metadata: dc:identifier, dc:title, dc:language, dcterms:modified.
XHTML Content Documents
All content documents must be valid XHTML5 with the EPUB namespace:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:epub="http://www.idpf.org/2007/ops"
xml:lang="en" lang="en">
<head>
<meta charset="UTF-8"/>
<title>Page Title</title>
<link rel="stylesheet" type="text/css" href="../styles/book.css"/>
</head>
<body>
<!-- content -->
</body>
</html>
Key requirements:
- Must include
xml:langandlangattributes on<html> - Use
xmlns:epubfor semantic inflection (epub:type) - Self-closing tags for void elements (
<meta/>,<link/>,<img/>) - All attribute values must be quoted
Navigation Document (toc.xhtml)
Must contain a <nav epub:type="toc"> element. Should also include landmarks:
<nav epub:type="landmarks">
<ol>
<li><a epub:type="cover" href="text/cover.xhtml">Cover</a></li>
<li><a epub:type="toc" href="toc.xhtml">Table of Contents</a></li>
<li><a epub:type="bodymatter" href="text/photo_001.xhtml">Photos</a></li>
</ol>
</nav>
Semantic Inflection
Use epub:type for structural semantics:
cover— cover pagetitlepage— title pagetoc— table of contentsbodymatter— main contentfootnote,endnote,bibliography— back matter (not used in photo books)
CSS in EPUB 3.3
Spec-Guaranteed Support
EPUB 3.3 references CSS 2.1 as the required baseline, plus specific CSS3 modules:
| Module | Key Features |
|---|---|
| CSS 2.1 | Selectors, box model, positioning, floats, fonts, colors |
| CSS Writing Modes 3 | writing-mode, direction, vertical text |
| CSS Speech | Aural rendering (speak, voice-family) |
| CSS Fonts 3 | @font-face, font-feature-settings |
| CSS Text 3 | word-spacing, letter-spacing, text-transform |
| CSS Text Decoration 3 | text-decoration-color, text-decoration-style |
Widely Supported (Not Spec-Guaranteed)
Major reading systems (Apple Books, Kobo, Readium, Thorium) support more CSS3 than the spec requires. These are practically safe but not guaranteed:
- Flexbox (
display: flex) calc()- Viewport units (
vw,vh,vmin,vmax) object-fit,object-position- CSS custom properties (
--var) border-radius,box-shadow,opacity- CSS Grid (Apple Books, Readium — less universal)
Not Safe / Avoid
- CSS animations and transitions (inconsistent support)
position: fixed(meaningless in paginated context)position: sticky- Media queries beyond
min-width/max-width(limited in many readers) backdrop-filter- Container queries
Current Project CSS Approach
The stylesheet is defined in internal/epub/style.go as the bookCSS constant:
- Georgia serif font stack
- Responsive images:
max-width: 100%,object-fit: contain - Cover: flexbox centering with
object-fit: cover - Minimal spacing, white background, dark text (#333)
- Title page: 2.2em heading, muted gray author/date
Fixed-Layout (FXL) Considerations
For pre-paginated photo pages, add to OPF metadata:
<meta property="rendition:layout">pre-paginated</meta>
<meta property="rendition:spread">auto</meta>
Each FXL page needs a viewport meta tag:
<meta name="viewport" content="width=1200, height=1600"/>
FXL pages use absolute positioning — CSS2.1 features are sufficient.
Project Code Structure
Files
| File | Purpose |
|---|---|
internal/epub/epub.go |
Main Generate() entry point, ZIP assembly, OPF/XHTML templates |
internal/epub/style.go |
CSS stylesheet constant (bookCSS) |
internal/epub/image.go |
ResizeJPEG() — downscale with CatmullRom resampling |
internal/config/config.go |
Config struct with author, image size, quality settings |
Config Defaults
| Field | Default | Purpose |
|---|---|---|
Author |
— | DC creator metadata |
MaxPhotoEdge |
1200 | Max long-edge pixels |
JPEGQuality |
85 | Re-encode quality |
MapWidth |
600 | Static map pixel width |
MapHeight |
400 | Static map pixel height |
Page Types Generated
- Cover (
cover.xhtml) — full-bleed image,epub:type="cover" - Title (
title.xhtml) — title, summary, author, date;epub:type="titlepage" - Photo (
photo_NNN.xhtml) — image + optional h2 title + optional caption - Map (
map.xhtml) — optional static map from GPS data
Validation
Use epubcheck to validate output:
# Install
brew install epubcheck
# Validate
epubcheck output.epub
Common validation errors:
- Missing
dc:languageordcterms:modifiedin OPF mimetypefile compressed or not first in ZIP- Missing
xml:lang/langon<html>element - Nav document missing
epub:type="toc"nav element - Image referenced in OPF but not in ZIP (or vice versa)
- Non-self-closing void elements in XHTML
Build & Test
# Build the CLI
scripts/build-mac.sh
# Run Go tests
scripts/test.sh
# End-to-end test
scripts/test-e2e.sh
# Lint Go code
golangci-lint run ./...
Converted and distributed by TomeVault — claim your Tome and manage your conversions.