Research a subject via web search and produce a comprehensive, graduate-level university textbook as a professionally formatted PDF with table of contents, c...
---
name: make_textbook
description: >
Research a subject via web search and produce a comprehensive, graduate-level
university textbook as a professionally formatted PDF with table of contents,
citations, worked examples, misconceptions, data tables, glossary, and references.
Trigger phrases: "make a textbook", "write a textbook", "generate a textbook",
"create a university textbook", "build a textbook", "write a comprehensive textbook",
"graduate-level textbook", "academic textbook", "comprehensive learning material".
metadata:
builtin_skill_version: "1.3"
python_deps:
- reportlab>=3.6
pip_install: "python3 -m pip install reportlab"
input_schema: textbook_content_json
output_format: PDF
---
# Make a Textbook — Skill Guide v1.2
Build a comprehensive graduate-level university textbook on any subject, complete
with chapter outlines, worked examples, misconceptions, data tables, citations,
glossary, and an index. Output: a professionally formatted PDF (~40-100 KB per book).
---
## When to Use This Skill
Invoke when the user asks to "make a textbook," "write a textbook," "create a
comprehensive learning resource" on any topic — from quantum mechanics to local
AI agent infrastructure.
---
## Workflow Overview
```
SUBJECT → OUTLINE → CHAPTER RESEARCH → CONTENT DRAFTING → QA → PDF GENERATION → DELIVER
```
### Pass 1 — Outline Generation
1. Parse the topic into 6-12 chapters (~3-4 pages each)
2. Search the web for university syllabi, textbook tables of contents, and topic maps
3. Present a structured outline for user approval before proceeding
```
Part I / Section heading
Chapter 1. [Title] — 1-2 sentence description
Chapter 2. [Title] — ...
```
### Pass 2 — Deep Research (Per Chapter)
- Search authoritative sources: lecture notes, open-access textbooks, peer-reviewed papers
- Collect facts, formulas, case studies, examples, statistics
- Verify facts across ≥2 independent sources
- Identify common misconceptions by searching "common misconceptions in [topic]"
- Collect worked examples with step-by-step solutions
- Log every source for IEEE citation format
**Search strategy**: Use `batch_web_search` for 8-10 concurrent searches per chapter.
Combine broad searches with specific sub-topic queries.
### Pass 3 — Content Drafting (Per Chapter)
Each chapter follows this structure:
```
CHAPTER N. [Title]
├─ N.0 Introduction (overview, prerequisites)
├─ N.1 [Core concept] — definitions, explanation, worked examples
├─ N.2 [Next concept] — ...
├─ ⚠ Common Misconceptions (callout box)
├─ N.3 Data Table (comparison or structured data)
└─ References (IEEE numbered)
```
**Every chapter must include:**
- ≥2 worked examples with full solution methodology
- ≥2 common misconceptions with corrections
- ≥1 data table
- IEEE citations embedded in-text
- Every technical term defined on first use
### Pass 4 — Cross-Chapter QA
After drafting all chapters:
1. Check for contradictions between chapters
2. Check for missing definitions (terms used before being defined)
3. Verify citation integrity
4. Ensure notation is consistent across chapters
### Pass 5 — PDF Generation
The PDF generator is at `scripts/textbook_generator.py`. It reads the JSON content
file and produces a professional academic PDF with:
- **Cover page**: navy background, gold title text (multi-line wrapped), subtitle, date
- **Table of contents**: chapter list with sub-headings
- **Chapter banners**: navy with gold left border, chapter number, title
- **Example boxes**: blue accent bar, light-blue background
- **Misconception boxes**: orange accent bar, light-orange background
- **Data tables**: alternating row colours, navy headers
- **Chapter summaries**: bullet-point callout boxes
- **Glossary**: alphabetical by letter, bold term, indented definition
- **References**: hanging-indent IEEE format
Run it:
```bash
python3 scripts/textbook_generator.py textbook_content.json output/book.pdf
```
---
## JSON Content Schema
The `textbook_content.json` file must conform to this schema:
```json
{
"title": "Topic Title",
"subtitle": "Optional Subtitle",
"date": "May 2026",
"preface": "How to use this book...",
"chapters": [
{
"number": 1,
"title": "Chapter Title",
"intro": "Chapter banner subtitle (optional)",
"sections": [
{"type": "heading", "level": 1, "content": "Major Heading"},
{"type": "heading", "level": 2, "content": "Sub-heading"},
{"type": "text", "content": "Body text with **bold**, *italic*, `code` markup."},
{"type": "example", "title": "Example 1.1", "problem": "...", "solution": "..."},
{"type": "misconception", "title": "Misconception: ...", "explanation": "..."},
{"type": "table", "title": "My Data Table", "header": true,
"data": [["Col1","Col2","Col3"],["A","B","C"],["D","E","F"]]},
{"type": "divider", "content": ""}
],
"summary": "- Key takeaway 1\n- Key takeaway 2"
}
],
"glossary": [
{"term": "Term", "definition": "Definition sentence."}
],
"full_references": [
"[1] A. Author, Title, Source, Year."
]
}
```
### Supported Section Types
| type | Fields | Notes |
|----------------|-------------------------------------------------------------|-------|
| `heading` | `level` (1/2/3), `content` | Level 1 adds a gold rule above |
| `text` | `content` | Body text with markup |
| `example` | `title`, `problem`, `solution` | Blue callout box |
| `misconception`| `title`, `explanation` | Orange callout box |
| `table` | `data` (array of arrays — row 0 is headers), `header` (bool, default: true) | ⚠️ Use `data`, NOT `headers`+`rows` — see Common Issues section above |
| `divider` | none | Full-width gold rule |
### Markup in `text` content
| Syntax | Result |
|---------------|---------------------------------|
| `**text**` | Bold |
| `*text*` | Italic |
| `__text__` | Underline |
| `` `code` `` | Courier / monospace |
| `~~text~~` | Strikethrough |
---
## Error Handling & Fallbacks (v1.2 improvements)
The generator is resilient to malformed input:
- **Missing `data` in a table section** → table skipped silently, no crash
- **Ragged table rows** → padded to max column count automatically
- **Non-string cell values** → coerced to str
- **Unknown section types** → skipped silently (forward-compatible)
- **Missing glossary / references** → sections omitted, no crash
- **Missing optional fields** (subtitle, date, intro, preface) → replaced with ""
- **Malformed JSON** → clear error message printed to stderr, exit(1)
- **PDF build failure** → error message to stderr, exit(1)
- **reportlab not installed** → clear install instructions printed, exit(1)
---
## Common Issues & Fixes (learned from iteration)
### ⚠️ Tables not rendering — wrong field names
The generator's `make_table()` expects this exact format:
```json
{"type": "table", "title": "My Table", "header": true,
"data": [["Column A", "Column B"], ["Value 1", "Value 2"]]}
```
**Common mistake**: using separate `headers` + `rows` fields. That format is **not** read by the generator — tables will silently produce empty output.
If your source data has separate header/row arrays, combine them:
```python
section["data"] = [section["headers"]] + section["rows"]
section["header"] = True
del section["headers"]; del section["rows"]
```
### ⚠️ Cover says "Untitled Textbook" — title not at root level
The generator reads `data['title']` from the **top-level JSON key**, not from a nested `metadata` object. Always include these at the root level:
```json
{
"title": "My Actual Title",
"subtitle": "My Subtitle",
"date": "May 2026",
"metadata": { ... },
"chapters": [ ... ]
}
```
If your source data has `title` only inside `metadata`, copy it to the root before running the generator.
### ⚠️ Text sections showing as bullet lists instead of prose
Give every section an explicit `"type": "text"` field. Sections without a `type` field fall through to a default, but explicit is more reliable.
### ✅ PDF Verification Checklist (before sending to user)
Before delivering, always verify:
1. The PDF renders with the correct title on the cover (open via CDN or read the file)
2. Tables contain the right number of rows and columns
3. All chapters have readable prose content (not just bullet lists)
Quick Python verification:
```python
from textbook_generator import build_styles, make_table
styles = build_styles()
for chapter in data['chapters']:
for s in chapter['sections']:
if s.get('type') == 'table' and 'data' in s:
result = make_table(s, styles, 16.0)
tbl = result[0]
print(f"Table '{s['title']}': {tbl._nrows} rows x {tbl._ncols} cols")
```
### 💡 Converting text comparison blocks to tables
Comparison content (e.g. "University X: feature Y") reads far better as a formatted table than as a bullet list. When a text section lists items in the pattern `"Name | Description | Category"`, convert it to a table:
```json
{"type": "table", "title": "...", "header": true,
"data": [["Name","Description","Category"],
["Item 1","Desc 1","Cat A"],
["Item 2","Desc 2","Cat B"]]}
```
---
## Architecture Notes (for contributors)
- `textbook_generator.py` is pure Python 3, no external API calls
- ReportLab is the only hard dependency (pip install reportlab)
- Paths resolve relative to the skill root (parent of scripts/) — run from anywhere
- Page handler uses `canvas.showPage()` on page 1 to advance to page 2 for TOC
- All rendering functions (`make_example`, `make_table`, etc.) return a list of
flowables; empty list means "skip gracefully" — never raise from a renderer
- See inline docstrings in `textbook_generator.py` for detailed per-function docs
---
## Iteration Triggers
- **Chapter too shallow**: Expand with additional worked examples and data tables
- **Missing sources**: Return to Pass 2 for targeted sub-topic searches
- **Outline rejected**: Re-present with adjusted scope, chapter count, or emphasis
- **Contradiction found in QA**: Flag which chapter, return to that chapter's researchdon't have the plugin yet? install it then click "run inline in claude" again.