Four to six hours is the realistic window to go from a topic outline to a live KDP listing, using a Python pipeline. Here is the exact breakdown.
The Timeline
| Hour | Work |
|---|---|
| 0:00–0:30 | Outline, niche validation, KDP keyword research |
| 0:30–1:30 | Run generation pipeline (Claude API, 10 chapters) |
| 1:30–2:00 | Review and fix validation errors |
| 2:00–2:30 | Compile EPUB, check in Calibre |
| 2:30–3:30 | Cover design (Canva or automated) |
| 3:30–4:30 | KDP dashboard: metadata, categories, pricing |
| 4:30–5:00 | Gumroad listing (parallel distribution) |
| 5:00–6:00 | Buffer for re-uploads, preview errors, fixes |
The generation and compilation steps are automated. You spend your time on judgment calls: is the outline good, is the cover clear, are the chapter titles searchable.
Step 1: Outline Generation
import anthropic
def generate_outline(topic: str, target_pages: int = 80) -> str:
client = anthropic.Anthropic()
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=1024,
messages=[{
"role": "user",
"content": (
f"Create a detailed outline for a {target_pages}-page technical ebook "
f"on: {topic}\n\n"
"Format: numbered chapters with 3-5 bullet sub-topics each. "
"Target audience: working developers. "
"Include practical code examples in every chapter."
)
}]
)
return response.content[0].text
outline = generate_outline("FastAPI production deployment on AWS")
print(outline)
Spend 15 minutes reviewing the outline before running generation. Fixing the outline is free. Regenerating 10 chapters because the structure was wrong costs time and API credits.
Step 2: Chapter Generation with Checkpointing
import json
from pathlib import Path
CHECKPOINT = Path("checkpoint.json")
def load_checkpoint() -> dict:
if CHECKPOINT.exists():
return json.loads(CHECKPOINT.read_text())
return {}
def save_checkpoint(data: dict):
CHECKPOINT.write_text(json.dumps(data, indent=2))
def generate_chapters(client, chapters: list[dict]) -> Path:
out_dir = Path("chapters")
out_dir.mkdir(exist_ok=True)
checkpoint = load_checkpoint()
for ch in chapters:
slug = ch["slug"]
if slug in checkpoint:
print(f" Skip (cached): {slug}")
continue
print(f" Generating: {ch['title']}")
msg = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=4096,
messages=[{
"role": "user",
"content": (
f"Write chapter '{ch['title']}' for a technical ebook.\n"
f"Topics: {', '.join(ch['topics'])}\n"
"Requirements: ~1200 words, working Python examples, no filler."
)
}]
)
content = msg.content[0].text
path = out_dir / f"{slug}.md"
path.write_text(content)
checkpoint[slug] = str(path)
save_checkpoint(checkpoint)
return out_dir
Step 3: EPUB Compilation for KDP
KDP has specific requirements that trip up first-time publishers:
- EPUB 3.0 or higher
- No DRM-incompatible fonts embedded without license
- Cover image: exactly 2560 x 1600 px (or 1:1.6 ratio)
- File size: under 650 MB (rarely an issue for text books)
- No JavaScript in EPUB content
import subprocess
from pathlib import Path
def compile_epub(
chapters_dir: Path,
output: Path,
title: str,
author: str,
cover: Path,
css: Path | None = None
) -> Path:
chapter_files = sorted(chapters_dir.glob("*.md"))
if not chapter_files:
raise ValueError("No chapter files found")
cmd = [
"pandoc",
"--from", "markdown+fenced_code_blocks",
"--to", "epub3",
"--metadata", f"title={title}",
"--metadata", f"author={author}",
"--metadata", "lang=en-US",
"--epub-cover-image", str(cover),
"--toc",
"--toc-depth", "2",
"-o", str(output),
]
if css:
cmd += ["--css", str(css)]
cmd += [str(f) for f in chapter_files]
result = subprocess.run(cmd, capture_output=True, text=True)
if result.returncode != 0:
raise RuntimeError(f"Pandoc error:\n{result.stderr}")
size_kb = output.stat().st_size // 1024
print(f"EPUB ready: {output} ({size_kb} KB)")
return output
Validate the output in Calibre's EPUB viewer before uploading. KDP's previewer is slower and less informative about formatting issues.
Step 4: Cover at KDP Spec
from PIL import Image, ImageDraw, ImageFont
def generate_cover(
title: str,
subtitle: str,
output_path: Path,
bg_color: tuple = (15, 23, 42), # dark slate
text_color: tuple = (248, 250, 252)
) -> Path:
# KDP required: 2560 x 1600 px minimum at 300 DPI
W, H = 1600, 2560
img = Image.new("RGB", (W, H), bg_color)
draw = ImageDraw.Draw(img)
# Title block — use a real font in production
draw.text((80, 200), title, fill=text_color)
draw.text((80, 380), subtitle, fill=(148, 163, 184))
img.save(output_path, "JPEG", quality=95, dpi=(300, 300))
print(f"Cover: {output_path} ({W}x{H})")
return output_path
Step 5: KDP Metadata Checklist
When you reach the KDP dashboard, have these ready before you start:
- Title (exact, no subtitle in title field)
- Subtitle (separate field)
- Two categories (use the lookup, not guessing)
- 7 keywords — use Publisher Rocket or manual search volume checks
- Price: $9.99 US is the sweet spot for 70% royalty with good conversion
- Description: first 150 characters appear above the fold on mobile
Break-Even Math
At $12.99 launch price with 70% KDP royalty:
Royalty per sale = $12.99 × 0.70 = $9.09
Delivery fee = ~$0.05 (text-only ebook)
Net per sale = ~$9.04
Pipeline costs:
Claude API = ~$1.50/book
Cover design = $0 (automated) or $15 (Fiverr)
KDP enrollment = $0
Break-even = ceil($0 / $9.04) = 0 (no fixed monthly cost for KDP alone)
If you also run a Gumroad listing ($20/month for Creator plan), break-even is 3 sales. The second book is pure catalog leverage — same Gumroad subscription, no additional fixed cost.
What the 4-6 Hours Does Not Include
- Editing for depth (plan an extra 2–4 hours for technical accuracy review)
- SEO optimization of the KDP listing after publication
- Marketing and promotional work
The pipeline gets you to "published and purchasable." Getting to "selling consistently" is a separate loop.
The complete pipeline — all scripts, prompts, validation logic, cover generator, and KDP checklist — is packaged in the Python Ebook Automation Pipeline ($12.99, 30-day refund).
📋 Free: AI Publishing Checklist — 7 steps to ship a technical ebook with Python (PDF, free)
Full pipeline + 10 scripts: germy5.gumroad.com/l/xhxkzz — $12.99 launch price
Top comments (0)