+```
+
+2. Update `mkdocs.yml` nav to include test page:
+
+```yaml
+nav:
+ - Home: index.md
+ - Test: test-brython.md
+```
+
+3. Test:
+```bash
+mkdocs serve
+# Visit http://127.0.0.1:8000/test-brython/
+# Click RUN button, verify "Hello from Brython!" appears
+```
+
+**Commit:** `Add Brython runtime integration`
+
+---
+
+### Task 6.2: Implement Plotille Mock for Brython
+
+**What:** Since plotille won't work directly in Brython, create a browser-compatible version.
+
+**Considerations:**
+
+This is complex. Plotille uses features that may not work in Brython. For the initial implementation:
+
+**Option A:** Bundle the actual plotille source and hope it works in Brython
+**Option B:** Create a simplified browser-compatible version
+**Option C:** Use a server-side execution API (more complex)
+
+**Recommended approach:** Try Option A first (simplest per YAGNI). If plotille doesn't work in Brython, we'll need to discuss alternatives.
+
+**Files to create:**
+- `docs/javascripts/plotille-brython.js` (loader script)
+
+**Actions:**
+
+1. Copy plotille source to docs for Brython access:
+
+```bash
+# Create a script to copy plotille sources
+cat > scripts/copy_plotille_for_brython.py << 'EOF'
+#!/usr/bin/env python3
+"""Copy plotille source files for Brython access."""
+import shutil
+from pathlib import Path
+
+def main():
+ project_root = Path(__file__).parent.parent
+ source_dir = project_root / "plotille"
+ dest_dir = project_root / "docs" / "src" / "lib" / "plotille"
+
+ # Remove old copy
+ if dest_dir.exists():
+ shutil.rmtree(dest_dir)
+
+ # Copy plotille source
+ shutil.copytree(source_dir, dest_dir)
+ print(f"Copied plotille to {dest_dir}")
+
+if __name__ == "__main__":
+ main()
+EOF
+
+chmod +x scripts/copy_plotille_for_brython.py
+```
+
+2. Run the copy script:
+```bash
+python scripts/copy_plotille_for_brython.py
+```
+
+3. Update `scripts/generate_docs.py` to run this during generation:
+
+```python
+# Add at the end of main() before return
+def main() -> int:
+ # ... existing code ...
+
+ # Copy plotille for Brython
+ print("\nCopying plotille for Brython...")
+ copy_script = project_root / "scripts" / "copy_plotille_for_brython.py"
+ subprocess.run([sys.executable, str(copy_script)], check=True)
+
+ print("\nā Documentation generation complete")
+ return 0
+```
+
+**Test:**
+
+This requires actual testing with examples. We'll validate this in the next phase when integrating CodeMirror.
+
+**Commit:** `Add plotille source copying for Brython access`
+
+---
+
+## Phase 7: CodeMirror Integration
+
+### Task 7.1: Add CodeMirror 6 Setup
+
+**What:** Integrate CodeMirror 6 for code editing with Python syntax highlighting.
+
+**Files to create:**
+- `docs/javascripts/codemirror-setup.js`
+
+**Actions:**
+
+1. Update `mkdocs.yml` to include CodeMirror from CDN:
+
+```yaml
+extra_javascript:
+ - https://cdn.jsdelivr.net/npm/brython@3.12.0/brython.min.js
+ - https://cdn.jsdelivr.net/npm/brython@3.12.0/brython_stdlib.js
+ # CodeMirror 6
+ - https://cdn.jsdelivr.net/npm/codemirror@6.0.1/dist/index.min.js
+ - https://cdn.jsdelivr.net/npm/@codemirror/lang-python@6.1.3/dist/index.min.js
+ - https://cdn.jsdelivr.net/npm/@codemirror/theme-one-dark@6.1.2/dist/index.min.js
+ - javascripts/codemirror-setup.js
+ - javascripts/brython-setup.js
+```
+
+2. Create `docs/javascripts/codemirror-setup.js`:
+
+```javascript
+/**
+ * CodeMirror 6 setup for plotille documentation.
+ *
+ * Converts textarea elements into CodeMirror editors with Python highlighting.
+ */
+
+document.addEventListener('DOMContentLoaded', function() {
+ // Wait for CodeMirror to load
+ if (typeof CodeMirror === 'undefined') {
+ console.error('CodeMirror not loaded');
+ return;
+ }
+
+ // Find all code editor textareas
+ const editors = document.querySelectorAll('.code-editor');
+
+ editors.forEach(textarea => {
+ const editorId = textarea.id;
+ const initialCode = textarea.value;
+
+ // Create CodeMirror editor
+ // Note: This uses basic textarea for now
+ // Full CodeMirror 6 integration would require bundling
+ // For simplicity, we'll enhance the textarea with basic features
+
+ textarea.style.fontFamily = "'IBM Plex Mono', monospace";
+ textarea.style.fontSize = '14px';
+ textarea.style.lineHeight = '1.5';
+ textarea.style.tabSize = '4';
+
+ // Add tab key support
+ textarea.addEventListener('keydown', function(e) {
+ if (e.key === 'Tab') {
+ e.preventDefault();
+ const start = this.selectionStart;
+ const end = this.selectionEnd;
+ const value = this.value;
+
+ // Insert 4 spaces
+ this.value = value.substring(0, start) + ' ' + value.substring(end);
+ this.selectionStart = this.selectionEnd = start + 4;
+ }
+ });
+
+ console.log(`Editor initialized: ${editorId}`);
+ });
+});
+```
+
+**Note:** Full CodeMirror 6 integration from CDN is complex. The above provides basic textarea enhancement. If you need full CodeMirror features (syntax highlighting, autocomplete), you'll need to either:
+
+A) Bundle CodeMirror properly with a build step
+B) Use a simpler approach (current implementation)
+C) Use CDN but with more complex module loading
+
+For now, **proceed with enhanced textarea** (YAGNI). Full CodeMirror can be added later if needed.
+
+**Test:**
+
+```bash
+mkdocs serve
+# Visit test-brython page
+# Verify code editor has monospace font and tab key works
+```
+
+**Commit:** `Add CodeMirror setup with textarea enhancement`
+
+---
+
+### Task 7.2: Improve Brython Execution with Output Capture
+
+**What:** Better stdout capturing for Brython execution.
+
+**Files to modify:**
+- `docs/javascripts/brython-setup.js`
+
+**Actions:**
+
+Replace the `runExample` function in `brython-setup.js`:
+
+```javascript
+/**
+ * Execute Python code in an example with proper output capture.
+ *
+ * @param {string} exampleName - Name of the example to run
+ */
+function runExample(exampleName) {
+ const editor = document.getElementById(`editor-${exampleName}`);
+ const outputDiv = document.querySelector(`#output-${exampleName} .output-content`);
+
+ if (!editor || !outputDiv) {
+ console.error(`Example ${exampleName} not found`);
+ return;
+ }
+
+ const code = editor.value;
+
+ // Clear previous output
+ outputDiv.textContent = '';
+ outputDiv.classList.remove('error');
+
+ // Show loading indicator
+ outputDiv.textContent = 'Running...';
+
+ // Use setTimeout to allow UI update
+ setTimeout(() => {
+ try {
+ // Create a new output buffer
+ let outputBuffer = [];
+
+ // Monkey-patch print for output capture
+ const printFunc = function(...args) {
+ const line = args.join(' ');
+ outputBuffer.push(line);
+ };
+
+ // Inject print into the Python code
+ const wrappedCode = `
+import sys
+from io import StringIO
+
+__output__ = StringIO()
+__old_stdout__ = sys.stdout
+sys.stdout = __output__
+
+try:
+${code.split('\n').map(line => ' ' + line).join('\n')}
+finally:
+ sys.stdout = __old_stdout__
+ print(__output__.getvalue(), end='')
+`;
+
+ // Execute with Brython
+ const script = document.createElement('script');
+ script.type = 'text/python';
+ script.id = `brython-script-${exampleName}`;
+ script.textContent = wrappedCode;
+
+ // Add output capture
+ window.__brython_output__ = '';
+ const oldLog = console.log;
+ console.log = function(...args) {
+ window.__brython_output__ += args.join(' ') + '\n';
+ oldLog.apply(console, args);
+ };
+
+ document.body.appendChild(script);
+
+ // Run Brython on this script
+ if (window.brython) {
+ brython({debug: 1, ids: [script.id]});
+ }
+
+ // Restore console.log
+ console.log = oldLog;
+
+ // Small delay to capture output
+ setTimeout(() => {
+ const output = window.__brython_output__ || '(no output)';
+ outputDiv.textContent = output;
+
+ // Clean up
+ script.remove();
+ delete window.__brython_output__;
+ }, 100);
+
+ } catch (error) {
+ // Display error
+ outputDiv.classList.add('error');
+ outputDiv.textContent = `Error: ${error.message}`;
+ console.error('Brython execution error:', error);
+ }
+ }, 10);
+}
+```
+
+**Test:**
+
+```bash
+mkdocs serve
+# Test the example execution again
+# Verify output is captured correctly
+```
+
+**Commit:** `Improve Brython output capture`
+
+---
+
+## Phase 8: API Documentation with mkdocstrings
+
+### Task 8.1: Configure mkdocstrings for API Reference
+
+**What:** Set up automatic API documentation generation from docstrings.
+
+**Files to modify:**
+- `mkdocs.yml`
+
+**Actions:**
+
+1. Update `mkdocs.yml` plugins section:
+
+```yaml
+plugins:
+ - search
+ - mkdocstrings:
+ handlers:
+ python:
+ options:
+ docstring_style: google
+ show_source: true
+ show_root_heading: true
+ show_root_full_path: false
+ show_signature_annotations: true
+ separate_signature: true
+ show_symbol_type_heading: true
+ show_symbol_type_toc: true
+ signature_crossrefs: true
+ merge_init_into_class: true
+ paths: [plotille]
+```
+
+2. Create API reference structure in `docs/api/`:
+
+```bash
+mkdir -p docs/api
+```
+
+3. Create `docs/api/index.md`:
+
+```markdown
+# API Reference
+
+Complete API documentation for plotille.
+
+## High-Level Functions
+
+Quick plotting functions for simple use cases.
+
+- [Plotting Functions](plotting.md) - `plot()`, `scatter()`, `histogram()`
+- [Figure Class](figure.md) - Compose complex multi-plot visualizations
+
+## Core Components
+
+- [Canvas](canvas.md) - Low-level drawing primitives
+- [Colors](colors.md) - Color handling and themes
+
+## Utilities
+
+- [Input Formatting](formatting.md) - Data preprocessing
+- [Data Types](datatypes.md) - Internal data structures
+```
+
+4. Create `docs/api/plotting.md`:
+
+```markdown
+# Plotting Functions
+
+High-level plotting functions for quick visualizations.
+
+## plot
+
+::: plotille.plot
+ options:
+ show_root_heading: true
+ show_source: true
+
+## scatter
+
+::: plotille.scatter
+ options:
+ show_root_heading: true
+ show_source: true
+
+## hist
+
+::: plotille.hist
+ options:
+ show_root_heading: true
+ show_source: true
+
+## histogram
+
+::: plotille.histogram
+ options:
+ show_root_heading: true
+ show_source: true
+```
+
+5. Create `docs/api/figure.md`:
+
+```markdown
+# Figure
+
+The Figure class for composing complex visualizations.
+
+::: plotille.Figure
+ options:
+ show_root_heading: true
+ show_source: true
+ members:
+ - __init__
+ - plot
+ - scatter
+ - histogram
+ - text
+ - axvline
+ - axhline
+ - axvspan
+ - axhspan
+ - imgshow
+ - show
+ - clear
+```
+
+6. Create `docs/api/canvas.md`:
+
+```markdown
+# Canvas
+
+Low-level canvas for direct drawing.
+
+::: plotille.Canvas
+ options:
+ show_root_heading: true
+ show_source: true
+ members:
+ - __init__
+ - point
+ - line
+ - rect
+ - text
+ - braille_image
+ - image
+ - plot
+```
+
+**Test:**
+
+```bash
+mkdocs serve
+# Visit http://127.0.0.1:8000/api/
+# Verify API documentation appears with docstrings
+```
+
+**Commit:** `Add mkdocstrings API reference configuration`
+
+---
+
+### Task 8.2: Enhance Docstrings with Examples (Sample)
+
+**What:** Add doctest examples to key functions as a template.
+
+**Files to modify:**
+- `plotille/_graphs.py` (or wherever `plot()` is defined)
+
+**Actions:**
+
+This task demonstrates enhancing ONE function as an example. You'll repeat this pattern for other functions.
+
+1. Find the `plot()` function (likely in `plotille/__init__.py` or `plotille/_graphs.py`)
+
+2. Enhance its docstring with a doctest example:
+
+```python
+def plot(
+ X,
+ Y,
+ width=80,
+ height=40,
+ X_label='X',
+ Y_label='Y',
+ linesep=os.linesep,
+ interp='linear',
+ x_min=None,
+ x_max=None,
+ y_min=None,
+ y_max=None,
+ lc=None,
+ bg=None,
+ color_mode='names',
+ origin=True,
+ marker=None,
+):
+ """
+ Create plot with X, Y values and linear interpolation between points.
+
+ Parameters:
+ X: List[float] X values.
+ Y: List[float] Y values. X and Y must have the same number of entries.
+ width: int The number of characters for the width (columns) of the canvas.
+ height: int The number of characters for the height (rows) of the canvas.
+ X_label: str Label for X-axis.
+ Y_label: str Label for Y-axis. max 8 characters.
+ linesep: str The requested line separator. default: os.linesep
+ interp: Optional[str] Specify interpolation; values None, 'linear'
+ x_min, x_max: float Limits for the displayed X values.
+ y_min, y_max: float Limits for the displayed Y values.
+ lc: multiple Give the line color.
+ bg: multiple Give the background color.
+ color_mode: str Specify color input mode; 'names' (default), 'byte' or 'rgb'
+ see plotille.color.__docs__
+ origin: bool Whether to print the origin. default: True
+ marker: str Instead of braille dots set a marker char for actual values.
+
+ Returns:
+ str: plot over `X`, `Y`.
+
+ Examples:
+ Simple line plot:
+
+ >>> import plotille
+ >>> X = [1, 2, 3, 4, 5]
+ >>> Y = [1, 4, 2, 3, 5]
+ >>> result = plotille.plot(X, Y, width=40, height=10)
+ >>> 'ā ' in result # Contains braille dots
+ True
+ >>> 'X' in result # Contains axis label
+ True
+
+ Plot with custom range:
+
+ >>> result = plotille.plot([0, 1], [0, 1], width=20, height=5,
+ ... x_min=0, x_max=1, y_min=0, y_max=1)
+ >>> len(result) > 0
+ True
+ """
+ # ... existing implementation ...
+```
+
+**Test:**
+
+```bash
+# Run doctests
+pytest --doctest-modules plotille/_graphs.py -v
+# Or wherever plot() is defined
+
+# Should show doctests passing
+```
+
+**Commit:** `Add doctest examples to plot() function`
+
+---
+
+### Task 8.3: Add Doctests to Core Functions (Iterative)
+
+**What:** Systematically add doctest examples to all public functions.
+
+**Files to modify:**
+- All files in `plotille/` directory with public functions
+
+**Actions:**
+
+This is a large task. Break it down:
+
+1. Create a checklist of functions to document:
+
+```bash
+# Generate list of public functions
+python -c "
+import plotille
+import inspect
+
+members = inspect.getmembers(plotille, inspect.isfunction)
+public = [name for name, _ in members if not name.startswith('_')]
+for name in sorted(public):
+ print(f'- [ ] {name}')
+" > docs/plans/doctest-checklist.md
+```
+
+2. For each function:
+ - Read existing docstring
+ - Add at least one `>>>` example showing basic usage
+ - Add edge case examples if relevant
+ - Run `pytest --doctest-modules` to verify
+ - Commit with message like `Add doctests to scatter() function`
+
+3. Prioritize by importance:
+ - High-level functions first (`plot`, `scatter`, `hist`, etc.)
+ - Then `Figure` methods
+ - Then `Canvas` methods
+ - Finally utility functions
+
+**Test:**
+
+After each function:
+```bash
+pytest --doctest-modules plotille/ -v
+# All doctests should pass
+```
+
+**This is iterative:** Do a few functions, commit, repeat. Don't do all at once.
+
+**Commit pattern:** `Add doctests to ()`
+
+---
+
+## Phase 9: Navigation and Site Structure
+
+### Task 9.1: Update Navigation in mkdocs.yml
+
+**What:** Define the site navigation structure.
+
+**Files to modify:**
+- `mkdocs.yml`
+
+**Actions:**
+
+Update the `nav` section in `mkdocs.yml`:
+
+```yaml
+nav:
+ - Home: index.md
+ - Cookbook:
+ - Basic Plots: cookbook/basic.md
+ - Complex Figures: cookbook/figures.md
+ - Canvas Drawing: cookbook/canvas.md
+ - Advanced Examples: cookbook/advanced.md
+ - API Reference:
+ - Overview: api/index.md
+ - Plotting Functions: api/plotting.md
+ - Figure: api/figure.md
+ - Canvas: api/canvas.md
+```
+
+**Test:**
+
+```bash
+mkdocs serve
+# Verify navigation structure appears correctly
+# All links work
+```
+
+**Commit:** `Configure site navigation structure`
+
+---
+
+### Task 9.2: Customize Navigation Sidebar Styling
+
+**What:** Style the navigation to match terminal aesthetic.
+
+**Files to modify:**
+- `docs/stylesheets/terminal.css`
+
+**Actions:**
+
+Add to `docs/stylesheets/terminal.css`:
+
+```css
+/* Navigation as terminal directory listing */
+.md-nav {
+ font-family: 'IBM Plex Mono', monospace;
+}
+
+.md-nav__title {
+ font-family: 'VT323', monospace;
+ color: var(--amber-bright);
+ font-size: 1.2rem;
+ text-shadow: 0 0 5px var(--amber-glow);
+}
+
+.md-nav__list {
+ list-style: none;
+}
+
+.md-nav__item {
+ position: relative;
+}
+
+.md-nav__link {
+ color: var(--amber-base);
+ padding-left: 1.5rem;
+ transition: color 0.2s, text-shadow 0.2s;
+}
+
+.md-nav__link:hover {
+ color: var(--amber-bright);
+ text-shadow: 0 0 8px var(--amber-glow);
+}
+
+/* Terminal prompt indicator for active item */
+.md-nav__link--active {
+ color: var(--amber-bright);
+ font-weight: 600;
+}
+
+.md-nav__link--active::before {
+ content: 'root@plotille:~$';
+ position: absolute;
+ left: -8rem;
+ color: var(--amber-dim);
+ font-size: 0.85rem;
+ opacity: 0.7;
+}
+
+/* Folder icons using braille */
+.md-nav__item--nested > .md-nav__link::before {
+ content: 'ā æ ';
+ color: var(--amber-dim);
+}
+
+.md-nav__item:not(.md-nav__item--nested) > .md-nav__link::before {
+ content: '⣿ ';
+ color: var(--amber-dim);
+ font-size: 0.6rem;
+}
+```
+
+**Test:**
+
+```bash
+mkdocs serve
+# Check navigation sidebar styling
+# Verify braille icons appear
+# Test hover effects
+```
+
+**Commit:** `Add terminal-styled navigation sidebar`
+
+---
+
+## Phase 10: Hero Animation
+
+### Task 10.1: Create Animated Hero Plot
+
+**What:** Animate a plotille graph appearing on the home page.
+
+**Files to create:**
+- `docs/javascripts/hero-animation.js`
+
+**Actions:**
+
+1. Create `docs/javascripts/hero-animation.js`:
+
+```javascript
+/**
+ * Animated hero plot for home page.
+ *
+ * Draws a sine wave using braille dots, character by character.
+ */
+
+function animateHeroPlot() {
+ const heroPlot = document.getElementById('hero-animation');
+
+ if (!heroPlot) {
+ return;
+ }
+
+ // Example plotille output (sine wave)
+ // This would ideally be generated server-side
+ const plotOutput = ` 5.00⤠┰ā ā ā ā ā¢ā”ā
+ ⤠ā¢ā” ā ⢸
+ ⤠ā¢ā” ā ā ⢸
+ ⤠ā¢ā” ā ā ⢸
+ ⤠ā¢ā” ā ā ⢸
+ 0.00ā¼ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā ¤ā¢¤ā” ⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⢼⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤⠤
+ ⤠⢠ā ā ⢸
+ ⤠ā¢ā” ā ⢸
+ ⤠ā¢ā” ā ā ⢸
+ ⤠ā¢ā” ā ā ⢸
+ -5.00ā¤ā£ā£ā£ā” ā ¤ā ā ā ā ā ā ā ā ā ¤ā£ā£ā£
+ āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
+ -3.14 X 3.14`;
+
+ // Animate character by character
+ const chars = plotOutput.split('');
+ let index = 0;
+
+ heroPlot.textContent = '';
+
+ const interval = setInterval(() => {
+ if (index < chars.length) {
+ heroPlot.textContent += chars[index];
+ index++;
+ } else {
+ clearInterval(interval);
+ }
+ }, 5); // 5ms per character = ~1 second for 200 chars
+}
+
+// Run animation when page loads
+document.addEventListener('DOMContentLoaded', function() {
+ setTimeout(animateHeroPlot, 500); // Slight delay after page load
+});
+```
+
+2. Update `mkdocs.yml` to include the script:
+
+```yaml
+extra_javascript:
+ - https://cdn.jsdelivr.net/npm/brython@3.12.0/brython.min.js
+ - https://cdn.jsdelivr.net/npm/brython@3.12.0/brython_stdlib.js
+ - javascripts/codemirror-setup.js
+ - javascripts/brython-setup.js
+ - javascripts/hero-animation.js
+```
+
+**Better approach:** Generate the hero plot dynamically during doc build.
+
+3. Update `scripts/generate_docs.py` to generate hero plot:
+
+```python
+def generate_hero_plot() -> str:
+ """
+ Generate a sample plot for the hero animation.
+
+ Returns:
+ String containing plotille plot output
+ """
+ try:
+ import plotille
+ import math
+
+ X = [i / 10 for i in range(-31, 32)]
+ Y = [math.sin(x) for x in X]
+
+ plot_output = plotille.plot(
+ X, Y,
+ width=60,
+ height=10,
+ X_label='X',
+ Y_label='',
+ )
+
+ return plot_output
+ except Exception as e:
+ # Fallback if generation fails
+ return "Error generating plot"
+
+
+# Update generate_home_page()
+def generate_home_page(docs_dir: Path) -> Path:
+ """Generate the home/index page."""
+ hero_plot = generate_hero_plot()
+
+ content = f"""# plotille
+
+
+
+ [root@plotille ~]$
+
+
+
{hero_plot}
+
+
+
+Plot in the terminal using braille dots, with no dependencies.
+
+## Features
+
+- **Scatter plots, line plots, histograms** - Basic plotting functions
+- **Complex figures** - Compose multiple plots with legends
+- **Canvas drawing** - Direct pixel manipulation for custom visualizations
+- **Image rendering** - Display images using braille dots or background colors
+- **Color support** - Multiple color modes: names, byte values, RGB
+- **No dependencies** - Pure Python with no external requirements
+
+## Quick Start
+
+Install plotille:
+
+```bash
+pip install plotille
+```
+
+Create your first plot:
+
+```python
+import plotille
+import math
+
+X = [i/10 for i in range(-30, 30)]
+Y = [math.sin(x) for x in X]
+
+print(plotille.plot(X, Y, height=20, width=60))
+```
+
+## Explore
+
+Browse the [cookbook](cookbook/basic/) to see interactive examples you can edit and run in your browser.
+
+"""
+
+ index_file = docs_dir / "index.md"
+ index_file.write_text(content)
+ return index_file
+```
+
+**Test:**
+
+```bash
+python scripts/generate_docs.py
+mkdocs serve
+# Visit home page, verify plot appears in hero section
+```
+
+**Commit:** `Add hero plot to home page`
+
+---
+
+## Phase 11: GitHub Actions CI/CD
+
+### Task 11.1: Create Documentation Build Workflow
+
+**What:** Automate doc building and deployment on push to main.
+
+**Files to create:**
+- `.github/workflows/docs.yml`
+
+**Actions:**
+
+1. Create directory:
+```bash
+mkdir -p .github/workflows
+```
+
+2. Create `.github/workflows/docs.yml`:
+
+```yaml
+name: Build and Deploy Documentation
+
+on:
+ push:
+ branches:
+ - master # Adjust if your main branch is named differently
+ workflow_dispatch: # Allow manual trigger
+
+permissions:
+ contents: write # Needed to push to gh-pages
+
+jobs:
+ build-and-deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0 # Full history for proper git info
+
+ - name: Set up Python
+ uses: actions/setup-python@v5
+ with:
+ python-version: '3.11'
+
+ - name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -e ".[dev]"
+
+ - name: Run tests (including doctests)
+ run: |
+ pytest --doctest-modules plotille/ -v
+
+ - name: Generate documentation
+ run: |
+ python scripts/generate_docs.py
+
+ - name: Build MkDocs site
+ run: |
+ mkdocs build --strict
+
+ - name: Deploy to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: ./site
+ cname: plotille.tammo.io
+```
+
+**Test:**
+
+You can't fully test this until you push to GitHub, but you can verify the workflow syntax:
+
+```bash
+# Install actionlint for workflow validation (optional)
+# brew install actionlint # macOS
+# Or download from https://github.com/rhysd/actionlint
+
+# Validate workflow
+actionlint .github/workflows/docs.yml
+
+# Or just verify it's valid YAML
+python -c "import yaml; yaml.safe_load(open('.github/workflows/docs.yml'))"
+```
+
+**Commit:** `Add GitHub Actions workflow for documentation`
+
+---
+
+### Task 11.2: Configure GitHub Pages Settings
+
+**What:** Set up GitHub repository for Pages deployment.
+
+**Actions (to be done in GitHub web interface):**
+
+1. Push the changes to GitHub:
+```bash
+git push origin master # Or your main branch
+```
+
+2. Go to repository Settings ā Pages
+
+3. Under "Build and deployment":
+ - Source: "Deploy from a branch"
+ - Branch: Select `gh-pages` and `/ (root)`
+ - Click "Save"
+
+4. Under "Custom domain":
+ - Enter: `plotille.tammo.io`
+ - Click "Save"
+ - Wait for DNS check to complete
+
+5. Enable "Enforce HTTPS" once DNS check passes
+
+**DNS Configuration (at your domain registrar):**
+
+Add CNAME record:
+```
+Host: plotille
+Points to: tammoippen.github.io
+```
+
+**Test:**
+
+After workflow runs and DNS propagates:
+- Visit https://plotille.tammo.io
+- Verify site loads with documentation
+- Check that HTTPS works
+
+**Commit:** (No code changes, just documentation of steps)
+
+---
+
+## Phase 12: Testing and Polish
+
+### Task 12.1: Manual Testing Checklist
+
+**What:** Comprehensive testing of the documentation site.
+
+**Actions:**
+
+Create a testing checklist `docs/plans/testing-checklist.md`:
+
+```markdown
+# Documentation Testing Checklist
+
+## Visual Design
+- [ ] Amber phosphor color scheme applies throughout
+- [ ] IBM Plex Mono font loads correctly
+- [ ] VT323 font loads for headers
+- [ ] Scanline effect is visible but not distracting
+- [ ] Terminal windows have proper styling
+- [ ] Navigation sidebar matches terminal aesthetic
+- [ ] Responsive design works on mobile
+
+## Navigation
+- [ ] All navigation links work
+- [ ] Breadcrumbs function correctly
+- [ ] Search works (if enabled)
+- [ ] Active page is highlighted in sidebar
+- [ ] Braille dot icons appear in navigation
+
+## Home Page
+- [ ] Hero plot displays correctly
+- [ ] Quick start code block renders
+- [ ] Links to cookbook work
+
+## Cookbook Pages
+- [ ] All four category pages exist (basic, figures, canvas, advanced)
+- [ ] Examples are categorized correctly
+- [ ] Interactive examples have working editors
+- [ ] Run buttons work for interactive examples
+- [ ] Output displays correctly
+- [ ] Static examples show pre-rendered output
+- [ ] Dependency warnings show for static examples
+
+## Interactive Examples
+- [ ] Code editor is editable
+- [ ] Tab key inserts spaces
+- [ ] Run button executes code
+- [ ] Output appears in terminal-styled div
+- [ ] Errors display clearly
+- [ ] Can modify code and re-run
+- [ ] Multiple examples on same page don't interfere
+
+## API Reference
+- [ ] All API pages exist
+- [ ] Docstrings render correctly
+- [ ] Type hints display properly
+- [ ] Function signatures are clear
+- [ ] Examples in docstrings render
+- [ ] Cross-references link correctly
+- [ ] Source code links work
+
+## Doctests
+- [ ] All doctests pass: `pytest --doctest-modules plotille/`
+- [ ] Coverage is reasonable (aim for 80%+ of public functions)
+
+## Build Process
+- [ ] `python scripts/generate_docs.py` completes without errors
+- [ ] `mkdocs build` completes without warnings
+- [ ] Generated site is in `site/` directory
+- [ ] No broken links in built site
+
+## CI/CD
+- [ ] GitHub Actions workflow runs successfully
+- [ ] Documentation deploys to gh-pages branch
+- [ ] Site is accessible at plotille.tammo.io
+- [ ] HTTPS works
+- [ ] Custom domain configured correctly
+
+## Performance
+- [ ] Page load time is reasonable (<3s)
+- [ ] No console errors in browser
+- [ ] Brython loads correctly
+- [ ] Fonts load without flash of unstyled text
+
+## Browser Compatibility
+- [ ] Works in Chrome/Chromium
+- [ ] Works in Firefox
+- [ ] Works in Safari
+- [ ] Works in Edge
+```
+
+Work through this checklist systematically, fixing issues as you find them.
+
+**Commit pattern:** `Fix: ` for each fix
+
+---
+
+### Task 12.2: Add Error Styling for Interactive Examples
+
+**What:** Better error display when code fails.
+
+**Files to modify:**
+- `docs/stylesheets/terminal.css`
+
+**Actions:**
+
+Add error styling to `terminal.css`:
+
+```css
+/* Error output styling */
+.terminal-output .error {
+ color: #ff6b6b;
+ background: rgba(255, 0, 0, 0.1);
+ border-left: 3px solid #ff6b6b;
+ padding-left: 0.5rem;
+}
+
+.output-content.error {
+ color: #ff6b6b;
+}
+
+/* Loading state */
+.terminal-output .loading::after {
+ content: '...';
+ animation: loading 1.5s infinite;
+}
+
+@keyframes loading {
+ 0%, 100% { opacity: 0; }
+ 50% { opacity: 1; }
+}
+```
+
+**Test:**
+
+Create a test example that intentionally errors:
+
+```markdown
+# Error Test
+
+
+
+ [python3 error.py]
+
+
+
+
+
+ root@plotille:~$
+
+
+
+
+```
+
+Verify error displays with red styling.
+
+**Commit:** `Add error styling for interactive examples`
+
+---
+
+### Task 12.3: Add README Section About Documentation
+
+**What:** Update project README to link to the new documentation site.
+
+**Files to modify:**
+- `README.md`
+
+**Actions:**
+
+Add a documentation section near the top of `README.md`:
+
+```markdown
+## Documentation
+
+š **Full documentation available at [plotille.tammo.io](https://plotille.tammo.io)**
+
+Features:
+- **Interactive examples** - Edit and run code in your browser
+- **Complete API reference** - Auto-generated from source
+- **Cookbook** - Examples organized by complexity
+
+```
+
+**Commit:** `Add documentation link to README`
+
+---
+
+## Phase 13: Refinement and Edge Cases
+
+### Task 13.1: Handle Empty/Missing Examples Gracefully
+
+**What:** Ensure generation script handles edge cases.
+
+**Files to modify:**
+- `scripts/generate_docs.py`
+
+**Actions:**
+
+Add validation to generation script:
+
+```python
+def main() -> int:
+ """Main entry point."""
+ project_root = Path(__file__).parent.parent
+ examples_dir = project_root / "examples"
+ output_dir = project_root / "docs" / "assets" / "example-outputs"
+ docs_dir = project_root / "docs"
+
+ if not examples_dir.exists():
+ print(f"Error: {examples_dir} not found", file=sys.stderr)
+ return 1
+
+ # Analyze all Python files
+ examples = []
+ for example_file in sorted(examples_dir.glob("*.py")):
+ try:
+ info = analyze_example(example_file)
+ examples.append(info)
+ except Exception as e:
+ print(f"Warning: Failed to analyze {example_file.name}: {e}",
+ file=sys.stderr)
+ continue
+
+ if not examples:
+ print("Warning: No examples found", file=sys.stderr)
+ # Generate placeholder pages
+ for category in ['basic', 'figures', 'canvas', 'advanced']:
+ category_dir = docs_dir / "cookbook"
+ category_dir.mkdir(parents=True, exist_ok=True)
+ placeholder = category_dir / f"{category}.md"
+ placeholder.write_text(f"# {category.title()}\n\nNo examples yet.\n")
+ return 0
+
+ # ... rest of existing code ...
+```
+
+**Test:**
+
+```bash
+# Test with no examples (temporarily)
+mv examples examples.backup
+mkdir examples
+python scripts/generate_docs.py
+# Should handle gracefully
+
+# Restore
+rmdir examples
+mv examples.backup examples
+```
+
+**Commit:** `Add error handling for missing examples`
+
+---
+
+### Task 13.2: Add Source File Headers
+
+**What:** Ensure all documentation source files have descriptive headers.
+
+**Files to check:**
+- `scripts/generate_docs.py`
+- `docs/javascripts/*.js`
+- `docs/stylesheets/*.css`
+
+**Actions:**
+
+Add headers following the CLAUDE.md rule about ABOUTME comments:
+
+Example for `scripts/generate_docs.py`:
+
+```python
+#!/usr/bin/env python3
+# ABOUTME: Generates plotille documentation from examples and source code.
+# ABOUTME: Analyzes examples, executes static ones, and creates markdown pages.
+"""
+Generate documentation from examples.
+
+This script:
+1. Scans examples/ directory
+2. Classifies examples by dependencies
+3. Generates markdown files for MkDocs
+"""
+```
+
+Check each file and add appropriate headers.
+
+**Commit:** `Add ABOUTME headers to documentation files`
+
+---
+
+### Task 13.3: Performance Optimization - Lazy Load Brython
+
+**What:** Only load Brython on pages that need it.
+
+**Files to modify:**
+- `mkdocs.yml`
+- `docs/javascripts/brython-setup.js`
+
+**Actions:**
+
+1. Update `mkdocs.yml` to conditionally load Brython:
+
+```yaml
+# Move Brython scripts to be loaded only when needed
+extra_javascript:
+ - javascripts/codemirror-setup.js
+ - javascripts/hero-animation.js
+ # Brython loaded conditionally
+```
+
+2. Update example pages to load Brython:
+
+In `scripts/generate_docs.py`, update `generate_interactive_example_markdown()`:
+
+```python
+def generate_interactive_example_markdown(info: ExampleInfo) -> str:
+ """Generate markdown for an interactive example."""
+ source_code = info.path.read_text()
+ escaped_code = source_code.replace('```', '\\`\\`\\`')
+
+ # Add script tag to load Brython on this page
+ brython_loader = '''
+
+
+
+'''
+
+ return f"""{brython_loader}
+
+## {info.name}
+
+{info.description}
+
+
+ ...
+
+
+"""
+```
+
+**Note:** This optimization is optional (YAGNI). Only implement if page load time is actually slow.
+
+**Commit:** (Optional) `Optimize: Lazy load Brython on interactive pages`
+
+---
+
+## Phase 14: Finalization
+
+### Task 14.1: Write Documentation for Contributors
+
+**What:** Document the doc system for future maintainers.
+
+**Files to create:**
+- `docs/contributing.md`
+- `CONTRIBUTING.md` (link to above)
+
+**Actions:**
+
+1. Create `docs/contributing.md`:
+
+```markdown
+# Contributing to plotille
+
+Thank you for contributing to plotille!
+
+## Documentation System
+
+The documentation is built with MkDocs and auto-deployed to https://plotille.tammo.io
+
+### Structure
+
+- `docs/` - Documentation source files (markdown)
+- `examples/` - Example scripts (auto-imported to docs)
+- `scripts/generate_docs.py` - Documentation generation script
+- `mkdocs.yml` - MkDocs configuration
+
+### Local Development
+
+1. Install dependencies:
+ ```bash
+ pip install -e ".[dev]"
+ ```
+
+2. Generate docs from examples:
+ ```bash
+ python scripts/generate_docs.py
+ ```
+
+3. Serve locally:
+ ```bash
+ mkdocs serve
+ ```
+
+4. Visit http://127.0.0.1:8000
+
+### Adding Examples
+
+1. Create a new `.py` file in `examples/`
+2. Add a docstring or comment at the top describing it
+3. Run `python scripts/generate_docs.py`
+4. The example will automatically appear in the cookbook
+
+Examples using only plotille + stdlib will be interactive in the browser.
+Examples using numpy, Pillow, etc. will show pre-rendered output.
+
+### Updating API Documentation
+
+API docs are auto-generated from docstrings using mkdocstrings.
+
+1. Update docstrings in `plotille/` source files
+2. Add examples using doctest format (`>>>`)
+3. Run tests: `pytest --doctest-modules plotille/`
+4. Rebuild docs: `mkdocs build`
+
+All doctest examples must pass before deploying.
+
+### Deployment
+
+Documentation auto-deploys on push to `master`:
+1. GitHub Actions runs tests
+2. Generates documentation
+3. Builds MkDocs site
+4. Deploys to gh-pages branch
+5. Available at https://plotille.tammo.io
+
+### Theme Customization
+
+The documentation uses a custom amber phosphor CRT theme:
+- Colors: `docs/stylesheets/terminal.css`
+- JavaScript: `docs/javascripts/`
+- Theme: Material for MkDocs with heavy customization
+```
+
+2. Create `CONTRIBUTING.md` at project root:
+
+```markdown
+# Contributing
+
+See the full contributing guide: https://plotille.tammo.io/contributing/
+```
+
+3. Update `mkdocs.yml` nav:
+
+```yaml
+nav:
+ - Home: index.md
+ - Cookbook:
+ - Basic Plots: cookbook/basic.md
+ - Complex Figures: cookbook/figures.md
+ - Canvas Drawing: cookbook/canvas.md
+ - Advanced Examples: cookbook/advanced.md
+ - API Reference:
+ - Overview: api/index.md
+ - Plotting Functions: api/plotting.md
+ - Figure: api/figure.md
+ - Canvas: api/canvas.md
+ - Contributing: contributing.md
+```
+
+**Commit:** `Add contributing documentation`
+
+---
+
+### Task 14.2: Final Testing and Launch
+
+**What:** Complete final testing before announcement.
+
+**Actions:**
+
+1. Work through complete testing checklist (Task 12.1)
+
+2. Test on multiple browsers and devices
+
+3. Check performance with browser DevTools
+
+4. Verify all links work (use link checker):
+```bash
+# Optional: install link checker
+# pip install linkchecker
+
+# Build site
+mkdocs build
+
+# Check links
+# linkchecker site/index.html
+```
+
+5. Get a fresh pair of eyes to review (if possible)
+
+**Commit:** `Final polish and testing`
+
+---
+
+### Task 14.3: Create Announcement
+
+**What:** Prepare announcement of new documentation.
+
+**Files to create:**
+- `docs/plans/launch-announcement.md`
+
+**Actions:**
+
+Create launch announcement draft:
+
+```markdown
+# plotille Documentation Launch
+
+New comprehensive documentation site now available at **https://plotille.tammo.io**!
+
+## What's New
+
+š„ļø **Interactive Examples** - Edit and run plotille code directly in your browser
+š **Complete API Reference** - Auto-generated from source with examples
+šØ **Terminal Aesthetic** - Amber phosphor CRT theme
+š **Searchable** - Find functions and examples quickly
+š± **Responsive** - Works on mobile and desktop
+
+## Highlights
+
+- **Cookbook-first approach** - Learn by example
+- **Live code editing** - Powered by Brython
+- **Tested documentation** - All examples verified with doctests
+- **Auto-deployed** - Always up to date with latest release
+
+Check it out: https://plotille.tammo.io
+
+---
+
+Technical details:
+- Built with MkDocs + mkdocstrings
+- Custom amber phosphor terminal theme
+- Interactive examples via Brython
+- Deployed via GitHub Actions to GitHub Pages
+```
+
+**Commit:** `Add launch announcement`
+
+---
+
+## Summary and Next Steps
+
+You've now implemented a complete documentation system for plotille!
+
+### What You Built
+
+1. ā **Documentation generator** - Analyzes and categorizes examples
+2. ā **Static pre-rendering** - Executes examples during build
+3. ā **Interactive examples** - Brython-powered browser execution
+4. ā **API reference** - Auto-generated with mkdocstrings
+5. ā **Terminal aesthetic** - Amber phosphor CRT theme
+6. ā **CI/CD pipeline** - Auto-deploy on push to main
+7. ā **Doctest integration** - Tested documentation examples
+
+### Commands Reference
+
+```bash
+# Generate documentation
+python scripts/generate_docs.py
+
+# Serve locally
+mkdocs serve
+
+# Build for production
+mkdocs build
+
+# Run doctests
+pytest --doctest-modules plotille/
+
+# Deploy (via CI)
+git push origin master
+```
+
+### Maintenance
+
+- **Add examples**: Just add `.py` files to `examples/`
+- **Update API docs**: Edit docstrings in `plotille/` source
+- **Theme changes**: Edit `docs/stylesheets/terminal.css`
+- **Behavior changes**: Edit `docs/javascripts/*.js`
+
+### Known Limitations
+
+1. **Brython compatibility**: Some Python features may not work in browser
+2. **External dependencies**: numpy/Pillow examples show pre-rendered output only
+3. **Performance**: Loading Brython adds ~500KB to page size
+4. **Browser support**: Requires modern browser with ES6 support
+
+### Future Enhancements (Optional)
+
+- Full CodeMirror 6 integration with syntax highlighting
+- Version switching (using mike plugin)
+- More sophisticated Brython output capture
+- Screenshot generation for social media sharing
+- Dark/light theme toggle
+- More examples and tutorials
+
+---
+
+## Troubleshooting
+
+### Common Issues
+
+**Problem**: `mkdocs serve` shows errors
+**Solution**: Check `mkdocs.yml` syntax with YAML linter
+
+**Problem**: Examples don't execute
+**Solution**: Check browser console for JavaScript errors
+
+**Problem**: Doctest failures
+**Solution**: Run `pytest --doctest-modules plotille/ -v` to see which tests fail
+
+**Problem**: GitHub Pages 404
+**Solution**: Verify gh-pages branch exists and contains built site
+
+**Problem**: Custom domain not working
+**Solution**: Check DNS propagation and CNAME file in gh-pages branch
+
+**Problem**: Fonts not loading
+**Solution**: Check network tab in browser DevTools, verify Google Fonts CDN accessible
+
+---
+
+## Testing Strategy for Each Phase
+
+Follow Test-Driven Development:
+
+1. **Unit tests first** - Write tests for utility functions
+2. **Integration tests** - Test script end-to-end
+3. **Manual testing** - Verify in browser
+4. **Commit frequently** - After each passing test
+
+### Example TDD Flow
+
+```bash
+# 1. Write test
+echo "def test_new_feature(): assert False" >> tests/test_generate_docs.py
+
+# 2. Run test (should fail)
+pytest tests/test_generate_docs.py::test_new_feature -v
+
+# 3. Implement feature
+# ... edit code ...
+
+# 4. Run test (should pass)
+pytest tests/test_generate_docs.py::test_new_feature -v
+
+# 5. Commit
+git add -A
+git commit -m "Add feature X with tests"
+```
+
+---
+
+**End of Implementation Plan**
+
+This plan provides complete step-by-step instructions for implementing the plotille documentation system. Follow each task sequentially, test thoroughly, and commit frequently. Good luck!
diff --git a/docs/plans/final-review.md b/docs/plans/final-review.md
new file mode 100644
index 0000000..c183692
--- /dev/null
+++ b/docs/plans/final-review.md
@@ -0,0 +1,240 @@
+# Final Review - Brython Implementation
+
+## Overall Assessment
+
+**Excellent work!** The implementer has successfully rewritten the Brython execution system with a much more robust approach. The build completes successfully and the infrastructure is in place for interactive examples.
+
+## ā What's Working Excellently
+
+### 1. Brython Execution Architecture āāā
+**Outstanding implementation** - Much better than the original plan:
+
+- **Permanent Python executor** (`brython-executor.py`) loaded once, runs all examples
+- **Clean separation** between Python (executor logic) and JavaScript (DOM interaction)
+- **Proper stdout capture** using custom `OutputCapture` class with `isatty()` support
+- **Error handling** with full tracebacks displayed to users
+- **Ready indicator** using polling to ensure executor is loaded before use
+
+**Key advantage:** This approach is more maintainable and follows Brython best practices.
+
+### 2. Local Brython Installation ā
+- Brython CDN replaced with local files (~5MB total)
+- Ensures consistent behavior and offline capability
+- Files: `docs/brython.js`, `docs/brython_stdlib.js`
+
+### 3. AnsiUp Integration for Colors ā
+- Added `ansi_up.js` for ANSI color code ā HTML conversion
+- Loaded as ES6 module and exposed to Python executor
+- Allows colored terminal output in browser (plotille uses ANSI codes)
+- `isatty() = True` in OutputCapture enables plotille colors
+
+### 4. Proper Brython Module Path ā
+- Plotille copied to `Lib/site-packages/plotille/` (Brython's standard location)
+- Brython automatically searches this path for imports
+- No need for custom pythonpath configuration
+
+### 5. Build Process Fixed ā
+- `generate_docs.py` completes successfully
+- `IsADirectoryError` bug fixed: `output_paths.get(info.name)` returns None properly
+- Static examples handled correctly with "Output not available" message
+- `__pycache__` excluded from plotille copy
+
+### 6. Minor Issues Fixed ā
+- CodeMirror check removed (was misleading)
+- Test page removed from navigation
+- Textarea enhancement works correctly
+
+## ā ļø One Issue Found
+
+### Hero Plot Generation Fails
+
+**Issue:** Home page shows:
+```
+Error generating plot: No module named 'plotille'
+```
+
+**Root Cause:** When `generate_docs.py` runs, it tries to `import plotille` to generate the hero plot, but plotille isn't in the Python path during script execution.
+
+**Previous State:** The plot was working earlier (git diff shows it had the actual sine wave plot with braille characters).
+
+**Why it broke:** Likely environment changed during one of the recent commits, or script is now run in different context.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+Update the `generate_hero_plot()` function to add the project root to sys.path:
+
+```python
+def generate_hero_plot() -> str:
+ """
+ Generate a sample plot for the hero animation.
+
+ Returns:
+ String containing plotille plot output
+ """
+ try:
+ import math
+ import sys
+ from pathlib import Path
+
+ # Add project root to path so plotille can be imported
+ project_root = Path(__file__).parent.parent
+ if str(project_root) not in sys.path:
+ sys.path.insert(0, str(project_root))
+
+ import plotille
+
+ X = [i / 10 for i in range(-31, 32)]
+ Y = [math.sin(x) for x in X]
+
+ plot_output = plotille.plot(
+ X,
+ Y,
+ width=60,
+ height=10,
+ X_label="X",
+ Y_label="",
+ )
+
+ return plot_output
+ except Exception as e:
+ # Fallback if generation fails
+ return f"Error generating plot: {e}"
+```
+
+**Test:**
+```bash
+python scripts/generate_docs.py
+# Should see actual plot in docs/index.md, not error message
+
+head -20 docs/index.md
+# Should see braille characters in the hero-plot section
+```
+
+**Commit:**
+```bash
+git add scripts/generate_docs.py docs/index.md
+git commit -m "Fix hero plot generation by adding project root to sys.path"
+```
+
+## š Final Testing Checklist
+
+Once the hero plot is fixed, verify everything works:
+
+### Build Process
+- [x] `python scripts/generate_docs.py` completes without errors
+- [x] No `__pycache__` in `docs/Lib/site-packages/plotille/`
+- [ ] Hero plot shows actual sine wave (after fix)
+- [x] Static examples show "Output not available" message
+- [x] Basic and Advanced cookbook pages generated
+
+### Browser Functionality
+Visit http://127.0.0.1:8000 and check:
+
+#### Home Page
+- [ ] Hero terminal shows sine wave plot (after fix)
+- [x] Quick start code block displays correctly
+- [x] Navigation shows Home, Cookbook sections
+
+#### Test Page (`/test-brython/`)
+- [ ] Click `[RUN]` button
+- [ ] Should see "Hello from Brython!" and "4" in output
+- [ ] No console errors
+
+#### Basic Cookbook (`/cookbook/basic/`)
+- [ ] Examples load with code in textareas
+- [ ] Tab key inserts 4 spaces
+- [ ] Click `[EXEC]` on simple example (e.g., `house_example`)
+- [ ] Output appears in terminal output area
+- [ ] Try editing code and re-running
+
+#### Advanced Cookbook (`/cookbook/advanced/`)
+- [x] Static examples show pre-rendered output or "not available" message
+- [x] Dependency warnings display correctly
+- [x] Code blocks format properly
+
+### Expected Limitations
+
+**Plotille examples may not all work in Brython:**
+- Brython has limited stdlib (some features plotille uses may not be available)
+- Unicode/braille handling might differ
+- ANSI color codes should work with AnsiUp
+
+**This is documented and acceptable:**
+- Simple Python examples (print, math, loops) should work ā
+- Plotille examples may work partially or not at all ā ļø
+- Static examples cover the not-working cases ā
+
+## šÆ Summary
+
+### What's Been Accomplished
+
+**Phase 5 (Terminal Theme):** ā Complete
+- Amber phosphor CRT aesthetic
+- Color contrast issues fixed
+- Terminal window styling
+
+**Phase 6 (Brython Integration):** ā Complete with improvements
+- Better implementation than original plan
+- Permanent executor script approach
+- Local Brython files
+- AnsiUp color support
+
+**Phase 7 (CodeMirror/Editor):** ā Complete
+- Textarea enhancement functional
+- Tab key support
+- Monospace font styling
+
+### Files Changed Summary
+
+**New Files:**
+- `docs/overrides/main.html` - Template override for Brython executor
+- `docs/javascripts/brython-executor.py` - Python code running in browser
+- `docs/javascripts/brython-setup.js` - JavaScript initialization
+- `docs/javascripts/codemirror-setup.js` - Textarea enhancements
+- `docs/brython.js` - Local Brython runtime
+- `docs/brython_stdlib.js` - Brython standard library
+- `docs/ansi_up.js` - ANSI color conversion
+- `docs/Lib/site-packages/plotille/` - Plotille for Brython
+
+**Modified Files:**
+- `scripts/generate_docs.py` - Fixed build bugs, added hero plot
+- `scripts/copy_plotille_for_brython.py` - Exclude pycache, use Lib/site-packages
+- `mkdocs.yml` - Local Brython, removed test from nav, custom_dir
+- `docs/stylesheets/terminal.css` - Color contrast fixes
+
+### Remaining Work
+
+**Immediate (5 minutes):**
+1. Fix hero plot sys.path issue
+
+**Next Phase (Not Started Yet):**
+- Phase 8: API Documentation with mkdocstrings
+- Phase 9: Navigation and Site Structure (partially done)
+- Phase 10: Hero Animation (partially done, needs fix)
+- Phase 11-14: CI/CD, testing, refinement
+
+### Code Quality Notes
+
+**Strengths:**
+- Clean separation of concerns
+- Good error handling
+- Follows Brython best practices
+- Well-commented code
+- ABOUTME headers present
+
+**No major issues found** - just the one hero plot import bug.
+
+---
+
+## Recommendation
+
+ā **Approve with one minor fix**
+
+The Brython implementation is excellent and actually better than what was originally planned. Once the hero plot import issue is fixed (5-minute change), this phase is complete and ready to proceed to Phase 8 (API Documentation).
+
+**Next Steps:**
+1. Apply hero plot fix
+2. Test in browser (especially plotille examples to see which work)
+3. Commit and proceed to Phase 8: API Documentation
+
+Great work by the implementer! The permanent executor approach is more elegant than the dynamic script creation approach in the original plan.
diff --git a/docs/plans/implementation-plan-updates.md b/docs/plans/implementation-plan-updates.md
new file mode 100644
index 0000000..8c6ebda
--- /dev/null
+++ b/docs/plans/implementation-plan-updates.md
@@ -0,0 +1,323 @@
+# Implementation Plan Updates - Simplified CSS Approach
+
+## Changes to Original Plan
+
+This document updates `documentation-system-implementation.md` to reflect the simplified approach of using standard Material theme instead of custom amber phosphor CRT aesthetic.
+
+---
+
+## Phase 5: Terminal Window Styling (REVISED)
+
+### Task 5.1: Create Minimal Terminal Window Styling (REPLACES OLD TASK 5.1)
+
+**What:** Style only the terminal window components for interactive examples. Use standard Material theme for everything else.
+
+**Files to create:**
+- `docs/stylesheets/terminal.css` (minimal, ~120 lines)
+
+**Actions:**
+
+1. Create `docs/stylesheets/terminal.css`:
+
+```css
+/*
+ * ABOUTME: Terminal window styling for plotille interactive examples.
+ * ABOUTME: Uses standard Material theme for everything except terminal components.
+ */
+
+:root {
+ --terminal-bg: #1e1e1e;
+ --terminal-fg: #d4d4d4;
+ --terminal-border: #3e3e3e;
+ --terminal-header-bg: #2d2d2d;
+ --terminal-button-bg: #0e639c;
+ --terminal-button-hover: #1177bb;
+}
+
+.terminal-window {
+ background: var(--terminal-bg);
+ border: 1px solid var(--terminal-border);
+ border-radius: 6px;
+ margin: 1.5rem 0;
+ overflow: hidden;
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+}
+
+.terminal-header {
+ background: var(--terminal-header-bg);
+ padding: 0.5rem 1rem;
+ border-bottom: 1px solid var(--terminal-border);
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+}
+
+.terminal-title {
+ color: var(--terminal-fg);
+ font-size: 0.85rem;
+ font-weight: 500;
+}
+
+.terminal-run-btn {
+ background: var(--terminal-button-bg);
+ color: #ffffff;
+ border: none;
+ padding: 0.25rem 0.75rem;
+ border-radius: 3px;
+ cursor: pointer;
+ font-size: 0.85rem;
+ font-weight: 500;
+ transition: background 0.2s;
+}
+
+.terminal-run-btn:hover {
+ background: var(--terminal-button-hover);
+}
+
+.terminal-body {
+ padding: 1rem;
+ background: var(--terminal-bg);
+}
+
+.code-editor-wrapper {
+ border: 1px solid var(--terminal-border);
+ border-radius: 4px;
+ overflow: hidden;
+}
+
+.code-editor {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+ background: var(--terminal-bg);
+ color: var(--terminal-fg);
+ width: 100%;
+ min-height: 300px;
+ padding: 1rem;
+ border: none;
+ resize: vertical;
+ line-height: 1.5;
+ tab-size: 4;
+}
+
+.code-editor:focus {
+ outline: none;
+ box-shadow: 0 0 0 2px var(--terminal-button-bg);
+}
+
+.terminal-output {
+ font-family: 'Consolas', 'Monaco', 'Courier New', monospace;
+ color: var(--terminal-fg);
+ white-space: pre-wrap;
+ margin-top: 1rem;
+ line-height: 1.4;
+ max-height: 600px;
+ overflow-y: auto;
+}
+
+.terminal-prompt {
+ color: #4ec9b0;
+ display: block;
+ margin-bottom: 0.5rem;
+}
+
+.output-content {
+ margin-top: 0.5rem;
+}
+
+.output-content.error {
+ color: #f48771;
+}
+
+.hero-terminal {
+ margin: 2rem 0;
+}
+
+.hero-plot {
+ font-size: 0.75rem;
+}
+```
+
+2. Update `mkdocs.yml` to use standard Material theme:
+
+```yaml
+site_name: plotille
+site_url: https://plotille.tammo.io
+site_description: Plot in the terminal using braille dots
+site_author: Tammo Ippen
+repo_url: https://github.com/tammoippen/plotille
+repo_name: tammoippen/plotille
+
+theme:
+ name: material
+ features:
+ - content.code.copy
+ - navigation.sections
+ - navigation.top
+ - search.suggest
+ - search.highlight
+
+plugins:
+ - search
+ - mkdocstrings:
+ handlers:
+ python:
+ options:
+ docstring_style: google
+ show_source: true
+ show_signature_annotations: true
+ separate_signature: true
+
+markdown_extensions:
+ - pymdownx.highlight:
+ anchor_linenums: true
+ - pymdownx.superfences
+ - admonition
+ - pymdownx.details
+
+extra_css:
+ - stylesheets/terminal.css
+
+extra_javascript:
+ - brython.js
+ - brython_stdlib.js
+ - ansi_up.js
+ - javascripts/codemirror-setup.js
+ - javascripts/brython-setup.js
+
+nav:
+ - Home: index.md
+ - Cookbook:
+ - Basic Plots: cookbook/basic.md
+ - Advanced Examples: cookbook/advanced.md
+```
+
+3. Update `.gitignore`:
+
+```gitignore
+# Site build output
+site/
+
+# Documentation build artifacts
+docs/Lib/
+docs/assets/example-outputs/
+```
+
+4. Remove build artifacts from git:
+
+```bash
+git rm -r --cached docs/Lib/
+git rm -r --cached docs/assets/example-outputs/
+```
+
+**Test:**
+```bash
+python scripts/generate_docs.py
+mkdocs serve
+# Visit http://127.0.0.1:8000
+# Verify:
+# - Standard Material theme (clean, professional)
+# - Terminal windows look like terminals (dark, monospace)
+# - Everything readable and accessible
+# - Search works with default styling
+# - Code blocks use Material's syntax highlighting
+```
+
+**Commit:** `Add minimal terminal window styling with standard Material theme`
+
+**Design Goals:**
+- **Simplicity:** ~120 lines of CSS vs 547
+- **Maintainability:** Only style what's necessary
+- **Accessibility:** Use Material's tested, accessible defaults
+- **Clarity:** Clear visual distinction between docs and terminals
+
+---
+
+### Task 5.2: REMOVED
+
+Font bundling task is no longer needed - use system/browser default fonts via Material theme.
+
+---
+
+## Phase 10: Hero Animation (SIMPLIFIED)
+
+### Task 10.1: SIMPLIFIED - Static Hero Plot
+
+The original task included JavaScript animation. Simplified version:
+
+**What:** Display a static plotille plot on the home page. No animation needed.
+
+**This is already implemented** in `generate_home_page()` which generates the hero plot. The plot appears in the hero-terminal div which is styled by the minimal terminal.css.
+
+**No additional work needed** for this task. The hero plot is generated during `python scripts/generate_docs.py` and displayed in a terminal window styled by terminal.css.
+
+---
+
+## Removed Sections
+
+The following sections from the original plan are **NO LONGER NEEDED**:
+
+### From Phase 5:
+- ā All the "amber phosphor color palette" variables
+- ā Global font imports (VT323, IBM Plex Mono)
+- ā CRT scanline effects
+- ā Global Material theme overrides
+- ā Custom navigation styling
+- ā Custom header styling
+- ā Custom search styling
+- ā Syntax highlighting overrides
+- ā Admonition overrides
+
+### From Phase 10:
+- ā JavaScript hero animation (keep static plot)
+- ā Character-by-character reveal animation
+- ā `docs/javascripts/hero-animation.js` file
+
+---
+
+## What Stays the Same
+
+These phases are **unchanged**:
+
+- **Phase 1:** Project Setup & Dependencies ā
+- **Phase 2:** Example Analysis & Classification ā
+- **Phase 3:** Static Example Pre-rendering ā
+- **Phase 4:** Markdown Generation ā
+- **Phase 6:** Brython Integration ā
+- **Phase 7:** CodeMirror/Editor Enhancement ā
+- **Phase 8:** API Documentation ā
+- **Phase 9:** Navigation (already minimal) ā
+- **Phase 11:** GitHub Actions CI/CD ā
+- **Phase 12-14:** Testing, refinement, launch ā
+
+---
+
+## Summary of Changes
+
+**Philosophy Change:**
+- **Old:** Custom amber phosphor CRT theme everywhere
+- **New:** Standard Material theme, terminal styling only for terminals
+
+**CSS Reduction:**
+- **Old:** 547 lines of global overrides
+- **New:** 120 lines of terminal-only styling
+
+**Visual Design:**
+- **Old:** Amber on black everywhere, CRT effects, custom fonts
+- **New:** Material's defaults everywhere, terminal windows look like VS Code terminals
+
+**Maintenance:**
+- **Old:** Fight Material's updates, maintain custom syntax highlighting
+- **New:** Ride Material's updates, zero maintenance on theme
+
+**Benefits:**
+- Simpler implementation
+- Better readability
+- More accessible
+- Easier to maintain
+- Faster page loads
+- Professional appearance
+
+**Trade-offs:**
+- Less "unique" visual identity
+- No retro CRT aesthetic
+
+**Conclusion:** The simplified approach better serves the primary goal: **documenting plotille clearly and making it easy for users to try examples interactively.**
diff --git a/docs/plans/implementation-review.md b/docs/plans/implementation-review.md
new file mode 100644
index 0000000..96f1555
--- /dev/null
+++ b/docs/plans/implementation-review.md
@@ -0,0 +1,448 @@
+# Documentation Implementation Review
+
+## Overall Assessment
+
+Excellent progress on Tasks 4.2, 4.3, and 5.1! The structure is solid and the amber phosphor theme foundation is in place. However, there are several issues that need to be addressed before proceeding to the next phase.
+
+**Dev server is running at:** http://127.0.0.1:8000
+
+---
+
+## Critical Issues (Must Fix Before Proceeding)
+
+### 1. Color Contrast Problems - CRITICAL ā
+
+**Issue:** The current color scheme has severe readability issues:
+- White/light text on yellow backgrounds is not readable
+- H1 headers appear to have black font with yellow shadow/glow, making them unreadable
+- Material theme overrides are creating poor contrast combinations
+
+**Root Cause:** The CSS is setting Material theme primary colors to amber, which Material then uses for backgrounds in some components. This creates amber-on-amber or light-on-amber combinations.
+
+**Fix Required in `docs/stylesheets/terminal.css`:**
+
+```css
+/* Global overrides for Material theme */
+[data-md-color-scheme="plotille"] {
+ /* Keep amber for accents, but use proper backgrounds */
+ --md-primary-fg-color: var(--amber-base);
+ --md-primary-fg-color--light: var(--amber-bright);
+ --md-primary-fg-color--dark: var(--amber-dim);
+ --md-accent-fg-color: var(--amber-bright);
+
+ /* Force dark backgrounds with amber text */
+ --md-default-bg-color: var(--amber-black);
+ --md-default-fg-color: var(--amber-base);
+ --md-code-bg-color: var(--amber-dark);
+ --md-code-fg-color: var(--amber-base);
+
+ /* Add these to prevent light backgrounds */
+ --md-typeset-a-color: var(--amber-bright);
+ --md-typeset-color: var(--amber-base);
+}
+
+/* Ensure headers are always readable */
+h1, h2, h3, h4, h5, h6 {
+ font-family: 'VT323', monospace;
+ color: var(--amber-bright) !important;
+ background: transparent !important;
+ text-shadow: 0 0 8px var(--amber-glow);
+ letter-spacing: 0.05em;
+}
+
+/* Force main content area to be dark */
+.md-main,
+.md-content,
+.md-content__inner {
+ background-color: var(--amber-black) !important;
+ color: var(--amber-base) !important;
+}
+
+/* Ensure sidebar is dark */
+.md-sidebar {
+ background-color: var(--amber-black) !important;
+}
+
+/* Links should be bright amber and underlined for visibility */
+a {
+ color: var(--amber-bright) !important;
+ text-decoration: underline;
+}
+
+a:hover {
+ color: var(--amber-bright) !important;
+ text-shadow: 0 0 10px var(--amber-glow);
+}
+```
+
+**Test:** After applying, verify that:
+- All text is readable (amber on black, never black on amber)
+- Headers are bright amber with glow effect
+- No white or light backgrounds appear anywhere
+- Links are clearly visible
+
+---
+
+### 2. `__init__.py` Being Treated as Example ā
+
+**Issue:** The file `examples/__init__.py` is being processed and appears in `basic.md` as "## __init__" with empty content.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+In the `main()` function, modify the loop to skip `__init__.py`:
+
+```python
+# Analyze all Python files
+examples = []
+for example_file in sorted(examples_dir.glob("*.py")):
+ # Skip __init__.py files
+ if example_file.name == "__init__.py":
+ continue
+ info = analyze_example(example_file)
+ examples.append(info)
+```
+
+**Test:** Run `python scripts/generate_docs.py` and verify `__init__` no longer appears in `docs/cookbook/basic.md`.
+
+---
+
+### 3. Performance Example Should Not Be in Cookbook ā
+
+**Issue:** `performance_example.py` appears in `basic.md` but it's not a useful example for users - it's for internal performance testing.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+Add performance examples to the skip list:
+
+```python
+# Analyze all Python files
+examples = []
+SKIP_EXAMPLES = {"__init__.py", "performance_example.py"}
+
+for example_file in sorted(examples_dir.glob("*.py")):
+ # Skip files that aren't user-facing examples
+ if example_file.name in SKIP_EXAMPLES:
+ continue
+ info = analyze_example(example_file)
+ examples.append(info)
+```
+
+**Test:** Verify `performance_example` no longer appears in the generated cookbook pages.
+
+---
+
+### 4. License Headers in Examples ā
+
+**Issue:** All examples include the full MIT license header (23 lines), which clutters the documentation. Users don't need to see this in the browser.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+Add a function to strip license headers:
+
+```python
+def strip_license_header(source_code: str) -> str:
+ """
+ Remove MIT license header from source code.
+
+ Args:
+ source_code: Python source code possibly containing license header
+
+ Returns:
+ Source code with license header removed
+ """
+ lines = source_code.split('\n')
+
+ # Look for MIT license pattern
+ if '# The MIT License' in source_code:
+ # Find the end of the license block (first non-comment/non-blank line after license)
+ in_license = False
+ start_index = 0
+
+ for i, line in enumerate(lines):
+ stripped = line.strip()
+
+ # Start of license
+ if 'MIT License' in line:
+ in_license = True
+ start_index = i
+ continue
+
+ # End of license block (first non-comment, non-blank line)
+ if in_license and stripped and not stripped.startswith('#'):
+ # Remove everything from start_index to just before this line
+ return '\n'.join(lines[i:])
+
+ # If we didn't find the end, remove first 23 lines (typical license length)
+ if in_license:
+ return '\n'.join(lines[23:])
+
+ return source_code
+```
+
+Then update `generate_interactive_example_markdown()` and `generate_static_example_markdown()`:
+
+```python
+def generate_interactive_example_markdown(info: ExampleInfo) -> str:
+ """Generate markdown for an interactive example."""
+ source_code = info.path.read_text()
+
+ # Strip license header
+ source_code = strip_license_header(source_code)
+
+ # Escape backticks in code for markdown
+ escaped_code = source_code.replace("```", "\\`\\`\\`")
+
+ # ... rest of function ...
+```
+
+```python
+def generate_static_example_markdown(info: ExampleInfo, output_path: Path) -> str:
+ """Generate markdown for a static example with pre-rendered output."""
+ source_code = info.path.read_text()
+
+ # Strip license header
+ source_code = strip_license_header(source_code)
+
+ # Read pre-rendered output
+ # ... rest of function ...
+```
+
+**Test:** Verify examples in cookbook pages start with `import` statements, not license headers.
+
+---
+
+### 5. Hero Plot is Empty ā
+
+**Issue:** The home page has `` but it's empty. According to the plan (Task 10.1), the hero should display an actual plotille sine wave.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+Add the `generate_hero_plot()` function:
+
+```python
+def generate_hero_plot() -> str:
+ """
+ Generate a sample plot for the hero animation.
+
+ Returns:
+ String containing plotille plot output
+ """
+ try:
+ import plotille
+ import math
+
+ X = [i / 10 for i in range(-31, 32)]
+ Y = [math.sin(x) for x in X]
+
+ plot_output = plotille.plot(
+ X, Y,
+ width=60,
+ height=10,
+ X_label='X',
+ Y_label='',
+ )
+
+ return plot_output
+ except Exception as e:
+ # Fallback if generation fails
+ return f"Error generating plot: {e}"
+```
+
+Then update `generate_home_page()`:
+
+```python
+def generate_home_page(docs_dir: Path) -> Path:
+ """Generate the home/index page."""
+ # Generate the hero plot
+ hero_plot = generate_hero_plot()
+
+ # Change to f-string to include hero_plot
+ content = f"""# plotille
+
+
+
+ [root@plotille ~]$
+
+
+
{hero_plot}
+
+
+
+Plot in the terminal using braille dots, with no dependencies.
+
+## Features
+
+- **Scatter plots, line plots, histograms** - Basic plotting functions
+- **Complex figures** - Compose multiple plots with legends
+- **Canvas drawing** - Direct pixel manipulation for custom visualizations
+- **Image rendering** - Display images using braille dots or background colors
+- **Color support** - Multiple color modes: names, byte values, RGB
+- **No dependencies** - Pure Python with no external requirements
+
+## Quick Start
+
+Install plotille:
+
+```bash
+pip install plotille
+```
+
+Create your first plot:
+
+```python
+import plotille
+import math
+
+X = [i/10 for i in range(-30, 30)]
+Y = [math.sin(x) for x in X]
+
+print(plotille.plot(X, Y, height=20, width=60))
+```
+
+## Explore
+
+Browse the [cookbook](cookbook/basic.md) to see interactive examples you can edit and run in your browser.
+
+"""
+
+ index_file = docs_dir / "index.md"
+ index_file.write_text(content)
+ return index_file
+```
+
+**Test:** Verify home page shows a sine wave plot in the hero terminal.
+
+---
+
+### 6. Navigation Incomplete ā ļø
+
+**Issue:** `mkdocs.yml` only lists `- Home: index.md`. The cookbook pages should be in the navigation.
+
+**Fix Required in `mkdocs.yml`:**
+
+Update the `nav` section:
+
+```yaml
+nav:
+ - Home: index.md
+ - Cookbook:
+ - Basic Plots: cookbook/basic.md
+ - Advanced Examples: cookbook/advanced.md
+```
+
+**Note:** Only `basic` and `advanced` categories exist because no examples matched `figures` or `canvas` patterns. This is correct behavior based on the current examples.
+
+**Test:** Verify navigation sidebar shows Home and Cookbook sections.
+
+---
+
+## Expected Issue (Not Yet Implemented)
+
+### 7. `runExample is not defined` Error ā Expected
+
+**Issue:** Clicking `[EXEC]` buttons in examples shows:
+```
+Uncaught ReferenceError: runExample is not defined
+```
+
+**Reason:** This is expected! Brython integration (Phase 6) hasn't been implemented yet. The HTML structure is in place, but the JavaScript to make it work comes in Tasks 6.1-6.2 and Task 7.2.
+
+**Do NOT fix this yet.** This will be handled in:
+- Task 6.1: Add Brython runtime and setup JavaScript
+- Task 7.2: Implement proper Brython execution with output capture
+
+**For now:** The buttons are non-functional, which is correct for this stage.
+
+---
+
+## How to Apply Fixes
+
+### Step 1: Update `scripts/generate_docs.py`
+
+Apply fixes for issues #2, #3, #4, and #5:
+
+1. Add `strip_license_header()` function
+2. Update example loop to skip `__init__.py` and `performance_example.py`
+3. Update both markdown generation functions to call `strip_license_header()`
+4. Add `generate_hero_plot()` function
+5. Update `generate_home_page()` to use `generate_hero_plot()` and f-strings
+
+### Step 2: Update `docs/stylesheets/terminal.css`
+
+Apply fix for issue #1 (color contrast):
+
+1. Add `!important` to critical background/foreground rules
+2. Add explicit rules for `.md-main`, `.md-content`, `.md-sidebar`
+3. Fix link styling for visibility
+4. Ensure headers always have proper contrast
+
+### Step 3: Update `mkdocs.yml`
+
+Apply fix for issue #6 (navigation):
+
+1. Add Cookbook section with basic and advanced pages
+
+### Step 4: Regenerate and Test
+
+```bash
+# Regenerate documentation with all fixes
+python scripts/generate_docs.py
+
+# Verify changes
+cat docs/index.md | grep "hero-plot" # Should contain plot output
+grep -c "MIT License" docs/cookbook/basic.md # Should be 0
+grep -c "__init__" docs/cookbook/basic.md # Should be 0
+grep -c "performance_example" docs/cookbook/basic.md # Should be 0
+
+# Check site in browser (server should auto-reload)
+# Visit http://127.0.0.1:8000
+```
+
+### Step 5: Commit
+
+```bash
+git add scripts/generate_docs.py docs/ mkdocs.yml
+git commit -m "Fix color contrast, filter unwanted examples, add hero plot, update nav"
+```
+
+---
+
+## Testing Checklist
+
+After applying all fixes, verify in browser at http://127.0.0.1:8000:
+
+### Color & Contrast
+- [ ] All text is readable (amber on black throughout)
+- [ ] Headers are bright amber, clearly visible
+- [ ] No white or light backgrounds anywhere
+- [ ] Links are underlined and bright amber
+- [ ] Terminal windows have proper amber/black contrast
+- [ ] Sidebar is dark with amber text
+
+### Content
+- [ ] Home page shows sine wave plot in hero terminal
+- [ ] No `__init__` example in basic cookbook
+- [ ] No `performance_example` in basic cookbook
+- [ ] Examples start with imports, not license headers
+- [ ] Navigation shows "Home" and "Cookbook" sections
+- [ ] Cookbook has "Basic Plots" and "Advanced Examples" pages
+
+### Expected Non-Working Features (OK for now)
+- [ ] `[EXEC]` buttons show "runExample is not defined" error (expected - will be fixed in Phase 6)
+
+---
+
+## Summary
+
+**Total fixes needed:** 6 critical issues
+
+**Files to modify:**
+1. `scripts/generate_docs.py` - Issues #2, #3, #4, #5
+2. `docs/stylesheets/terminal.css` - Issue #1
+3. `mkdocs.yml` - Issue #6
+
+**Estimated time:** 30-45 minutes
+
+Once these fixes are applied and tested, you're ready to proceed with **Phase 6: Brython Integration** (Tasks 6.1-6.2) which will make the `[EXEC]` buttons functional.
+
+Great work so far! The foundation is solid - these are just refinements to get the styling and content filtering right before moving forward.
diff --git a/docs/plans/phase11-12-review.md b/docs/plans/phase11-12-review.md
new file mode 100644
index 0000000..2fd376c
--- /dev/null
+++ b/docs/plans/phase11-12-review.md
@@ -0,0 +1,355 @@
+# Phase 11-12 Implementation Review
+
+## Overall Assessment
+
+Good work on completing Tasks 11.1, 12.1, 12.2, and 12.3! The implementation is mostly solid with clear documentation and proper error handling. The workflow is well-structured and the testing checklist is comprehensive.
+
+**Status:**
+- ā Task 11.1: GitHub Actions workflow created
+- ā Task 12.1: Testing checklist created
+- ā Task 12.2: Error styling enhanced
+- ā Task 12.3: README updated with documentation link
+- ā Tasks 9.2 and 10: Correctly skipped (outdated/already done)
+
+---
+
+## What's Working Well ā
+
+### 1. GitHub Actions Workflow - Good Quality
+
+**File:** `.github/workflows/docs.yml`
+
+**Strengths:**
+- ā Clear, descriptive job name: "Build and Deploy Documentation"
+- ā Dual triggers: push to master + manual dispatch
+- ā Proper permissions set (`contents: write`)
+- ā Uses modern action versions (checkout@v4, setup-python@v5)
+- ā Full git history fetched (`fetch-depth: 0`)
+- ā Python 3.11 specified (good version choice)
+- ā Correct dependency installation: `pip install -e ".[dev]"`
+- ā Tests run before docs build (fail fast on broken tests)
+- ā Includes doctests: `pytest --doctest-modules plotille/ -v`
+- ā Generates docs with custom script
+- ā Uses `mkdocs build --strict` (catches warnings as errors)
+- ā Deploys to gh-pages using standard action
+- ā CNAME configured for custom domain: plotille.tammo.io
+- ā Clean, well-commented, easy to understand
+
+**Quality:** Professional implementation following GitHub Actions best practices.
+
+### 2. Error Styling - Well Implemented
+
+**File:** `docs/stylesheets/terminal.css`
+
+**Added features:**
+```css
+/* Error output styling */
+.terminal-output .error {
+ color: #ff6b6b;
+ background: rgba(255, 0, 0, 0.1);
+ border-left: 3px solid #ff6b6b;
+ padding-left: 0.5rem;
+}
+
+.output-content.error {
+ color: #ff6b6b;
+}
+
+/* Loading state */
+.terminal-output .loading::after {
+ content: '...';
+ animation: loading 1.5s infinite;
+}
+
+@keyframes loading {
+ 0%, 100% { opacity: 0; }
+ 50% { opacity: 1; }
+}
+```
+
+**Strengths:**
+- ā Clear visual distinction for errors (red color, background, left border)
+- ā Subtle, professional styling (not garish)
+- ā Loading animation provides feedback during execution
+- ā Uses standard red error color (#ff6b6b - soft red, good contrast)
+- ā Animation is smooth and not distracting
+- ā Follows the minimal CSS philosophy
+
+**Quality:** Clean, effective, and consistent with Material theme approach.
+
+### 3. README Documentation Section - Clear and Concise
+
+**File:** `README.md`
+
+**Content:**
+```markdown
+## Documentation
+
+š **Full documentation available at [plotille.tammo.io](https://plotille.tammo.io)**
+
+Features:
+- **Interactive examples** - Edit and run code in your browser
+- **Complete API reference** - Auto-generated from source
+- **Cookbook** - Examples organized by complexity
+```
+
+**Strengths:**
+- ā Prominent placement at top of README
+- ā Clear link to documentation site
+- ā Emoji makes it stand out
+- ā Highlights key features users will find valuable
+- ā Concise - doesn't overwhelm
+- ā Encourages exploration
+
+**Quality:** Effective marketing of the documentation.
+
+### 4. Testing Checklist - Comprehensive
+
+**File:** `docs/plans/testing-checklist.md`
+
+**Coverage includes:**
+- Visual design (updated for Material theme)
+- Navigation
+- Home page
+- Cookbook pages
+- Interactive examples
+- API reference
+- Doctests
+- Build process
+- CI/CD
+- Performance
+- Browser compatibility
+
+**Strengths:**
+- ā 75 specific checkpoints
+- ā Covers all major areas
+- ā Organized by section
+- ā Includes technical tests (pytest commands)
+- ā Includes UX tests (browser compatibility)
+- ā Updated to reflect Material theme (not amber phosphor)
+
+---
+
+## Issues Found ā ļø
+
+### Issue 1: Testing Checklist Outdated Reference
+
+**Problem:** Line 22 in `docs/plans/testing-checklist.md`:
+
+```markdown
+- [ ] All four category pages exist (basic, figures, canvas, advanced)
+```
+
+**Reality:** Only two category pages exist (basic, advanced). We removed figures and canvas from navigation because they don't have examples.
+
+**Impact:** Minor - someone following the checklist will be confused.
+
+**Fix:**
+
+Change line 22 from:
+```markdown
+- [ ] All four category pages exist (basic, figures, canvas, advanced)
+```
+
+To:
+```markdown
+- [ ] Both cookbook pages exist (basic, advanced)
+```
+
+And change line 23:
+```markdown
+- [ ] Examples are categorized correctly
+```
+
+To:
+```markdown
+- [ ] Examples are categorized correctly (basic for interactive, advanced for static)
+```
+
+---
+
+### Issue 2: Potential Dependency Management Discrepancy (Minor)
+
+**Observation:** The project uses `uv` (has `uv.lock` file) locally, but the GitHub Actions workflow uses `pip`.
+
+**Current workflow:**
+```yaml
+- name: Install dependencies
+ run: |
+ python -m pip install --upgrade pip
+ pip install -e ".[dev]"
+```
+
+**Why this might matter:**
+- `uv` might have different dependency resolution than `pip`
+- Could lead to "works locally, fails in CI" scenarios
+- `uv` is much faster than `pip`
+
+**Impact:**
+- Low - likely to work fine since dependencies are well-specified
+- Could cause occasional CI failures if pip resolves differently than uv
+
+**Options:**
+
+**Option A:** Keep as-is (pip in CI)
+- Simpler, more standard
+- Works with GitHub's Python setup action
+- Good enough for most projects
+
+**Option B:** Use uv in CI (more consistent)
+```yaml
+- name: Set up Python and uv
+ uses: astral-sh/setup-uv@v3
+ with:
+ version: "latest"
+
+- name: Install dependencies
+ run: |
+ uv sync --dev
+```
+
+**Recommendation:**
+- **Keep Option A for now** (current implementation)
+- Only switch to uv if you encounter actual dependency resolution issues
+- This follows YAGNI principle
+
+**Not a bug**, just a consideration for future if issues arise.
+
+---
+
+## Testing Recommendations
+
+Before the workflow runs on GitHub, test locally:
+
+### 1. Test Workflow Steps Locally
+
+```bash
+# 1. Test dependency installation
+pip install -e ".[dev]"
+
+# 2. Test pytest with doctests
+pytest --doctest-modules plotille/ -v
+
+# 3. Test doc generation
+python scripts/generate_docs.py
+
+# 4. Test mkdocs build with strict mode
+mkdocs build --strict
+
+# 5. Verify site directory created
+ls -la site/
+
+# 6. Test site locally
+mkdocs serve
+# Visit http://127.0.0.1:8000 and test interactive examples
+```
+
+### 2. Verify Error Styling
+
+```bash
+mkdocs serve
+# Visit http://127.0.0.1:8000/cookbook/basic/
+# Click [EXEC] on an example
+# Modify code to cause an error (e.g., undefined variable)
+# Run it
+# Verify error displays with red styling and left border
+```
+
+### 3. Check README Rendering
+
+Visit your GitHub repository page and verify:
+- Documentation section is visible
+- Link works (after site is deployed)
+- Formatting looks good
+
+### 4. Test Workflow Validation
+
+```bash
+# Validate workflow YAML syntax
+# (GitHub has strict YAML parsing)
+python -c "import yaml; yaml.safe_load(open('.github/workflows/docs.yml'))"
+
+# Or use actionlint if available
+# brew install actionlint
+# actionlint .github/workflows/docs.yml
+```
+
+---
+
+## GitHub Pages Setup (Task 11.2)
+
+**Note:** This needs to be done manually in the GitHub web interface.
+
+**Steps:**
+
+1. Push the `docs` branch to GitHub:
+```bash
+git push origin docs
+```
+
+2. Go to repository Settings ā Pages
+
+3. Under "Build and deployment":
+ - Source: "Deploy from a branch"
+ - Branch: Select `gh-pages` (will be created by workflow)
+ - Folder: `/ (root)`
+
+4. Under "Custom domain":
+ - Enter: `plotille.tammo.io`
+ - Wait for DNS check
+
+5. Enable "Enforce HTTPS" once DNS check passes
+
+6. **DNS Configuration** (at your domain registrar):
+ - Add CNAME record:
+ - Host: `plotille`
+ - Points to: `tammoippen.github.io`
+
+7. **Trigger the workflow:**
+ - Merge `docs` branch to `master`, OR
+ - Manually trigger via Actions tab ā "Build and Deploy Documentation" ā Run workflow
+
+8. **Verify deployment:**
+ - Check Actions tab for successful run
+ - Visit https://plotille.tammo.io (after DNS propagates)
+
+---
+
+## Summary
+
+**Completed Successfully:**
+- ā GitHub Actions workflow with all necessary steps
+- ā Testing checklist with 75+ checkpoints
+- ā Error and loading state styling for terminal
+- ā README updated with clear documentation link
+- ā All code committed to docs branch
+
+**Needs Attention:**
+- ā ļø Update testing checklist (line 22-23) to reflect reality (2 cookbook pages, not 4)
+
+**Considerations for Future:**
+- š” Potential pip vs uv discrepancy (not urgent, only if issues arise)
+
+**Quality Assessment:**
+- Code quality: Very good
+- Documentation: Clear and comprehensive
+- Workflow structure: Professional
+- Following standards: Yes
+- Ready for deployment: Yes (after checklist fix)
+
+**Time to fix:** 2 minutes (edit testing checklist)
+
+---
+
+## Next Steps
+
+1. **Fix testing checklist** (update lines 22-23)
+2. **Test workflow locally** (run all 5 steps)
+3. **Push to GitHub** (`git push origin docs`)
+4. **Merge to master** (or create PR)
+5. **Configure GitHub Pages** (Task 11.2 - manual steps above)
+6. **Wait for workflow to run** (check Actions tab)
+7. **Verify site** (visit plotille.tammo.io after DNS propagates)
+8. **Run through testing checklist** (docs/plans/testing-checklist.md)
+
+The implementation is production-ready and follows best practices. Great work!
diff --git a/docs/plans/phase6-7-review.md b/docs/plans/phase6-7-review.md
new file mode 100644
index 0000000..b1e0b76
--- /dev/null
+++ b/docs/plans/phase6-7-review.md
@@ -0,0 +1,364 @@
+# Phase 6-7 Implementation Review
+
+## Overall Assessment
+
+Good progress on Tasks 5.2-7.1, but there are **critical bugs** that prevent the documentation from building, plus the Brython implementation needs completion of Task 7.2. The infrastructure is mostly in place but needs fixes before it can work.
+
+**Current Status:**
+- ā Task 5.2: Font bundling skipped (correct per YAGNI)
+- ā Task 6.1: Brython runtime added
+- ā Task 6.2: Plotille source copied successfully
+- ā Task 7.1: Textarea enhancement added
+- ā Task 7.2: **NOT COMPLETED** - This is required for Brython to actually work
+
+---
+
+## Critical Issues (Build-Breaking)
+
+### 1. Documentation Build Crashes ā **CRITICAL**
+
+**Issue:** Running `python scripts/generate_docs.py` crashes with:
+```
+IsADirectoryError: [Errno 21] Is a directory: '.'
+```
+
+**Root Cause:** When static examples fail to execute (because numpy/PIL aren't installed), they don't get added to `output_paths` dict. Then `generate_category_page()` calls:
+```python
+output_path = output_paths.get(info.name, Path())
+```
+
+This returns `Path()` which is `.` (current directory). Later, `generate_static_example_markdown()` checks:
+```python
+if output_path.exists():
+ output = output_path.read_text()
+```
+
+`Path('.')` exists (as a directory), so it tries to read a directory as a file ā crash.
+
+**Fix Required in `scripts/generate_docs.py`:**
+
+Change `generate_category_page()`:
+
+```python
+def generate_category_page(
+ category: str,
+ examples: list[ExampleInfo],
+ output_paths: dict[str, Path],
+ docs_dir: Path,
+) -> Path:
+ """Generate a markdown page for a category of examples."""
+ # ... existing code ...
+
+ # Add each example
+ for info in examples:
+ if info.is_interactive:
+ markdown = generate_interactive_example_markdown(info)
+ else:
+ # FIX: Pass None if output doesn't exist, not Path()
+ output_path = output_paths.get(info.name) # Returns None if not found
+ markdown = generate_static_example_markdown(info, output_path)
+
+ content.append(markdown)
+
+ # ... rest of function ...
+```
+
+And update `generate_static_example_markdown()`:
+
+```python
+def generate_static_example_markdown(
+ info: ExampleInfo,
+ output_path: Path | None, # Allow None
+) -> str:
+ """Generate markdown for a static example with pre-rendered output."""
+ source_code = info.path.read_text()
+
+ # Strip license header
+ source_code = strip_license_header(source_code)
+
+ # Read pre-rendered output
+ # FIX: Check for None and valid file
+ if output_path and output_path.is_file():
+ output = output_path.read_text()
+ else:
+ output = "Output not available (dependencies not installed during build)"
+
+ deps = ", ".join(sorted(info.imports - {"plotille"}))
+
+ # ... rest of function ...
+```
+
+**Test:**
+```bash
+python scripts/generate_docs.py
+# Should complete without errors
+```
+
+---
+
+## Major Issues (Functionality Broken)
+
+### 2. Task 7.2 Not Completed ā ļø **REQUIRED**
+
+**Issue:** The current `runExample()` function in `brython-setup.js` uses incorrect Brython API and won't work properly:
+
+```javascript
+// Current implementation (from Task 6.1) - INCORRECT:
+window.__BRYTHON__.python_to_js(code); // This API doesn't exist
+const result = eval(window.__BRYTHON__.imported['__main__']); // Wrong approach
+```
+
+**Impact:** Clicking `[EXEC]` buttons will either:
+- Do nothing
+- Show errors
+- Not capture output correctly
+
+**What's Missing:** Task 7.2 in the implementation plan specifies a completely different approach that:
+- Creates a `
+
+
+
+
+
+
Plotille Brython Compatibility Test
+
+
This page tests whether plotille can run in the browser using Brython (Python in the browser).