bookforge-kdp 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- bookforge_kdp-0.2.0/LICENSE +21 -0
- bookforge_kdp-0.2.0/PKG-INFO +509 -0
- bookforge_kdp-0.2.0/README.md +445 -0
- bookforge_kdp-0.2.0/pyproject.toml +82 -0
- bookforge_kdp-0.2.0/setup.cfg +4 -0
- bookforge_kdp-0.2.0/src/bookforge/__init__.py +9 -0
- bookforge_kdp-0.2.0/src/bookforge/assemble.py +302 -0
- bookforge_kdp-0.2.0/src/bookforge/callouts.py +121 -0
- bookforge_kdp-0.2.0/src/bookforge/cli.py +182 -0
- bookforge_kdp-0.2.0/src/bookforge/config.py +474 -0
- bookforge_kdp-0.2.0/src/bookforge/covers.py +410 -0
- bookforge_kdp-0.2.0/src/bookforge/deps.py +35 -0
- bookforge_kdp-0.2.0/src/bookforge/diagrams.py +342 -0
- bookforge_kdp-0.2.0/src/bookforge/epub.py +80 -0
- bookforge_kdp-0.2.0/src/bookforge/errors.py +23 -0
- bookforge_kdp-0.2.0/src/bookforge/package.py +139 -0
- bookforge_kdp-0.2.0/src/bookforge/pdf.py +143 -0
- bookforge_kdp-0.2.0/src/bookforge/raster.py +88 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/.gitignore +3 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/assets/README.md +16 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/assets/author/README.md +2 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/assets/cover/README.md +3 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/assets/diagrams/README.md +4 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/book.yaml +63 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/build.bat +84 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/build.sh +65 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/content/back/about-notes.md +6 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/content/chapters/ch01-first-chapter.md +27 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/content/chapters/ch02-second-chapter.md +5 -0
- bookforge_kdp-0.2.0/src/bookforge/scaffold/content/front/preface.md +5 -0
- bookforge_kdp-0.2.0/src/bookforge/studio/__init__.py +56 -0
- bookforge_kdp-0.2.0/src/bookforge/studio/app.py +1114 -0
- bookforge_kdp-0.2.0/src/bookforge/studio/static/app.js +964 -0
- bookforge_kdp-0.2.0/src/bookforge/studio/static/index.html +390 -0
- bookforge_kdp-0.2.0/src/bookforge/studio/static/style.css +650 -0
- bookforge_kdp-0.2.0/src/bookforge/templates/epub.css +82 -0
- bookforge_kdp-0.2.0/src/bookforge/templates/interior.css +345 -0
- bookforge_kdp-0.2.0/src/bookforge/typography.py +33 -0
- bookforge_kdp-0.2.0/src/bookforge/verify.py +184 -0
- bookforge_kdp-0.2.0/src/bookforge/watch.py +74 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/PKG-INFO +509 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/SOURCES.txt +50 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/dependency_links.txt +1 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/entry_points.txt +2 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/requires.txt +17 -0
- bookforge_kdp-0.2.0/src/bookforge_kdp.egg-info/top_level.txt +1 -0
- bookforge_kdp-0.2.0/tests/test_assemble.py +154 -0
- bookforge_kdp-0.2.0/tests/test_config.py +264 -0
- bookforge_kdp-0.2.0/tests/test_covers_and_toc.py +201 -0
- bookforge_kdp-0.2.0/tests/test_studio_api.py +374 -0
- bookforge_kdp-0.2.0/tests/test_studio_packaging.py +114 -0
- bookforge_kdp-0.2.0/tests/test_studio_picker.py +153 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Pushkar Mishra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: bookforge-kdp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
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.
|
|
5
|
+
Author: Pushkar Mishra
|
|
6
|
+
License: MIT License
|
|
7
|
+
|
|
8
|
+
Copyright (c) 2026 Pushkar Mishra
|
|
9
|
+
|
|
10
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
11
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
12
|
+
in the Software without restriction, including without limitation the rights
|
|
13
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
14
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
15
|
+
furnished to do so, subject to the following conditions:
|
|
16
|
+
|
|
17
|
+
The above copyright notice and this permission notice shall be included in all
|
|
18
|
+
copies or substantial portions of the Software.
|
|
19
|
+
|
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
21
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
22
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
23
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
24
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
25
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
26
|
+
SOFTWARE.
|
|
27
|
+
|
|
28
|
+
Project-URL: Homepage, https://github.com/pushkar-mishra/BookForge
|
|
29
|
+
Project-URL: Repository, https://github.com/pushkar-mishra/BookForge
|
|
30
|
+
Project-URL: Issues, https://github.com/pushkar-mishra/BookForge/issues
|
|
31
|
+
Keywords: kdp,epub,epub3,self-publishing,amazon-kdp,pandoc,book,publishing,pdf
|
|
32
|
+
Classifier: Development Status :: 4 - Beta
|
|
33
|
+
Classifier: Environment :: Console
|
|
34
|
+
Classifier: Intended Audience :: Other Audience
|
|
35
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
36
|
+
Classifier: Operating System :: OS Independent
|
|
37
|
+
Classifier: Programming Language :: Python :: 3
|
|
38
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
39
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
40
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
42
|
+
Classifier: Topic :: Text Processing :: Markup :: Markdown
|
|
43
|
+
Classifier: Topic :: Text Processing :: Markup :: reStructuredText
|
|
44
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
45
|
+
Requires-Python: >=3.10
|
|
46
|
+
Description-Content-Type: text/markdown
|
|
47
|
+
License-File: LICENSE
|
|
48
|
+
Requires-Dist: pyyaml>=6.0
|
|
49
|
+
Requires-Dist: pypdf>=4.0
|
|
50
|
+
Requires-Dist: weasyprint>=61.0
|
|
51
|
+
Requires-Dist: pillow>=10.0
|
|
52
|
+
Requires-Dist: pypdfium2>=4.25
|
|
53
|
+
Provides-Extra: studio
|
|
54
|
+
Requires-Dist: fastapi>=0.110; extra == "studio"
|
|
55
|
+
Requires-Dist: uvicorn>=0.27; extra == "studio"
|
|
56
|
+
Requires-Dist: ruamel.yaml>=0.18; extra == "studio"
|
|
57
|
+
Requires-Dist: python-multipart>=0.0.9; extra == "studio"
|
|
58
|
+
Provides-Extra: dev
|
|
59
|
+
Requires-Dist: build>=1.0; extra == "dev"
|
|
60
|
+
Requires-Dist: twine>=5.0; extra == "dev"
|
|
61
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
62
|
+
Requires-Dist: httpx2>=0.1; extra == "dev"
|
|
63
|
+
Dynamic: license-file
|
|
64
|
+
|
|
65
|
+
<h1 align="center">BookForge</h1>
|
|
66
|
+
|
|
67
|
+
<p align="center">
|
|
68
|
+
<em>A book.yaml file and a folder of markdown in — a KDP-ready paperback, EPUB, and covers out.</em>
|
|
69
|
+
</p>
|
|
70
|
+
|
|
71
|
+
<p align="center">
|
|
72
|
+
<a href="https://pypi.org/project/bookforge-kdp/"><img alt="PyPI" src="https://img.shields.io/badge/pip%20install-book--forge-3b5bdb"></a>
|
|
73
|
+
<img alt="Python" src="https://img.shields.io/badge/python-3.10%2B-3b5bdb">
|
|
74
|
+
<img alt="Engine" src="https://img.shields.io/badge/engine-pandoc%20%2B%20weasyprint-1971c2">
|
|
75
|
+
<img alt="QA" src="https://img.shields.io/badge/verify-6%20automated%20checks-2f9e44">
|
|
76
|
+
<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>
|
|
77
|
+
<img alt="Tests" src="https://img.shields.io/badge/tests-141%20passing-2f9e44">
|
|
78
|
+
<img alt="Self-built" src="https://img.shields.io/badge/self--built%20guide-130pp%20%C2%B7%200%20epubcheck%20errors-2f9e44">
|
|
79
|
+
<img alt="API keys" src="https://img.shields.io/badge/API%20keys-none%20required-2f9e44">
|
|
80
|
+
<img alt="Platforms" src="https://img.shields.io/badge/platforms-macOS%20%C2%B7%20Linux%20%C2%B7%20Windows-868e96">
|
|
81
|
+
<a href="https://github.com/pushkar-mishra/BookForge/blob/main/LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-868e96"></a>
|
|
82
|
+
</p>
|
|
83
|
+
|
|
84
|
+
<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>
|
|
85
|
+
|
|
86
|
+
BookForge is the shared build pipeline left over after six independent
|
|
87
|
+
nonfiction book projects each hand-rolled their own scripts to solve the
|
|
88
|
+
same problem. Point it at a `book.yaml` file and a `content/` folder of
|
|
89
|
+
markdown chapters and it produces the same four deliverables every KDP
|
|
90
|
+
paperback + Kindle listing needs — with **no per-book fork of any build
|
|
91
|
+
script**.
|
|
92
|
+
|
|
93
|
+
**Repo:** https://github.com/pushkar-mishra/BookForge ·
|
|
94
|
+
**License:** MIT · **PyPI:** `pip install bookforge-kdp`
|
|
95
|
+
|
|
96
|
+
> **This repo is the pipeline. `examples/sample-book/` is the manual.**
|
|
97
|
+
> It's a complete, real 130-page book — *BookForge: The Step-by-Step
|
|
98
|
+
> Guide to Publishing Your Book on Amazon KDP* — built entirely by the
|
|
99
|
+
> tool it documents, from nothing but its own `book.yaml` and markdown.
|
|
100
|
+
> See [The Book](#the-book) below.
|
|
101
|
+
|
|
102
|
+
<br clear="right"/>
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## What you get
|
|
107
|
+
|
|
108
|
+
- **A 6x9in interior PDF** — mirrored margins, running page numbers, a
|
|
109
|
+
generated table of contents, half-title/title/copyright/About-the-Author
|
|
110
|
+
pages auto-generated from `book.yaml`
|
|
111
|
+
- **A validated EPUB3** — same source content, no embedded cover (KDP
|
|
112
|
+
supplies its own), passes `epubcheck` as part of the build, not after
|
|
113
|
+
- **A paperback wrap cover** — back + spine + front in one bleed PDF, spine
|
|
114
|
+
width computed automatically from the interior's actual page count
|
|
115
|
+
- **A Kindle front cover** — a separate JPG at the exact 1800×2700px KDP
|
|
116
|
+
expects
|
|
117
|
+
- **A ready-to-upload `amazon-kdp/` folder** — the four files above plus a
|
|
118
|
+
generated README, checklist, and listing metadata, all rendered straight
|
|
119
|
+
from `book.yaml` so nothing in it can drift out of sync
|
|
120
|
+
|
|
121
|
+
Everything runs **fully local** — no LLM calls, no API keys, no network
|
|
122
|
+
dependency once `pandoc` and `epubcheck` are installed.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Two ways to use it
|
|
127
|
+
|
|
128
|
+
Both are fully supported, both read and write the same `book.yaml` and
|
|
129
|
+
`content/*.md`, and you can switch between them at any point — write a chapter
|
|
130
|
+
in the UI, build it from the terminal, or the reverse.
|
|
131
|
+
|
|
132
|
+
<table>
|
|
133
|
+
<tr>
|
|
134
|
+
<th align="left">Command line</th>
|
|
135
|
+
<th align="left">BookForge Studio (UI)</th>
|
|
136
|
+
</tr>
|
|
137
|
+
<tr valign="top">
|
|
138
|
+
<td>
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
pip install bookforge-kdp
|
|
142
|
+
|
|
143
|
+
bookforge new ~/Books/my-book
|
|
144
|
+
cd ~/Books/my-book
|
|
145
|
+
./build.sh
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Scriptable, CI-friendly, no web stack.
|
|
149
|
+
|
|
150
|
+
</td>
|
|
151
|
+
<td>
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
pip install "bookforge-kdp[studio]"
|
|
155
|
+
|
|
156
|
+
bookforge studio
|
|
157
|
+
# → http://127.0.0.1:8000
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Write, press **Build book**, see the covers.
|
|
161
|
+
|
|
162
|
+
</td>
|
|
163
|
+
</tr>
|
|
164
|
+
</table>
|
|
165
|
+
|
|
166
|
+
Prerequisites are the same for both: **Python 3.10+**, plus `pandoc` and
|
|
167
|
+
`epubcheck` on `PATH` (`brew install pandoc epubcheck`, or `apt install pandoc
|
|
168
|
+
epubcheck`). `bookforge` checks for both at build time and prints an install
|
|
169
|
+
hint if either is missing.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Quickstart — command line
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
python3 -m venv .venv
|
|
177
|
+
.venv/bin/pip install bookforge-kdp
|
|
178
|
+
source .venv/bin/activate # puts `bookforge` on PATH for this shell
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
> Skipped `source .venv/bin/activate`? Every command below still works if
|
|
182
|
+
> you spell out the full path instead, e.g. `.venv/bin/bookforge new ...`.
|
|
183
|
+
|
|
184
|
+
```bash
|
|
185
|
+
bookforge new ~/Books/my-new-book --title "My Book" --author "Author Name"
|
|
186
|
+
cd ~/Books/my-new-book
|
|
187
|
+
# edit book.yaml and content/, then either:
|
|
188
|
+
./build.sh # or build.bat on Windows -- runs the full pipeline
|
|
189
|
+
# ...or run each stage yourself:
|
|
190
|
+
bookforge build all # dist/interior.pdf + dist/{slug}.epub
|
|
191
|
+
bookforge covers # dist/cover-paperback.pdf + dist/cover-kindle.jpg
|
|
192
|
+
bookforge verify # QA checks — page count, spine math, epubcheck, ...
|
|
193
|
+
bookforge package # assembles amazon-kdp/ for upload
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
While drafting, run `bookforge watch` (or `./build.sh watch`) in its own
|
|
197
|
+
terminal: it rebuilds on every save to `book.yaml`, `content/`, or
|
|
198
|
+
`assets/`, and a bad edit prints a clean error without killing the loop.
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Quickstart — BookForge Studio
|
|
203
|
+
|
|
204
|
+
Prefer a window to a terminal? Studio is a small local app that does the same
|
|
205
|
+
work: create chapters, write them, press **Build book**. It writes the same
|
|
206
|
+
files the commands do, so you can switch between the two freely.
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
pip install "bookforge-kdp[studio]"
|
|
210
|
+
bookforge studio # or: bookforge studio path/to/book
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Then open <http://127.0.0.1:8000>. No account, no sign-in, nothing leaves
|
|
214
|
+
your machine — it binds to `127.0.0.1` only.
|
|
215
|
+
|
|
216
|
+
The UI is an **optional extra**: a plain `pip install bookforge-kdp` stays a CLI
|
|
217
|
+
with no web stack, and `bookforge studio` then tells you exactly what to
|
|
218
|
+
install rather than failing obscurely.
|
|
219
|
+
|
|
220
|
+
- **Landing screen** — start a new book, or open one. **Browse…** opens the
|
|
221
|
+
system's native folder dialog (the server opens it, since a browser can't
|
|
222
|
+
hand a page a real path), and books you've opened before are listed.
|
|
223
|
+
- **Chapters** — the sidebar *is* your table of contents. Adding a chapter
|
|
224
|
+
writes the markdown file **and** registers it in `book.yaml`; removing one
|
|
225
|
+
unlists it and leaves your words on disk.
|
|
226
|
+
- **Book details** — title, author, subtitle, biography, tagline, ISBN, plus
|
|
227
|
+
author-photo and cover-art upload, as a plain form. You never see YAML,
|
|
228
|
+
and `book.yaml` is edited in place with your comments intact.
|
|
229
|
+
- **Build book** — the full pipeline, with the six `verify` checks reported
|
|
230
|
+
in plain language ("Cover fits the interior").
|
|
231
|
+
|
|
232
|
+
Studio ships inside the package but behind the extra, so the two can never
|
|
233
|
+
disagree about internal APIs it uses (`book_outline()`, `verify_build()`).
|
|
234
|
+
See [`docs/STUDIO.md`](https://github.com/pushkar-mishra/BookForge/blob/main/docs/STUDIO.md), or Appendix D of the book.
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## The book
|
|
239
|
+
|
|
240
|
+
*BookForge: The Step-by-Step Guide to Publishing Your Book on Amazon
|
|
241
|
+
KDP* — a complete 130-page manual, written and built entirely by
|
|
242
|
+
BookForge itself, source in
|
|
243
|
+
[`examples/sample-book/`](https://github.com/pushkar-mishra/BookForge/tree/main/examples/sample-book):
|
|
244
|
+
|
|
245
|
+
<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>
|
|
246
|
+
|
|
247
|
+
| Part | Chapters |
|
|
248
|
+
|---|---|
|
|
249
|
+
| I. Before You Write | Why a Book Needs a Build Pipeline · Installing BookForge · Your First Project · The Config File |
|
|
250
|
+
| II. Writing Your Content | Where Content Goes · Parts, Chapters, and Numbering · Callouts and Diagrams |
|
|
251
|
+
| III. Building the Three Deliverables | The Interior PDF · The EPUB · The Covers |
|
|
252
|
+
| IV. Shipping to KDP | Verify · Package · Publishing to KDP · After You Publish |
|
|
253
|
+
| Appendices | The book.yaml Reference · Troubleshooting · Command Reference · BookForge Studio · Glossary |
|
|
254
|
+
|
|
255
|
+
Build it yourself:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
git clone https://github.com/pushkar-mishra/BookForge
|
|
259
|
+
cd BookForge && python3 -m venv .venv && .venv/bin/pip install -e .
|
|
260
|
+
source .venv/bin/activate
|
|
261
|
+
cd examples/sample-book
|
|
262
|
+
python3 assets/diagrams/gen_diagrams.py # generate the seven figures
|
|
263
|
+
./build.sh # interior, EPUB, covers, verify, package
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
---
|
|
267
|
+
|
|
268
|
+
## Pipeline stages
|
|
269
|
+
|
|
270
|
+
| Command | Produces | Notes |
|
|
271
|
+
|---|---|---|
|
|
272
|
+
| `bookforge new` | a scaffolded project | `book.yaml` + starter `content/` + `assets/` + `build.sh`/`build.bat` |
|
|
273
|
+
| `bookforge build pdf\|epub\|all` | `dist/interior.pdf`, `dist/{slug}.epub` | EPUB fails the build on any `epubcheck` error |
|
|
274
|
+
| `bookforge covers` | `dist/cover-paperback.pdf`, `dist/cover-kindle.jpg` | spine width derived from the interior's page count |
|
|
275
|
+
| `bookforge diagrams render <dir>` | `*.png` next to each `*.svg` | rasterizes `bookforge.diagrams` DSL output for EPUB |
|
|
276
|
+
| `bookforge verify` | a pass/fail QA report | see [Verify](#verify) below |
|
|
277
|
+
| `bookforge package` | `amazon-kdp/` | copies build outputs + renders README/checklist/metadata |
|
|
278
|
+
| `bookforge watch` | continuous rebuilds | polls `book.yaml`, `content/`, `assets/` for changes |
|
|
279
|
+
| `bookforge studio` | the local web UI | optional extra: `pip install "bookforge-kdp[studio]"` |
|
|
280
|
+
|
|
281
|
+
Every new book also gets `build.sh` / `build.bat`, a thin wrapper around
|
|
282
|
+
the same commands: `./build.sh` (no args) runs `diagrams → build all →
|
|
283
|
+
covers → verify → package` in order and **stops at the first failure**
|
|
284
|
+
(e.g. a failing `verify` blocks `package` from ever running), or run one
|
|
285
|
+
stage at a time with `./build.sh pdf|epub|covers|diagrams|verify|package|watch`.
|
|
286
|
+
|
|
287
|
+
Every command re-reads `book.yaml` and re-globs `content/` on each
|
|
288
|
+
invocation — edit config or markdown, rerun (or leave `watch` running),
|
|
289
|
+
and the output always reflects current source.
|
|
290
|
+
|
|
291
|
+
---
|
|
292
|
+
|
|
293
|
+
## Verify
|
|
294
|
+
|
|
295
|
+
`bookforge verify` runs six checks against the current build, each one a
|
|
296
|
+
real KDP rejection reason turned into an automated gate instead of a
|
|
297
|
+
manual pre-upload ritual:
|
|
298
|
+
|
|
299
|
+
| Check | Fails when |
|
|
300
|
+
|---|---|
|
|
301
|
+
| `page_count_minimum` | interior is under KDP's paperback minimum (`kdp.min_pages`, default 24) |
|
|
302
|
+
| `spine_math_matches_cover` | the cover PDF's width doesn't match the spine width for the current page count |
|
|
303
|
+
| `epubcheck_zero_errors` | `epubcheck` reports any error on the built EPUB |
|
|
304
|
+
| `kindle_pixel_dims` | the Kindle cover isn't exactly 1800×2700px |
|
|
305
|
+
| `no_placeholder_text` | any chapter still contains draft markers |
|
|
306
|
+
| `chapter_frontmatter_complete` | a chapter referenced in `book.yaml` is missing or has no `title:` |
|
|
307
|
+
|
|
308
|
+
`verify` exits non-zero if any check fails, so it's safe to wire into CI.
|
|
309
|
+
Every failure also prints a `Recommendation:` line with the concrete next
|
|
310
|
+
step, not just the diagnosis:
|
|
311
|
+
|
|
312
|
+
```
|
|
313
|
+
[FAIL] page_count_minimum: 10 pages (minimum 24)
|
|
314
|
+
...
|
|
315
|
+
Recommendation:
|
|
316
|
+
- page_count_minimum: add 14 more page(s) of content (new chapters, or
|
|
317
|
+
longer existing ones) and rebuild, or lower kdp.min_pages in book.yaml
|
|
318
|
+
if this isn't going to KDP paperback
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
---
|
|
322
|
+
|
|
323
|
+
## Repository layout
|
|
324
|
+
|
|
325
|
+
```
|
|
326
|
+
src/bookforge/
|
|
327
|
+
config.py book.yaml schema — structure (parts -> chapters), metadata, palette, trim
|
|
328
|
+
assemble.py content/*.md + book.yaml -> one pandoc-ready markdown string
|
|
329
|
+
pdf.py assemble -> pandoc html5 -> WeasyPrint -> pypdf page count
|
|
330
|
+
epub.py assemble -> pandoc epub3 -> epubcheck
|
|
331
|
+
covers.py paperback wrap + Kindle cover, same WeasyPrint toolchain as pdf.py
|
|
332
|
+
callouts.py the 8 callout kinds (label + accent color + tint), shared by PDF and EPUB
|
|
333
|
+
diagrams.py SVG diagram primitives + a declarative DSL (flow / vflow / cycle)
|
|
334
|
+
raster.py PDF -> PNG/JPG via pypdfium2 (no system binary, all platforms)
|
|
335
|
+
verify.py the six QA checks above
|
|
336
|
+
package.py assembles amazon-kdp/ from dist/ + renders README/checklist/metadata
|
|
337
|
+
watch.py mtime-polling edit -> rebuild loop, no watchdog dependency
|
|
338
|
+
deps.py checks pandoc/epubcheck are on PATH, prints an install hint if not
|
|
339
|
+
errors.py BookForgeError hierarchy — user-causable failures print cleanly
|
|
340
|
+
cli.py argparse entry point wiring all of the above to `bookforge <command>`
|
|
341
|
+
templates/ interior.css, epub.css
|
|
342
|
+
scaffold/ the project `bookforge new` copies (including build.sh / build.bat)
|
|
343
|
+
tests/ 141 tests, no system binaries required
|
|
344
|
+
studio/ the optional local UI (FastAPI + vanilla JS), shipped
|
|
345
|
+
behind the `studio` extra so a plain install stays a CLI
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Book project layout
|
|
349
|
+
|
|
350
|
+
```
|
|
351
|
+
mybook/
|
|
352
|
+
book.yaml # title, author, palette, trim size, table of contents
|
|
353
|
+
build.sh, build.bat # run the whole pipeline, or one stage at a time
|
|
354
|
+
content/
|
|
355
|
+
front/ # dedication.md, preface.md -- listed in book.yaml front_matter
|
|
356
|
+
chapters/ # ch01-slug.md, ... -- referenced from parts[].chapters
|
|
357
|
+
back/ # glossary.md, appendices -- listed in book.yaml back_matter
|
|
358
|
+
assets/
|
|
359
|
+
author/author-photo.png
|
|
360
|
+
cover/cover-art.png # optional; an auto-generated mark is used if absent
|
|
361
|
+
diagrams/ # *.svg sources (bookforge.diagrams DSL) + generated *.png
|
|
362
|
+
dist/ # gitignored -- build output
|
|
363
|
+
amazon-kdp/ # gitignored -- `bookforge package` output
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
Half-title, title page, copyright page, table of contents, and the "About
|
|
367
|
+
the Author" page are always auto-generated from `book.yaml`. Everything
|
|
368
|
+
else is an ordinary markdown file listed in `front_matter`/`back_matter`,
|
|
369
|
+
or a chapter referenced from a `parts[].chapters` list.
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## Front matter and the copyright page
|
|
374
|
+
|
|
375
|
+
Title, copyright, contents, and About-the-Author pages are generated from
|
|
376
|
+
`book.yaml` — but the wording and the page conventions are yours:
|
|
377
|
+
|
|
378
|
+
```yaml
|
|
379
|
+
copyright:
|
|
380
|
+
notice: "{title} (c) {year} {rights_holder}."
|
|
381
|
+
rights: "Licensed under CC BY-SA 4.0, with attribution."
|
|
382
|
+
extra: ["Printed in the United Kingdom."]
|
|
383
|
+
# or, for a publisher who sets their own:
|
|
384
|
+
blank: true
|
|
385
|
+
|
|
386
|
+
pages:
|
|
387
|
+
half_title: false # drops the opening leaf, so copyright lands on p2
|
|
388
|
+
chapters_start_on: recto # every chapter opens on a right-hand page
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
Emptying a paragraph omits it, so a Creative Commons book need not print
|
|
392
|
+
"All rights reserved". `blank: true` leaves the page present but empty — the
|
|
393
|
+
leaf still prints, so no page numbers shift. `recto` starts insert blank
|
|
394
|
+
versos where needed, and those carry no folio.
|
|
395
|
+
|
|
396
|
+
All of it is editable from Studio's **Book details**, with a live preview of
|
|
397
|
+
the finished copyright page.
|
|
398
|
+
|
|
399
|
+
## Callout boxes
|
|
400
|
+
|
|
401
|
+
```markdown
|
|
402
|
+
::: takeaways
|
|
403
|
+
- First key takeaway
|
|
404
|
+
:::
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
Pandoc's native fenced-div syntax — nothing BookForge invented. Available
|
|
408
|
+
kinds: `example`, `best`, `warning`, `tip`, `takeaways`, `note`,
|
|
409
|
+
`exercise`, `resources` — rendered consistently in both the PDF and the
|
|
410
|
+
EPUB from a single source of truth (`bookforge/callouts.py`).
|
|
411
|
+
|
|
412
|
+
Labels are per-book. Add a `callouts:` block to `book.yaml` to rename any
|
|
413
|
+
of them:
|
|
414
|
+
|
|
415
|
+
```yaml
|
|
416
|
+
callouts:
|
|
417
|
+
warning: "WATCH OUT"
|
|
418
|
+
exercise: "TRY IT YOURSELF"
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
## Diagrams
|
|
422
|
+
|
|
423
|
+
```markdown
|
|
424
|
+
{{DIAGRAM: my-diagram | A Diagram Title | What the diagram shows}}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
resolves to `assets/diagrams/my-diagram.svg` (PDF) or the rasterized
|
|
428
|
+
`.png` (EPUB), degrading to an italic "diagram pending" note if the asset
|
|
429
|
+
doesn't exist yet. Placeholders inside code fences are left verbatim, so a
|
|
430
|
+
book can document the syntax. Generate diagrams with the
|
|
431
|
+
`bookforge.diagrams` DSL (`flow`, `vflow`, `cycle`) — see
|
|
432
|
+
`examples/sample-book/assets/diagrams/gen_diagrams.py`.
|
|
433
|
+
|
|
434
|
+
---
|
|
435
|
+
|
|
436
|
+
## Engine
|
|
437
|
+
|
|
438
|
+
[pandoc](https://pandoc.org) (markdown → HTML5 / EPUB3) +
|
|
439
|
+
[WeasyPrint](https://weasyprint.org) (HTML/CSS → PDF), both called for
|
|
440
|
+
every book from the same shared `bookforge` package — one templating
|
|
441
|
+
language for the whole pipeline, no separate raster-graphics step for
|
|
442
|
+
covers. PDF→image conversion uses
|
|
443
|
+
[pypdfium2](https://github.com/pypdfium2-team/pypdfium2), which ships
|
|
444
|
+
prebuilt wheels for macOS, Linux, and Windows.
|
|
445
|
+
|
|
446
|
+
## Full command reference
|
|
447
|
+
|
|
448
|
+
```
|
|
449
|
+
bookforge new <path> [--title T] [--author A]
|
|
450
|
+
bookforge build pdf|epub|all [--config book.yaml] [--no-epubcheck]
|
|
451
|
+
bookforge covers [--config book.yaml] [--pages N]
|
|
452
|
+
bookforge diagrams render <dir>
|
|
453
|
+
bookforge package [--config book.yaml]
|
|
454
|
+
bookforge verify [--config book.yaml]
|
|
455
|
+
bookforge watch [--target pdf] [--config book.yaml]
|
|
456
|
+
bookforge studio [path] [--port 8000] # needs bookforge-kdp[studio]
|
|
457
|
+
bookforge --version
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## Developing BookForge itself
|
|
463
|
+
|
|
464
|
+
```bash
|
|
465
|
+
git clone https://github.com/pushkar-mishra/BookForge
|
|
466
|
+
cd BookForge
|
|
467
|
+
python3 -m venv .venv
|
|
468
|
+
.venv/bin/pip install -e ".[studio,dev]"
|
|
469
|
+
.venv/bin/python -m pytest # 141 tests, ~1.3s, no system binaries needed
|
|
470
|
+
```
|
|
471
|
+
|
|
472
|
+
Editable mode means changes to `src/bookforge/**` take effect immediately
|
|
473
|
+
— no rebuild step, just rerun `bookforge ...`.
|
|
474
|
+
|
|
475
|
+
To build a distributable package:
|
|
476
|
+
|
|
477
|
+
```bash
|
|
478
|
+
.venv/bin/python -m build # writes dist/bookforge_kdp-*.whl and *.tar.gz
|
|
479
|
+
.venv/bin/twine check dist/*
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
The version is declared once, in `src/bookforge/__init__.py`, and read
|
|
483
|
+
from there by `pyproject.toml`.
|
|
484
|
+
|
|
485
|
+
`templates/*.css` and `scaffold/**/*` are declared as package data, so
|
|
486
|
+
they're included automatically in both the editable install and the built
|
|
487
|
+
wheel. (One exception worth knowing: dotfiles like `scaffold/.gitignore`
|
|
488
|
+
don't survive glob-based package-data patterns and have to be listed
|
|
489
|
+
explicitly — see
|
|
490
|
+
[`PUBLISHING.md`](https://github.com/pushkar-mishra/BookForge/blob/main/PUBLISHING.md)
|
|
491
|
+
for why.)
|
|
492
|
+
|
|
493
|
+
**Publishing a release to PyPI** (as `bookforge-kdp` — `bookforge` was
|
|
494
|
+
already taken): the full runbook is in
|
|
495
|
+
[`PUBLISHING.md`](https://github.com/pushkar-mishra/BookForge/blob/main/PUBLISHING.md).
|
|
496
|
+
|
|
497
|
+
---
|
|
498
|
+
|
|
499
|
+
## Get to know the author
|
|
500
|
+
|
|
501
|
+
<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;"/>
|
|
502
|
+
|
|
503
|
+
**Pushkar Mishra** is a technology leader with 20+ years across
|
|
504
|
+
engineering, architecture, and product leadership. He built BookForge to
|
|
505
|
+
stop hand-rolling a new build system for every book, then wrote *the
|
|
506
|
+
book on BookForge* using nothing but BookForge itself — proof, not just
|
|
507
|
+
documentation.
|
|
508
|
+
|
|
509
|
+
<br clear="left"/>
|