Metadata-Version: 2.4
Name: bookforge-kdp
Version: 0.2.0
Summary: Turn a book.yaml file and a folder of markdown into a KDP-ready paperback PDF, a validated EPUB3, and both covers. Requires pandoc and epubcheck on PATH.
Author: Pushkar Mishra
License: MIT License
        
        Copyright (c) 2026 Pushkar Mishra
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/pushkar-mishra/BookForge
Project-URL: Repository, https://github.com/pushkar-mishra/BookForge
Project-URL: Issues, https://github.com/pushkar-mishra/BookForge/issues
Keywords: kdp,epub,epub3,self-publishing,amazon-kdp,pandoc,book,publishing,pdf
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Other Audience
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Text Processing :: Markup :: Markdown
Classifier: Topic :: Text Processing :: Markup :: reStructuredText
Classifier: Topic :: Software Development :: Build Tools
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pyyaml>=6.0
Requires-Dist: pypdf>=4.0
Requires-Dist: weasyprint>=61.0
Requires-Dist: pillow>=10.0
Requires-Dist: pypdfium2>=4.25
Provides-Extra: studio
Requires-Dist: fastapi>=0.110; extra == "studio"
Requires-Dist: uvicorn>=0.27; extra == "studio"
Requires-Dist: ruamel.yaml>=0.18; extra == "studio"
Requires-Dist: python-multipart>=0.0.9; extra == "studio"
Provides-Extra: dev
Requires-Dist: build>=1.0; extra == "dev"
Requires-Dist: twine>=5.0; extra == "dev"
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: httpx2>=0.1; extra == "dev"
Dynamic: license-file

<h1 align="center">BookForge</h1>

<p align="center">
  <em>A book.yaml file and a folder of markdown in — a KDP-ready paperback, EPUB, and covers out.</em>
</p>

<p align="center">
  <a href="https://pypi.org/project/bookforge-kdp/"><img alt="PyPI" src="https://img.shields.io/badge/pip%20install-book--forge-3b5bdb"></a>
  <img alt="Python" src="https://img.shields.io/badge/python-3.10%2B-3b5bdb">
  <img alt="Engine" src="https://img.shields.io/badge/engine-pandoc%20%2B%20weasyprint-1971c2">
  <img alt="QA" src="https://img.shields.io/badge/verify-6%20automated%20checks-2f9e44">
  <a href="https://github.com/pushkar-mishra/BookForge/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/pushkar-mishra/BookForge/actions/workflows/ci.yml/badge.svg"></a>
  <img alt="Tests" src="https://img.shields.io/badge/tests-141%20passing-2f9e44">
  <img alt="Self-built" src="https://img.shields.io/badge/self--built%20guide-130pp%20%C2%B7%200%20epubcheck%20errors-2f9e44">
  <img alt="API keys" src="https://img.shields.io/badge/API%20keys-none%20required-2f9e44">
  <img alt="Platforms" src="https://img.shields.io/badge/platforms-macOS%20%C2%B7%20Linux%20%C2%B7%20Windows-868e96">
  <a href="https://github.com/pushkar-mishra/BookForge/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-868e96"></a>
</p>

<a href="https://raw.githubusercontent.com/pushkar-mishra/BookForge/main/docs/images/cover-front.jpg"><img src="https://raw.githubusercontent.com/pushkar-mishra/BookForge/main/docs/images/cover-front.jpg" alt="BookForge — The Step-by-Step Guide to Publishing Your Book on Amazon KDP, by Pushkar Mishra" height="360px" align="right"></a>

BookForge is the shared build pipeline left over after six independent
nonfiction book projects each hand-rolled their own scripts to solve the
same problem. Point it at a `book.yaml` file and a `content/` folder of
markdown chapters and it produces the same four deliverables every KDP
paperback + Kindle listing needs — with **no per-book fork of any build
script**.

**Repo:** https://github.com/pushkar-mishra/BookForge &nbsp;·&nbsp;
**License:** MIT &nbsp;·&nbsp; **PyPI:** `pip install bookforge-kdp`

> **This repo is the pipeline. `examples/sample-book/` is the manual.**
> It's a complete, real 130-page book — *BookForge: The Step-by-Step
> Guide to Publishing Your Book on Amazon KDP* — built entirely by the
> tool it documents, from nothing but its own `book.yaml` and markdown.
> See [The Book](#the-book) below.

<br clear="right"/>

---

## What you get

- **A 6x9in interior PDF** — mirrored margins, running page numbers, a
  generated table of contents, half-title/title/copyright/About-the-Author
  pages auto-generated from `book.yaml`
- **A validated EPUB3** — same source content, no embedded cover (KDP
  supplies its own), passes `epubcheck` as part of the build, not after
- **A paperback wrap cover** — back + spine + front in one bleed PDF, spine
  width computed automatically from the interior's actual page count
- **A Kindle front cover** — a separate JPG at the exact 1800×2700px KDP
  expects
- **A ready-to-upload `amazon-kdp/` folder** — the four files above plus a
  generated README, checklist, and listing metadata, all rendered straight
  from `book.yaml` so nothing in it can drift out of sync

Everything runs **fully local** — no LLM calls, no API keys, no network
dependency once `pandoc` and `epubcheck` are installed.

---

## Two ways to use it

Both are fully supported, both read and write the same `book.yaml` and
`content/*.md`, and you can switch between them at any point — write a chapter
in the UI, build it from the terminal, or the reverse.

<table>
<tr>
<th align="left">Command line</th>
<th align="left">BookForge Studio (UI)</th>
</tr>
<tr valign="top">
<td>

```bash
pip install bookforge-kdp

bookforge new ~/Books/my-book
cd ~/Books/my-book
./build.sh
```

Scriptable, CI-friendly, no web stack.

</td>
<td>

```bash
pip install "bookforge-kdp[studio]"

bookforge studio
# → http://127.0.0.1:8000
```

Write, press **Build book**, see the covers.

</td>
</tr>
</table>

Prerequisites are the same for both: **Python 3.10+**, plus `pandoc` and
`epubcheck` on `PATH` (`brew install pandoc epubcheck`, or `apt install pandoc
epubcheck`). `bookforge` checks for both at build time and prints an install
hint if either is missing.

---

## Quickstart — command line

```bash
python3 -m venv .venv
.venv/bin/pip install bookforge-kdp
source .venv/bin/activate   # puts `bookforge` on PATH for this shell
```

> Skipped `source .venv/bin/activate`? Every command below still works if
> you spell out the full path instead, e.g. `.venv/bin/bookforge new ...`.

```bash
bookforge new ~/Books/my-new-book --title "My Book" --author "Author Name"
cd ~/Books/my-new-book
# edit book.yaml and content/, then either:
./build.sh                 # or build.bat on Windows -- runs the full pipeline
# ...or run each stage yourself:
bookforge build all        # dist/interior.pdf + dist/{slug}.epub
bookforge covers           # dist/cover-paperback.pdf + dist/cover-kindle.jpg
bookforge verify           # QA checks — page count, spine math, epubcheck, ...
bookforge package          # assembles amazon-kdp/ for upload
```

While drafting, run `bookforge watch` (or `./build.sh watch`) in its own
terminal: it rebuilds on every save to `book.yaml`, `content/`, or
`assets/`, and a bad edit prints a clean error without killing the loop.

---

## Quickstart — BookForge Studio

Prefer a window to a terminal? Studio is a small local app that does the same
work: create chapters, write them, press **Build book**. It writes the same
files the commands do, so you can switch between the two freely.

```bash
pip install "bookforge-kdp[studio]"
bookforge studio                        # or: bookforge studio path/to/book
```

Then open <http://127.0.0.1:8000>. No account, no sign-in, nothing leaves
your machine — it binds to `127.0.0.1` only.

The UI is an **optional extra**: a plain `pip install bookforge-kdp` stays a CLI
with no web stack, and `bookforge studio` then tells you exactly what to
install rather than failing obscurely.

- **Landing screen** — start a new book, or open one. **Browse…** opens the
  system's native folder dialog (the server opens it, since a browser can't
  hand a page a real path), and books you've opened before are listed.
- **Chapters** — the sidebar *is* your table of contents. Adding a chapter
  writes the markdown file **and** registers it in `book.yaml`; removing one
  unlists it and leaves your words on disk.
- **Book details** — title, author, subtitle, biography, tagline, ISBN, plus
  author-photo and cover-art upload, as a plain form. You never see YAML,
  and `book.yaml` is edited in place with your comments intact.
- **Build book** — the full pipeline, with the six `verify` checks reported
  in plain language ("Cover fits the interior").

Studio ships inside the package but behind the extra, so the two can never
disagree about internal APIs it uses (`book_outline()`, `verify_build()`).
See [`docs/STUDIO.md`](https://github.com/pushkar-mishra/BookForge/blob/main/docs/STUDIO.md), or Appendix D of the book.

---

## The book

*BookForge: The Step-by-Step Guide to Publishing Your Book on Amazon
KDP* — a complete 130-page manual, written and built entirely by
BookForge itself, source in
[`examples/sample-book/`](https://github.com/pushkar-mishra/BookForge/tree/main/examples/sample-book):

<a href="https://raw.githubusercontent.com/pushkar-mishra/BookForge/main/docs/images/cover-full.png"><img src="https://raw.githubusercontent.com/pushkar-mishra/BookForge/main/docs/images/cover-full.png" alt="BookForge — full wraparound cover (back, spine, front)" width="100%"></a>

| Part | Chapters |
|---|---|
| I. Before You Write | Why a Book Needs a Build Pipeline · Installing BookForge · Your First Project · The Config File |
| II. Writing Your Content | Where Content Goes · Parts, Chapters, and Numbering · Callouts and Diagrams |
| III. Building the Three Deliverables | The Interior PDF · The EPUB · The Covers |
| IV. Shipping to KDP | Verify · Package · Publishing to KDP · After You Publish |
| Appendices | The book.yaml Reference · Troubleshooting · Command Reference · BookForge Studio · Glossary |

Build it yourself:

```bash
git clone https://github.com/pushkar-mishra/BookForge
cd BookForge && python3 -m venv .venv && .venv/bin/pip install -e .
source .venv/bin/activate
cd examples/sample-book
python3 assets/diagrams/gen_diagrams.py   # generate the seven figures
./build.sh                                 # interior, EPUB, covers, verify, package
```

---

## Pipeline stages

| Command | Produces | Notes |
|---|---|---|
| `bookforge new` | a scaffolded project | `book.yaml` + starter `content/` + `assets/` + `build.sh`/`build.bat` |
| `bookforge build pdf\|epub\|all` | `dist/interior.pdf`, `dist/{slug}.epub` | EPUB fails the build on any `epubcheck` error |
| `bookforge covers` | `dist/cover-paperback.pdf`, `dist/cover-kindle.jpg` | spine width derived from the interior's page count |
| `bookforge diagrams render <dir>` | `*.png` next to each `*.svg` | rasterizes `bookforge.diagrams` DSL output for EPUB |
| `bookforge verify` | a pass/fail QA report | see [Verify](#verify) below |
| `bookforge package` | `amazon-kdp/` | copies build outputs + renders README/checklist/metadata |
| `bookforge watch` | continuous rebuilds | polls `book.yaml`, `content/`, `assets/` for changes |
| `bookforge studio` | the local web UI | optional extra: `pip install "bookforge-kdp[studio]"` |

Every new book also gets `build.sh` / `build.bat`, a thin wrapper around
the same commands: `./build.sh` (no args) runs `diagrams → build all →
covers → verify → package` in order and **stops at the first failure**
(e.g. a failing `verify` blocks `package` from ever running), or run one
stage at a time with `./build.sh pdf|epub|covers|diagrams|verify|package|watch`.

Every command re-reads `book.yaml` and re-globs `content/` on each
invocation — edit config or markdown, rerun (or leave `watch` running),
and the output always reflects current source.

---

## Verify

`bookforge verify` runs six checks against the current build, each one a
real KDP rejection reason turned into an automated gate instead of a
manual pre-upload ritual:

| Check | Fails when |
|---|---|
| `page_count_minimum` | interior is under KDP's paperback minimum (`kdp.min_pages`, default 24) |
| `spine_math_matches_cover` | the cover PDF's width doesn't match the spine width for the current page count |
| `epubcheck_zero_errors` | `epubcheck` reports any error on the built EPUB |
| `kindle_pixel_dims` | the Kindle cover isn't exactly 1800×2700px |
| `no_placeholder_text` | any chapter still contains draft markers |
| `chapter_frontmatter_complete` | a chapter referenced in `book.yaml` is missing or has no `title:` |

`verify` exits non-zero if any check fails, so it's safe to wire into CI.
Every failure also prints a `Recommendation:` line with the concrete next
step, not just the diagnosis:

```
[FAIL] page_count_minimum: 10 pages (minimum 24)
...
Recommendation:
  - page_count_minimum: add 14 more page(s) of content (new chapters, or
    longer existing ones) and rebuild, or lower kdp.min_pages in book.yaml
    if this isn't going to KDP paperback
```

---

## Repository layout

```
src/bookforge/
  config.py       book.yaml schema — structure (parts -> chapters), metadata, palette, trim
  assemble.py     content/*.md + book.yaml -> one pandoc-ready markdown string
  pdf.py          assemble -> pandoc html5 -> WeasyPrint -> pypdf page count
  epub.py         assemble -> pandoc epub3 -> epubcheck
  covers.py       paperback wrap + Kindle cover, same WeasyPrint toolchain as pdf.py
  callouts.py     the 8 callout kinds (label + accent color + tint), shared by PDF and EPUB
  diagrams.py     SVG diagram primitives + a declarative DSL (flow / vflow / cycle)
  raster.py       PDF -> PNG/JPG via pypdfium2 (no system binary, all platforms)
  verify.py       the six QA checks above
  package.py      assembles amazon-kdp/ from dist/ + renders README/checklist/metadata
  watch.py        mtime-polling edit -> rebuild loop, no watchdog dependency
  deps.py         checks pandoc/epubcheck are on PATH, prints an install hint if not
  errors.py       BookForgeError hierarchy — user-causable failures print cleanly
  cli.py          argparse entry point wiring all of the above to `bookforge <command>`
  templates/      interior.css, epub.css
  scaffold/       the project `bookforge new` copies (including build.sh / build.bat)
tests/           141 tests, no system binaries required
  studio/         the optional local UI (FastAPI + vanilla JS), shipped
                  behind the `studio` extra so a plain install stays a CLI
```

### Book project layout

```
mybook/
  book.yaml             # title, author, palette, trim size, table of contents
  build.sh, build.bat   # run the whole pipeline, or one stage at a time
  content/
    front/              # dedication.md, preface.md -- listed in book.yaml front_matter
    chapters/           # ch01-slug.md, ... -- referenced from parts[].chapters
    back/               # glossary.md, appendices -- listed in book.yaml back_matter
  assets/
    author/author-photo.png
    cover/cover-art.png   # optional; an auto-generated mark is used if absent
    diagrams/             # *.svg sources (bookforge.diagrams DSL) + generated *.png
  dist/                 # gitignored -- build output
  amazon-kdp/           # gitignored -- `bookforge package` output
```

Half-title, title page, copyright page, table of contents, and the "About
the Author" page are always auto-generated from `book.yaml`. Everything
else is an ordinary markdown file listed in `front_matter`/`back_matter`,
or a chapter referenced from a `parts[].chapters` list.

---

## Front matter and the copyright page

Title, copyright, contents, and About-the-Author pages are generated from
`book.yaml` — but the wording and the page conventions are yours:

```yaml
copyright:
  notice: "{title} (c) {year} {rights_holder}."
  rights: "Licensed under CC BY-SA 4.0, with attribution."
  extra: ["Printed in the United Kingdom."]
  # or, for a publisher who sets their own:
  blank: true

pages:
  half_title: false          # drops the opening leaf, so copyright lands on p2
  chapters_start_on: recto   # every chapter opens on a right-hand page
```

Emptying a paragraph omits it, so a Creative Commons book need not print
"All rights reserved". `blank: true` leaves the page present but empty — the
leaf still prints, so no page numbers shift. `recto` starts insert blank
versos where needed, and those carry no folio.

All of it is editable from Studio's **Book details**, with a live preview of
the finished copyright page.

## Callout boxes

```markdown
::: takeaways
- First key takeaway
:::
```

Pandoc's native fenced-div syntax — nothing BookForge invented. Available
kinds: `example`, `best`, `warning`, `tip`, `takeaways`, `note`,
`exercise`, `resources` — rendered consistently in both the PDF and the
EPUB from a single source of truth (`bookforge/callouts.py`).

Labels are per-book. Add a `callouts:` block to `book.yaml` to rename any
of them:

```yaml
callouts:
  warning: "WATCH OUT"
  exercise: "TRY IT YOURSELF"
```

## Diagrams

```markdown
{{DIAGRAM: my-diagram | A Diagram Title | What the diagram shows}}
```

resolves to `assets/diagrams/my-diagram.svg` (PDF) or the rasterized
`.png` (EPUB), degrading to an italic "diagram pending" note if the asset
doesn't exist yet. Placeholders inside code fences are left verbatim, so a
book can document the syntax. Generate diagrams with the
`bookforge.diagrams` DSL (`flow`, `vflow`, `cycle`) — see
`examples/sample-book/assets/diagrams/gen_diagrams.py`.

---

## Engine

[pandoc](https://pandoc.org) (markdown → HTML5 / EPUB3) +
[WeasyPrint](https://weasyprint.org) (HTML/CSS → PDF), both called for
every book from the same shared `bookforge` package — one templating
language for the whole pipeline, no separate raster-graphics step for
covers. PDF→image conversion uses
[pypdfium2](https://github.com/pypdfium2-team/pypdfium2), which ships
prebuilt wheels for macOS, Linux, and Windows.

## Full command reference

```
bookforge new <path> [--title T] [--author A]
bookforge build pdf|epub|all    [--config book.yaml] [--no-epubcheck]
bookforge covers                [--config book.yaml] [--pages N]
bookforge diagrams render <dir>
bookforge package               [--config book.yaml]
bookforge verify                [--config book.yaml]
bookforge watch [--target pdf]  [--config book.yaml]
bookforge studio [path]         [--port 8000]   # needs bookforge-kdp[studio]
bookforge --version
```

---

## Developing BookForge itself

```bash
git clone https://github.com/pushkar-mishra/BookForge
cd BookForge
python3 -m venv .venv
.venv/bin/pip install -e ".[studio,dev]"
.venv/bin/python -m pytest        # 141 tests, ~1.3s, no system binaries needed
```

Editable mode means changes to `src/bookforge/**` take effect immediately
— no rebuild step, just rerun `bookforge ...`.

To build a distributable package:

```bash
.venv/bin/python -m build         # writes dist/bookforge_kdp-*.whl and *.tar.gz
.venv/bin/twine check dist/*
```

The version is declared once, in `src/bookforge/__init__.py`, and read
from there by `pyproject.toml`.

`templates/*.css` and `scaffold/**/*` are declared as package data, so
they're included automatically in both the editable install and the built
wheel. (One exception worth knowing: dotfiles like `scaffold/.gitignore`
don't survive glob-based package-data patterns and have to be listed
explicitly — see
[`PUBLISHING.md`](https://github.com/pushkar-mishra/BookForge/blob/main/PUBLISHING.md)
for why.)

**Publishing a release to PyPI** (as `bookforge-kdp` — `bookforge` was
already taken): the full runbook is in
[`PUBLISHING.md`](https://github.com/pushkar-mishra/BookForge/blob/main/PUBLISHING.md).

---

## Get to know the author

<img src="https://raw.githubusercontent.com/pushkar-mishra/BookForge/main/examples/sample-book/assets/author/author-photo.png" alt="Pushkar Mishra" width="120" align="left" style="margin-right: 16px;"/>

**Pushkar Mishra** is a technology leader with 20+ years across
engineering, architecture, and product leadership. He built BookForge to
stop hand-rolling a new build system for every book, then wrote *the
book on BookForge* using nothing but BookForge itself — proof, not just
documentation.

<br clear="left"/>
