| 1 | # Obsidian Markdown to Ebook Pipeline |
| 2 | |
| 3 | This container watches a mounted markdown share for story folders and generates DOCX, EPUB, and MOBI files into a separate mounted output folder. |
| 4 | |
| 5 | ## How it works |
| 6 | |
| 7 | 1. The container scans the mounted vault under `/vault/<CREATIVE_FOLDER>`. |
| 8 | 2. Each story folder is identified by a `metadata.md` file with YAML frontmatter. |
| 9 | 3. If that frontmatter contains `export: true`, the container merges the sibling chapter `.md` files in that folder and exports a DOCX with `pandoc`, using a custom reference document so headings are black and the document uses Times New Roman instead of the default Office theme. |
| 10 | 4. That DOCX is then converted into EPUB and MOBI with Calibre's `ebook-convert`. |
| 11 | 5. The finished files are written to `/output`, with `.docx` in the root plus `/output/epub` and `/output/mobi` subfolders for the other formats. All generated files are set to mode `0644` so they are readable by all users. |
| 12 | 6. The container resets `export: false` in the story's `metadata.md`. |
| 13 | |
| 14 | ## Story layout |
| 15 | |
| 16 | Only markdown files directly inside the story folder are treated as chapters. Subfolders are ignored. |
| 17 | |
| 18 | ```text |
| 19 | Creative/ |
| 20 | Novel Name/ |
| 21 | metadata.md |
| 22 | Chapter 1 - Opening.md |
| 23 | Chapter 2 - Next Scene.md |
| 24 | cover.jpg |
| 25 | ``` |
| 26 | |
| 27 | Example `metadata.md`: |
| 28 | |
| 29 | ```md |
| 30 | --- |
| 31 | title: "Novel Name" |
| 32 | author: "Your Name" |
| 33 | language: en |
| 34 | export: false |
| 35 | # cover: cover.jpg |
| 36 | --- |
| 37 | ``` |
| 38 | |
| 39 | ## Run with Docker Compose |
| 40 | |
| 41 | Update [`docker-compose.yml`](/Users/DevUser/Desktop/SyncNotes/obsidian-epub-pipeline/docker-compose.yml) to point at your real folders, then run: |
| 42 | |
| 43 | ```bash |
| 44 | docker compose up -d --build |
| 45 | ``` |
| 46 | |
| 47 | Watch logs with: |
| 48 | |
| 49 | ```bash |
| 50 | docker compose logs -f |
| 51 | ``` |
| 52 | |
| 53 | ## Environment |
| 54 | |
| 55 | | Variable | Default | Description | |
| 56 | |---|---|---| |
| 57 | | `CREATIVE_FOLDER` | `Creative` | Subfolder under `/vault` to scan | |
| 58 | | `POLL_INTERVAL` | `10` | Seconds between scans | |
| 59 | | `LOG_LEVEL` | `INFO` | Python logging level | |
| 60 | | `VAULT_PATH` | `/vault` | Mounted source folder | |
| 61 | | `OUTPUT_DIR` | `/output` | Mounted output folder | |
| 62 | | `LUA_FILTER_PATH` | `/app/center-v.lua` | Pandoc Lua filter | |
| 63 | | `CSS_FILE_PATH` | `/app/epub-style.css` | Extra stylesheet used during EPUB and MOBI conversion | |
| 64 | |
| 65 | ## Docker Hub publishing flow |
| 66 | |
| 67 | Build and test locally first: |
| 68 | |
| 69 | ```bash |
| 70 | docker build -t YOUR_DOCKERHUB_USERNAME/obsidian-epub-pipeline:latest . |
| 71 | docker run --rm ^ |
| 72 | -v /path/to/markdown/share:/vault ^ |
| 73 | -v /path/to/epub/output:/output ^ |
| 74 | YOUR_DOCKERHUB_USERNAME/obsidian-epub-pipeline:latest |
| 75 | ``` |
| 76 | |
| 77 | Then log in and push: |
| 78 | |
| 79 | ```bash |
| 80 | docker login |
| 81 | docker push YOUR_DOCKERHUB_USERNAME/obsidian-epub-pipeline:latest |
| 82 | ``` |