pgAcademy — an illustrated field guide to the Postgres planner & executor.
Eighteen single-page lessons that walk through how Postgres actually reads your rows, combines your tables, and decides what to do with your indexes. Designed for engineers of every seniority — juniors meeting B-tree for the first time, and seniors debugging a plan they don't understand.
Lessons come in four parts:
- I. Index Types — B-Tree · Hash · GiST · GIN · BRIN · Bloom
- II. Scan Strategies — Seq Scan · Index Scan · Index-Only Scan
- III. Join Algorithms — Nested Loop · Hash Join · Merge Join
- IV. Ancillary Operators — Bitmap Heap/Index Scan · BitmapAnd · BitmapOr · Gather · HashAggregate
A companion to pgdoctor.
cd docs && python3 -m http.server 8000
# open http://localhost:8000No build step, no dependencies. Plain HTML + one CSS file + one JS file.
- Static HTML served from
/docs/onmain(GitHub Pages settings) docs/style.css— single theme (Fraunces + IBM Plex Sans + JetBrains Mono)docs/stepper.js— tiny vanilla step renderer shared by every lesson pagedocs/index.html— syllabus landing page
Each lesson is a self-contained HTML file that declares its steps as a JS array and lets stepper.js drive the narration + viz.
Required DOM contract:
<aside class="narration">
<div class="narration-scroll">
<h2>Step <span id="step-num">0</span></h2>
<div class="step-title" id="step-title"></div>
<p id="step-body"></p>
<div class="pgnote" id="pg-note" style="display:none;"></div>
</div>
<div class="narration-pinned">
<div class="controls">
<button id="prev" class="secondary">← Prev</button>
<button id="next">Next →</button>
</div>
<div class="controls">
<button id="reset" class="secondary">Reset</button>
<span class="step-counter" id="counter"></span>
</div>
</div>
</aside>
<section class="stage">
<!-- your visualization here -->
</section>Steps contract (window.STEPS must be set before stepper.js loads):
window.STEPS = [
{
title: 'A short chapter heading',
body: 'HTML allowed — <b>emphasis</b>, <code>code</code>, etc.',
note: 'Optional marginalia — source-code pointers, tuning notes.',
render: () => {
// Idempotent DOM mutation. Safe to jump to any step via #step=N.
}
},
// ...
];Register the lesson in docs/stepper.js by appending to window.LESSONS — this wires the syllabus order and the "prev/next lesson" navigation.
Style conventions: use the shared CSS variables (--ink, --seal, --good, --warn, --bad, …) instead of hard-coding hex values. Primitives you can reuse: .panel, .page / .tuple, .bitmap / .bit, .tnode, .row, .pgnote.
- Full keyboard navigation:
←/→/n/pbetween steps,rorEscto reset #step=Ndeep-linking, browser back/forward supportedaria-livenarration region, labelled controls,prefers-reduced-motionrespected
Published via GitHub Pages from main branch, /docs folder. No build, no CI-driven deploy — commit to main and the site refreshes.
See LICENSE.