π 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):
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));" />
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 printCSS 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-siteto 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¶
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:
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:
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:
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¶
- Create folder:
docs/study-guides/{topic-slug}/ - Create files:
index.md(guide),video-script.md(script),images/(screenshots) - Add to nav: Update
mkdocs.ymlunder Study Guides section - Write content: Module by module, commit after each batch
- Add cover page: Copy from existing guide, update title/info/version
- Capture screenshots: Minimal, convert to WebP
- Export PDF:
python export-pdf-browser.py --theme dark --output path.pdf - Write video script: After guide is complete
- Update study guides index: Add the new guide to
docs/study-guides/index.md
Links¶
| 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.com/in/susanthsutheesh | |
| Learning Portal | learn.aguidetocloud.com |
Last updated: April 2026