Skip to content

πŸ“š Study Guide System β€” How We Built It

Reference document β€” Everything we learned building the study guide system, PDF export, cover page, and styling fixes. Use this when creating the next study guide.


Overview

The study guide system lives in docs/study-guides/ and is designed to create professional, student-facing teaching materials that:

  • Render beautifully on the learning portal (dark neon theme)
  • Export to high-quality PDF (via Playwright browser capture)
  • Work with PortalPresenter (slide presentation mode)
  • Can be sold on Ko-fi ($5-10 per guide)

File Structure

docs/study-guides/
β”œβ”€β”€ index.md                          # Overview page listing all study guides
└── copilot-cli-beginner/             # One folder per study guide
    β”œβ”€β”€ index.md                      # The study guide (one long page)
    β”œβ”€β”€ video-script.md               # Slide-by-slide talk track for recording
    └── images/                       # Screenshots (WebP format)
        β”œβ”€β”€ copilot-welcome.webp
        β”œβ”€β”€ first-conversation.webp
        β”œβ”€β”€ model-menu.webp
        └── approval-prompt.webp

Export script (repo root):

export-pdf-browser.py                 # Playwright-based PDF export


Study Guide Template Structure

Every study guide follows this structure:

Section Purpose
Hidden h1 <h1 style="display:none;">Title</h1> β€” MkDocs needs it but we hide it
Cover page Full-screen branded block with title, info table, author, links
🎯 Scenario Real-world story framing the guide (e.g., "Meet Alex")
πŸ“‹ Prerequisites What students need before starting
🏁 What You'll Achieve Checkbox list of outcomes
πŸ—ΊοΈ Module Overview Coloured HTML tree showing all modules
Modules 1-N Concept (analogy) β†’ WHY it matters β†’ step-by-step HOW β†’ hands-on exercise β†’ checkpoint
πŸ“ Summary What was learned, key takeaway per module
πŸ”‘ Key Commands Quick reference table
πŸš€ Next Steps Where to go after this guide

Cover Page β€” Lessons Learned

What the cover page contains

  • Website logo (rounded, with purple glow drop-shadow) β€” copied from main site's logo_agtc_dark_1.webp
  • πŸ€– emoji prefixes the course title (not standalone)
  • Title (magenta glow) + subtitle (cyan)
  • Tagline (italic grey)
  • Info table: Level, Time, Modules, Version β€” labels bold magenta, values normal white, alternating row backgrounds with purple tint
  • Author name linked to LinkedIn
  • 5 branded buttons: YouTube Masterclasses, YouTube Bite-sized, Website, Ko-fi Shop, LinkedIn
  • Copyright notice

Key implementation details

Hidden h1 title: MkDocs requires an h1 for the page title. We hide it with an HTML <h1> tag:

<h1 style="display:none; height:0; margin:0; padding:0; font-size:0; line-height:0; overflow:hidden;">Title Here</h1>

⚠️ Do NOT use markdown # with {: style="..." } attribute list β€” it renders the raw attribute text on the portal instead of applying it.

Logo:

<img src="images/logo.webp" alt="A Guide to Cloud & AI" style="width: 160px; margin-bottom: 1.5rem; border-radius: 50%; filter: drop-shadow(0 0 15px rgba(102, 0, 204, 0.5));" />
- Source: copy logo_agtc_dark_1.webp from aguidetocloud-revamp/static/images/ into the study guide's images/ folder - Rename to logo.webp - border-radius: 50% makes it circular - drop-shadow adds the purple neon glow

Cover page container: Uses inline styles for the gradient background, flexbox centering, and min-height:

<div class="study-guide-cover" style="text-align: center; padding: 4rem 2rem; margin: -1rem -1rem 2rem -1rem; background: linear-gradient(135deg, #0d0d1a 0%, #1a0033 30%, #0d001a 50%, #1a0033 70%, #0d0d1a 100%); min-height: 80vh; display: flex; flex-direction: column; justify-content: center; align-items: center;">

Table rows with depth: Alternating background: rgba(102, 0, 204, 0.15) and rgba(102, 0, 204, 0.08) for visual depth.

Do NOT put a duplicate details table after the cover β€” all info is already in the cover.


Module Overview Tree β€” Coloured HTML

The module overview uses HTML with inline coloured spans instead of a code block. This allows: - Magenta (#ff66ff) for module names - Cyan (#66ffff) for sub-items - Amber (#ffbb33) for bonus modules

⚠️ Do NOT use a plain markdown code block for the tree β€” everything renders as green (Matrix code theme) and can't be differentiated.

Example:

<span style="color:#ff66ff; font-weight:bold;">β”œβ”€β”€ Module 1: Title</span><br/>
<span style="color:#66ffff;">β”‚   β”œβ”€β”€ Sub-item</span><br/>


PDF Export β€” The Journey

We tried 4 different approaches. Only one worked well.

❌ Option A: Browser Ctrl+P (Print to PDF)

  • Problem: @media print CSS converted everything to white background. Lost the dark theme. Some elements invisible.
  • Verdict: Not suitable for our dark-themed study guides.

❌ Option B: MkDocs print-site-plugin

  • Problem: Plugin needed to be installed on the GitHub Actions CI runner. Added print-site to mkdocs.yml but CI didn't have it installed β†’ broke the deployment for 3 consecutive builds.
  • Fix: Removed the plugin from mkdocs.yml entirely.
  • Verdict: Too much hassle for our use case. Combines ALL pages into one PDF (we want per-guide export).

❌ Option C: Pandoc + wkhtmltopdf

  • Problem: Pandoc converts raw markdown, not the rendered page. MkDocs-specific elements (admonitions, mermaid diagrams, styled HTML) don't render correctly. Content truncated in boxes with non-scrollable scrollbars.
  • Verdict: Inferior quality. Can't match the portal appearance.

βœ… Option D: Playwright (Headless Chromium) β€” THE WINNER

  • How it works: Opens a real headless browser, navigates to the actual portal URL, enters the password, waits for rendering, then tells Chrome to "print to PDF."
  • Result: Captures exactly what the portal looks like β€” mermaid diagrams, admonitions, tables, images, everything.
  • Script: export-pdf-browser.py

Key Playwright PDF settings

page.emulate_media(media="screen")  # CRITICAL: prevents @media print CSS from applying

Without this, Chrome uses print media for PDF generation, which triggers our @media print CSS that converts everything to white background.

page.pdf(
    format="A4",
    print_background=True,    # CRITICAL: without this, backgrounds are white
    margin={"top": "4mm", "bottom": "4mm", "left": "4mm", "right": "4mm"},
    display_header_footer=False  # CRITICAL: headers/footers force minimum ~15mm margins
)

⚠️ display_header_footer=True forces Chrome to maintain large minimum margins regardless of what you set. Always set to False for tight margins.

CSS Injection β€” The Breakthrough

MkDocs Material has !important CSS rules on many container elements. Inline styles set via JavaScript don't override them. The solution: inject a <style> tag with our own !important rules:

page.evaluate("""() => {
    const style = document.createElement('style');
    style.textContent = `
        .md-content { padding: 0 !important; margin: 0 !important; max-width: 100% !important; }
        .md-content__inner { padding: 0 !important; margin: 0 !important; }
        .md-grid { max-width: 100% !important; padding: 0 !important; }
        /* ... etc ... */
    `;
    document.head.appendChild(style);
}""")

⚠️ Do NOT use el.style.property = value β€” MkDocs Material's !important rules will override inline styles. Always inject a <style> tag with !important.

Cover page in PDF β€” Sizing

The cover page uses min-height: 80vh on the portal (looks great). For PDF: - Use max-height NOT min-height/height β€” forced height causes overflow across pages - Use page-break-after: always to ensure content starts on page 2 - Compress content (smaller fonts, tighter padding) via injected CSS so it fits one page - The script injects cover-specific CSS to shrink elements for A4

Blank first page fix

If the hidden h1 creates a blank first page in PDF, add this to the injected CSS:

.md-typeset h1:first-of-type { display: none !important; height: 0 !important; }


Admonition / Blockquote Readability β€” Fixes

Problem

Text inside admonition boxes (tip, warning, info, etc.) and blockquotes was invisible in the dark PDF β€” font color blending with background.

Root Cause

The retro-neon CSS only styled the title colour for each admonition type, but not the body text. Body text inherited from .md-typeset which sometimes wasn't specific enough.

Fix (in retro-neon.css)

Added explicit text colour for ALL content inside admonitions:

.md-typeset .admonition *:not(.admonition-title):not(code):not(a),
.md-typeset details *:not(summary):not(code):not(a) {
    color: #e8e8e8;
}
.md-typeset .admonition a { color: #66ffff !important; }
.md-typeset .admonition code { color: #ffbb33 !important; }

Also added overflow: visible to all admonitions and blockquotes to prevent content truncation.

Blockquotes

Changed text colour from #cccccc to #e8e8e8 and added explicit rules for nested <p>, <li>, <strong>, <em> elements.


Mermaid Diagram Styling

Global CSS added to retro-neon.css for all mermaid diagrams:

Element Colour Why
Node text (.nodeLabel) White, bold Readable on dark node backgrounds
Edge labels (.edgeLabel) Amber (#ffbb33) Stands out from green arrows
Arrows/lines Green (#00dd44) Matches Matrix code theme
Participant boxes Dark bg, magenta border Neon accent
Sequence message text Amber Differentiates from node text

Individual flowchart nodes can override with inline styles:

style A fill:#1a1a2e,stroke:#ff66ff,color:#fff,font-weight:bold


Code Block Font Fix

Problem

All ASCII art diagrams (building analogy, whiteboard, file trees) were misaligned β€” box-drawing characters didn't line up.

Root Cause

Code block font was set to Montserrat (proportional font β€” each letter different width) instead of a monospace font.

Fix

Changed pre > code and code font-family to:

font-family: 'Cascadia Code', 'Fira Code', 'Consolas', monospace;


Screenshots β€” Best Practices

  • Only capture essential screenshots β€” students can refer to the video for visual context
  • Convert PNG β†’ WebP immediately (85% size reduction)
  • Use Python Pillow for conversion: Image.open(png).save(webp, 'WEBP', quality=80)
  • ⚠️ Always verify WebP exists BEFORE deleting PNG β€” we lost screenshots once by deleting before conversion succeeded
  • Store in images/ subfolder within the study guide folder

Video Script Format

  • Slide-by-slide talking points matching PortalPresenter
  • Format: "Say: / Show: / Demo: / 🎯 Presenter tip: / πŸ“Œ Cue:"
  • Include a Recording Checklist at the end
  • Include a Screenshots Needed table
  • Include a YouTube Description Template with chapter timestamps
  • Write the video script AFTER the study guide is complete (so it matches)

Key Decisions & Preferences

Decision Choice Why
Write content yourself, not agents Always Full conversation context matters β€” agents produced nothing in 40 min
Write incrementally Module by module Reduces risk, allows feedback, prevents losing work
Quality over speed Always Getting it right first time saves more time than fixing later
Dark PDF theme Preferred Matches the portal β€” students see what they'll see online
PDF export method Playwright Only option that captures the actual rendered page
Screenshots Minimal Students have the video β€” only capture truly essential moments
macOS support Yes Widens audience β€” tabbed install instructions (winget/brew)
Cover page In the document Shows in both portal and PDF β€” single source
Study guides may be sold Ko-fi shop ($5-10) Not free β€” copyright notice on cover page

Quick Reference β€” Creating a New Study Guide

  1. Create folder: docs/study-guides/{topic-slug}/
  2. Create files: index.md (guide), video-script.md (script), images/ (screenshots)
  3. Add to nav: Update mkdocs.yml under Study Guides section
  4. Write content: Module by module, commit after each batch
  5. Add cover page: Copy from existing guide, update title/info/version
  6. Capture screenshots: Minimal, convert to WebP
  7. Export PDF: python export-pdf-browser.py --theme dark --output path.pdf
  8. Write video script: After guide is complete
  9. Update study guides index: Add the new guide to docs/study-guides/index.md

Resource URL
YouTube β€” Masterclasses youtube.com/susanthsutheesh
YouTube β€” Bite-sized youtube.com/aguidetocloud
Website aguidetocloud.com
Ko-fi Shop ko-fi.com/aguidetocloud/shop
LinkedIn linkedin.com/in/susanthsutheesh
Learning Portal learn.aguidetocloud.com

Last updated: April 2026