agentsclimarketplace

Teaching lecture

Skill ericluo04/claude-academic-workflow/skills/teaching-lecture

Academic research workflow for Claude Code: 14 skills (paper reading, lit review, bib auditing, preregistration, referee reports, replication packages, LaTeX, TikZ) plus a Quarto reveal.js slide system with render-time quality gates. Entirely AI-generated with Claude Code as a proof of concept.

Install
npx -y skills add ericluo04/claude-academic-workflow --skill teaching-lecture

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 5 stars5 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

Author Quarto reveal.js lecture decks for a classroom, built for engagement: incremental reveals, animation, discussion prompts, checks for understanding, worked examples. Larger Yale lecture theme, staged reveals, and figures sized for a projector. TRIGGER on "build a lecture", "slides for my class", "teaching deck", "lecture on X", "course slides", "class on AI", "make a lecture for week 3", "MBA lecture", "undergrad lecture", "add a discussion slide". Use research-talk for a conference, seminar, or job talk, slide-review to audit a deck that already exists, and course-site for the landing page, the week table, and publishing.

SKILL.md

29.2 KB, as published. Nobody here has run it

Teaching lecture decks

Builds a .qmd that renders to a reveal.js HTML deck for a class meeting, and organizes a semester of them into one published course site. Students are seeing the ideas for the first time, they are taking notes, they will reread the deck a week later, and their attention resets every fifteen minutes. That drives every choice here: bigger type, staged reveals, a visible roadmap, a worked example after every formal idea, and questions they have to answer out loud.

Out of scope: research presentations (use research-talk, which shares this toolchain and theme family but stays quiet and dense), auditing a deck you did not write (use slide-review), and LaTeX Beamer (use compile-latex). The course-site skill owns everything around the decks: the landing page, the week table, the site theme, publishing.

Shared theme and tooling live in ~/.claude/assets/quarto-yale/. README.md there is the machinery reference: the recipe, the class list, what the filter rewrites, what the gates assert, and the settings that silently break a deck. Read it for any of that; where it and the source disagree, the source wins. The head of yale-lecture.scss carries the palette and the theme's own reasoning about a class. This skill does not restate what research-talk already covers (output-location for code chunks, how pdfread.py works); read that skill where the two overlap. The pointer map at the end of this file says which reference file holds what.

The lecture theme is dark

yale-lecture.scss is a designed dark theme, not an inverted light one. 34px root for a lecture hall, near-black ground, and a named block for each thing a slide can ask of a student.

The table gives the example theme's values, so the mechanism is concrete; your own theme supplies its own palette and should keep the measured-contrast discipline.

RoleHexNotes
Ground#1a1c1eEvery slide, including dividers. Nothing changes it.
Body text#e8e6e313.7:1 on the ground.
Headings#ffffff17.1:1, headings only. Body text at pure white halates on a projector.
Links, accents#63aaff7.1:1. .yblue, list markers, progress bar.
Pale accent#a8ceff10.5:1. .ypale, h3, emphasis, table headers.
Inline code#ffa07a8.6:1. .yred as well.
Warning#f4c95d.yamber, .warning blocks.
Example#7ec699.ygreen, .example blocks, .demo-tag.
Muted#9aa0a66.5:1. .ygray, .dim, footer, slide number, appendix headings.
Divider disc#286dc03.3:1, a large solid shape only; white on it is 5.2:1.
Appendix slate#6f7a853.9:1, marks and rules on .appendix slides. Never text.

Ratios are WCAG 2.1 against the ground, measured rather than estimated.

Yale blue #00356b is not ink anywhere in this theme. It measures 1.4 to 1.7 to 1 against the dark ground, which is invisible rather than merely poor. Do not put it back as a text or accent colour, do not use it in a figure, and do not use it as a slide background: the ground stays near-black on purpose.

Two consequences to carry into a deck: a figure with a white panel background is a lightbox on a dark wall, so figures need dark panels (references/figures-dark.md), and any hex copied out of an older deck needs checking against this table. The palette's reasoning is in style/house.md and the head of the scss.

Before drafting anything

Ask, do not guess.

  1. Which course, which week, and how long the class is. 50 and 75 minutes are different decks, not the same deck at a different pace.
  2. What last week ended on. Every lecture opens by closing that loop, and the agenda slide needs it.
  3. Who is in the room, and what they can be assumed to know. A business-school AI class can draw MBAs, undergrads, and CS or econ PhD students in one section. A business student reads a figure faster than an equation and a CS student the reverse, so ask the mix, then give both with the picture first. Naming the prerequisite is what decides whether a formal definition can appear at all.
  4. What already exists: the paper the lecture is built on, prior years' slides, the R that makes the figures.

Then write the slide titles and read them back as a list before any bodies exist. A lecture title may be a topic label where a research title may not ("What a loss function is" is fine), but each block of three or four slides under it carries one claim, and the claims in order are the lecture.

The verified front matter

The format is a Quarto extension. Its master copy is ~/.claude/assets/quarto-yale/_extensions/yale/yale-lecture/; adopt it by copying that directory to _extensions/yale-lecture/ beside the deck (or at the project root), and give the rendered deck a mathjax/ copy from ~/.claude/assets/quarto-yale/mathjax/ beside the HTML, because the format self-hosts MathJax at a relative url. A standalone deck then needs only:

title: "Prediction is not a decision"
author: "Your Name"       # exact form; see style/house.md
date: 2026-09-16
format: yale-lecture-revealjs
engine: knitr             # only if the deck has R chunks; R is the default here for figures
bibliography: lecture-refs.bib   # only on a deck that cites

The format carries, so the deck must not repeat: the theme layered on default (eight of the twelve built-ins @import Google Fonts at display time), stage-slide.lua in filters:, citeproc: false (harmless on a deck that does not cite), refs-fit: lecture, highlight-style: a11y-dark, slide-number: c/t, incremental: true, date-format: long, fig-align: center, auto-animate-duration: 0.4, echo/warning/message: false, and self-hosted MathJax (method: mathjax, url: mathjax/MathJax.js) pinned to MathJax's own TeX webfonts so the metrics match on every machine and the fit gate's certification transfers. The comments in _extension.yml say why per key. A deck off the extension writes all of that out by hand; that manual recipe is in the README under "The recipe".

In a course project the per-course choices live once in lectures/_metadata.yml and cover the whole semester. The verified working copy, from the example course this repo's examples/ lecture comes from:

format:
  yale-lecture-revealjs:
    # These lectures render to docs/lectures/<name>.html and the site's MathJax
    # copy is at docs/assets/mathjax/ (a `resources` entry in _quarto.yml keeps
    # it there across renders), so the url is the path from the rendered page
    # to that copy.
    html-math-method:
      method: mathjax
      url: ../assets/mathjax/MathJax.js
engine: knitr

bibliography: stays out of it, in the one lecture that cites.

stage-slide.lua opens each content slide as its title alone and then reveals its blocks in turn, which incremental: true does for list items only; its six jobs are in the README under "What stage-slide.lua does", and its header comment is the reference before changing how a slide stages. A deck with dividers needs it or the discs come out empty.

MathJax handles \eqref, \label, \DeclareMathOperator, mathtools, and physics, none of which KaTeX can do. Do not switch to mathml or plain; a room with no network takes the offline variant, which gives up \eqref and friends (README, "The offline variant"). highlight-style: a11y-dark is the companion to this theme: a light style paints a white code card, and a misspelled style name fails silently at exit 0.

The progress bar is on by default and the format sets slide-number: c/t. Students pace themselves off the bar; on this theme it is segmented per section, and both the bar and the number take the appendix and the references out of the denominator, so the bar reads 100% on the .closing-slide and the class body counts 1/25 to 25/25 with the tail on its own 1/8 run. Measured details: references/staging.md; bar mechanics: README "The progress bar".

Leave chalkboard off: with embed-resources: true it is a hard render error, and annotation happens on the room's own boards. Misspelled YAML keys are ignored silently at exit 0; quarto inspect deck.qmd prints the resolved format.

Math macros

Park them on a hidden slide at the top of the file:

## Notation {visibility="hidden"}

\newcommand{\E}{\mathbb{E}}
\DeclareMathOperator*{\argmin}{arg\,min}

A bare macro block before the first ## becomes its own completely blank slide, counted in c/t and printed into the handout; visibility="hidden" drops the slide from navigation, the count, and the PDF, and the macros still resolve everywhere after it. Macros expand at parse time, before any renderer sees the math, so the same block works under MathJax and under the offline KaTeX variant; wrapping the definitions in $$ ... $$ fails.

Number a result you will refer back to, which a lecture does more than a talk does: $$ ... $$ {#eq-bayes}, then @eq-bayes in prose. Quarto's @eq- form is the portable one; raw \label plus \eqref also works under MathJax and breaks under the offline variant.

Math inside a raw HTML block works, because pandoc's markdown_in_html_blocks is on by default, so $a^\star = \argmin_a \E[L(a,y)\mid s]$ typesets correctly inside a raw <ol class="steps"> item.

The teaching vocabulary

ClassOne line
.keyideaThe one thing to remember. At most three per deck.
.definitionNew vocabulary.
.exampleThe concrete case.
.warningThe common error.
.questionA check the student answers; the answer goes on the next slide as a .fragment.
.promptLarge centered discussion question, sized to fill a slide while students talk.
.heroOne number that should land hard.
.full-bleedOn a heading whose slide is one image, edge to edge, capped at 78vh.
.demo-tagLive-coding marker: ## Live demo [demo]{.demo-tag}.
.aside-noteMuted caveat; arrives on the previous block's beat.
.numRight-align a numeric table column.
.jump, []{.jump-back}The appendix jump buttons below.
ul.agendaRoadmap list: .done struck-through gray, .now blue and bold with a triangle, the rest muted.
ol.stepsFilled blue numbered circles; every worked example, four or five steps.
#thm- familyNumbered theorem environments: references/theorems.md.
.yblue .ypale .ygray .ygreen .yamber .yred .dimColour spans, hex per the palette table.

ul.agenda and ol.steps work both as raw HTML lists and as fenced divs (::: {.agenda} / ::: {.steps} around the list); the theme styles both forms. The five teaching boxes each take a [Label]{.label} span, and the label text is yours:

::: {.keyidea}
[Key idea]{.label}
A predictor is only useful once you say what decision it feeds.
:::

The starter template exercises all five boxes, the agenda, the steps, .hero, and .prompt. Keep the class-to-meaning mapping fixed for the whole semester (references/pedagogy.md says why). Two blocks per slide is the limit, and it is physical as well as pedagogical: three blocks of two lines each fill 94% of the canvas at 34px root.

Dividers, appendix, references, jump buttons

Two divider archetypes, both a circle beside a vertically centred title, the same shapes yale-talk.scss uses so a talk and a lecture read as one family:

## How much a leaderboard can move {.section-break}

## Appendix {.appendix-break background-color="var(--appendix-ground)"}

.section-break is a numbered blue disc. The number comes from stage-slide.lua, so nothing is hand-numbered and the dividers renumber on the next render. A divider carries its title and nothing else, no background attribute; .appendix-break is the one divider that changes the ground, and its attribute is copied exactly as written above. The fallbacks, the print-view behaviour, and why a CSS counter is wrong here are in the README under "Things that will silently break the deck"; divider title diction is in style/house.md.

Slides after the appendix divider take {.appendix}: slate headings and marks, a standing APPENDIX pill above every heading, and the ground, the body text, and the five teaching boxes unchanged. The scheme's measured values and reasons are in style/house.md.

A lecture cites less than a seminar talk, and when it does the citation is a pointer for the student taking notes rather than part of the argument. Cite with [@key] or @key; the parentheses come from the citation style, never from CSS. The reference list goes at the very end, after the appendix, and paginates itself:

## References {.references-break background-color="var(--references-ground)"}

## References {.references}

::: {#refs}
:::

The format's citeproc: false is what lets stage-slide.lua run citeproc itself and cut the list across slides, and refs-fit: lecture is the measured 34px budget: 22.6 rendered lines at 113 characters per line, packed greedily, so the sample lecture packs 7 entries and then 5. STAGE_REFS_DEBUG=1 quarto render deck.qmd prints what the packer decided and refs-lines overrides it. Never put .scrollable on a references slide. The cite-form table, the hover and tooltip machinery, and the packing model are in the README under "Citations and the reference list".

Jump buttons: a question in week three is usually a question the appendix already answers. Give the appendix slide an id, name it from the lecture slide, and put a Back button on every appendix slide you might land on:

## Where the interval comes from {.appendix #ap-se}
::: {.with-previous}
[Derivation]{.jump target="ap-se"}
:::

and on the appendix slide []{.jump-back} in the same .with-previous wrapper, which renders as Back and returns to the exact slide and fragment step you left. A button goes on its own line, after a bordered or indented block and never inside one, and a forward label names the destination in one to three words. Run the fit gate after adding one; the button owns a line the slide did not own before. Alignment, the silent target breakers, and the handler: README "Jump buttons"; the lecture's measured numbers: references/staging.md; label diction: style/house.md.

Staging, in one paragraph

The invariant is that the title appears alone: every content slide opens as its heading and reveals its blocks one beat at a time, a figure as much as a list. incremental: true is the default to start from; opt lists out with ::: {.nonincremental}, group blocks into one beat with ::: {.together}, put an addendum on the previous beat with ::: {.with-previous}, and opt a slide out with {.no-stage}. Budget five to eight staged moments in a 75-minute deck beyond the incremental lists. Fragment variants, .r-stack layers, fragment-index, and auto-animate are in references/staging.md; the filter's internals are in the README under "Staging: the title appears alone, always".

Pacing and structure

Every lecture opens with the same two slides. One slide of recap that ends on the question this lecture answers, then the agenda as a ul.agenda with li.done on last week and li.now on today's first block. Repeat that agenda slide verbatim at each block boundary, moving .now down one, and close the lecture with every item .done. Students use it to locate themselves and it costs three slides.

A lecture does not end on a thank-you slide. The last two slides of the class are the synthesis pair: the agenda with every item .done, then the .closing-slide, which stages as heading, then one beat (references/closing-slide.md). After that comes the appendix divider, which the class only sees if a question sends you there.

Segment budget for 75 minutes:

MinutesWhatSlides
0-5Recap, agenda, the question3
5-25Block 1: motivation, the formal idea, a worked example8-10
25-30Discussion prompt or a check for understanding1-2
30-50Block 2: the complication and how it is handled8-10
50-55Second prompt, or a live demo1-2
55-70Block 3: application, or a paper read together6-8
70-75Synthesis: the agenda all .done, plus what is next2

A 50-minute class is the same shape with Block 3 dropped and one prompt instead of two, about 22 content slides. Roughly 1.5 to 2 minutes per content slide, half the density of a research talk. Sixty slides for 75 minutes is a reading, not a lecture. Where the prompts go and how to run them: references/pedagogy.md.

Build and verify

The render exits 0 whether or not the deck is presentable, so the gates are not optional. Run them every time.

cd <deck dir>
quarto render lecture.qmd --to yale-lecture-revealjs 2>&1 | tee /tmp/render.log
grep '\[WARNING\]' /tmp/render.log     # unclosed divs and missing images warn here, still exit 0

node ~/.claude/assets/quarto-yale/deck-check.mjs fit lecture.html   # must print DECK-FITS: YES
node ~/.claude/assets/quarto-yale/stage-check.mjs lecture.html      # must print STEP-0-CLEAN: YES

# only if this deck was built as the offline variant
~/.claude/assets/quarto-yale/check-offline.py lecture.html           # must print OFFLINE-SAFE: YES

deck-check.mjs fit drives headless Chrome, visits every slide, forces its fragments visible, and measures; it fails on overflow, excess width, missing images, crushed or shrunk figures, unrendered math, a dangling .jump target, and an unpaginated bibliography, and --json adds per-image geometry. A single-pass DOM scan cannot do this, because reveal sets display: none on every slide that is not current. stage-check.mjs puts every slide in its unadvanced state and asserts nothing but the heading is visible, then walks each content slide forward and fails a press that changes no visible ink (DEAD STEP, presses counted from 1), at a cost of about two seconds a deck. It skips slides by class (the dividers, the reference pages, the closing slide under either archetype name); {.no-stage} is not on that list. It is the filter's opt-out and the gate has never read it, so an unstaged slide still has to be classified as something other than content. Both gates are in the README in full. The sample lecture measures zero dead steps.

check-offline.py runs only on a deck built as the offline variant. On a default MathJax deck it reports the external MathJax reference and fails, which is correct and is not a defect (README, "The offline variant").

Overflow matters more here than in a research deck. At the 34px lecture root, a heading plus ten single-line bullets fills the canvas exactly, so eight is the working limit. Twelve bullets overshoot by 161 px, and lines eleven and twelve are simply gone on the projector while the laptop preview looks fine. Fixes, in order: split the slide (almost always right, since a slide that does not fit is doing two jobs), move the delivery lines into ::: {.notes} while the substance stays in the body where the handout keeps it, or add {.smaller} to the heading, kept for a table or a code block because shrinking type defeats a 34px root. panel-tabset is not a fix (only its first tab prints) and .scrollable slides always fail the gate; split instead.

To look at slides rather than measure them, use decktape and pdfread.py per the README ("Looking at a rendered deck"). The Read tool cannot open a PDF on this machine.

Course site and handout

The course-site skill owns the site in full; read it before touching _quarto.yml, index.qmd, or anything else outside lectures/. A semester of lectures lives in one Quarto website project per course (the example lecture in this repo's examples/ directory comes from one), each deck a lectures/wNN-slug.qmd holding content only, with the shared config once in lectures/_metadata.yml as shown above. While drafting, render one lecture: quarto render lectures/w03-slug.qmd.

The site's week table links a pdf next to every deck, and the handout has to be built by the render itself: a render prunes everything in docs/ that it did not produce, which deletes any PDF put there by hand. Build it in a post-render hook, which runs after the prune; the script walks the decks Quarto just rendered (QUARTO_PROJECT_OUTPUT_FILES, so rendering one lecture rebuilds only that handout) and calls the exporter on each:

node ~/.claude/assets/quarto-yale/deck-check.mjs handout \
  docs/lectures/w03-slug.html docs/lectures/w03-slug.pdf

A workable scripts/build-handouts.sh skips with a warning when node or the exporter is missing, exits nonzero when an export actually fails, and needs no change when a lecture is added. With pdf-separate-fragments at its false default the print view collapses each slide's build steps onto one fully revealed page (27 slides came out 27 pages), which is the student handout; set it true for a page per build step, a lecturer's cue printout that runs long under incremental: true. decktape is the fallback exporter, speaker notes appear in neither PDF, and panel-tabset prints only its first tab (README, "PDF handouts").

Starter template

assets/starter-template.qmd is the starter deck: recap and agenda, the five boxes, a worked example with a jump to its appendix derivation, an auto-animate pair, a .prompt, the synthesis pair, and the closing slide. It renders standalone, and passes both gates, with _extensions/yale-lecture/ copied beside it; it needs no _metadata.yml. Math at display time additionally needs a mathjax/ copy beside the rendered HTML.

Traps, all verified on this machine

SymptomCauseFix
Content clipped on the projector, clean on the laptopreveal scales a fixed 1050x700 canvas and render exits 0deck-check.mjs fit, then split the slide
Figure axis labels unreadable, gate says the slide is okauto-stretch shrank the figure instead of overflowingread --json per-image w, move the text into a column
A blank slide in the count and the handoutmacro block before the first #### Notation {visibility="hidden"}
\argmin errors as an unexpected control sequencemacros wrapped in $$ ... $$bare raw LaTeX under the hidden slide
Section divider has an almost invisible navy panel on itbackground-color="#00356b" copied from the talk themedrop the attribute; {.section-break} alone is right here
Divider disc is an empty circlestage-slide.lua not running: a deck off the extension with no filters: lineuse the extension format, or add the filter by absolute path
A figure or a note appears with the heading instead of waitingthe filter is not running, or the heading carries {.no-stage}stage-check.mjs names the slide
Math unrendered even with wifithe format's self-hosted mathjax/MathJax.js url resolves to nothing next to the rendered HTMLcopy ~/.claude/assets/quarto-yale/mathjax/ beside the deck, or override the url as the course project does
Appendix divider is on the near-black ground in the handoutreveal's print view builds no background elements at allnothing to fix; the ring and the lone title carry it
Progress bar is one unbroken linefewer than two .section-break dividers, or the filter is missingnothing to fix if the deck has one section; otherwise add the filter
Progress bar is not full on the closing slidethe appendix has no .appendix-break divider and no .appendix slides, so nothing marks where the class endsadd the divider before the first appendix slide
A jump button navigates but Back does nothingthe deck has .jump spans and a stale render, or the filter was droppedre-render; the filter emits the handler alongside the buttons
A jump button lands on the title slidethe target id is all digits, or the target slide is {visibility="hidden"}rename the id; reveal reads an all-digits id as a slide index
Dividers numbered 1, 2, 2, 2a CSS counter, which display: none slides do not incrementthe attribute plus content: attr(...), which the theme already does
A paragraph on a divider slide lands under the titlethe divider centres a full-height flex h2put the sentence on the next slide
pdf link on the course site 404s after a rendera render prunes docs/ of anything it did not buildbuild the handout in a post-render hook
Some text or a figure line is invisible on the wallYale blue #00356b used as ink on the dark ground, 1.4 to 1.7 to 1use #63aaff, or #a8ceff for a pale accent
Code block renders with no highlighting at allmisspelled highlight-style (solarized-dark and printing-dark do not exist)the format's a11y-dark
Figure is a white box in the middle of the slideggplot default themethe dark lecture_theme() in references/figures-dark.md
Title slide is top-aligned instead of centreda top: 0 !important rule was added to the themeremove it; it also disables {.center}
Figure inside a column or an .r-stack renders tiny or overflowsauto-stretch only ever sizes a direct child of the section, and .r-stretch by hand only removes the size capset fig-width/fig-height, or width= on a file image
Handout is missing most of a slide's contentpanel-tabset prints its first tab onlyseparate slides
Math gone in a room with no networkMathJax loads at display time (self-hosted or CDN)build the offline variant, or ship the mathjax/ copy with the deck
Offline variant loses its math anywaythe {method:, url:} object form left a runtime loaderbare html-math-method: katex plus self-contained-math: true
\eqref prints as literal textthe deck was built as the offline KaTeX variantQuarto @eq- cross-references
Render fails, RevealChalkboard is not compatiblechalkboard with embed-resourcesleave chalkboard off
Video slide shows "No compatible source was found"{{< video >}} writes a <source> with no typeraw <video src="...">
plotly figure 403s in classplotly.py 6.x emits a module import of cdn.plot.lyadd plotly-connected: false to the front matter
Choropleth blank with no networkplotly fetches topojson at display timeuse a static image of the map
Regression table columns read 1. and 2.pandoc parses (1) as an ordered-list markerrename the columns
Blank image on a slide, render exited 0missing file, only a buried [WARNING] Could not fetch resourcethe gate reports MISSING IMG
A YAML key silently does nothingQuarto ignores unknown reveal keysquarto inspect deck.qmd
Every asset 404s on GitHub PagesJekyll dropped the _files directoriestouch docs/.nojekyll and commit it
Handout collapses every build step onto one pagepdf-separate-fragments defaults to false and decktape ignores itthat collapsed export is the student handout; for a page per build step set pdf-separate-fragments: true and use deck-check.mjs handout
A second, unpaginated bibliography on the last slidebibliography: on a deck without citeproc: false (the extension format carries it)use the extension, or add the line; the fit gate fails the deck for it
Reference list runs off the bottomrefs-fit missing or wrong for the themeSTAGE_REFS_DEBUG=1 quarto render prints the packer's decision; refs-lines overrides it
Citation renders as a literal @keyciteproc: false with the filter absent from filters:put the filter back

Where the detail lives

FileWhat it holds
references/pedagogy.mdThe density doctrine, prompts and checks for understanding (Mazur), speaker notes, the semantic vocabulary rule, the pattern audit table.
references/theorems.mdThe numbered theorem family, #thm- crossrefs, the #def-/#exm- guard, proof-in-appendix with jump buttons, the harmless citeproc warning.
references/figures-dark.mdFigure geometry at the 34px root, lecture_theme(), captioned figures, the silent-shrink trap, plotly, video, .full-bleed.
references/closing-slide.mdThe closing slide: markup, heading-then-one-beat with .together, the rationale, how the gate classifies it.
references/staging.mdFragment variants, .r-stack, fragment-index, auto-animate, the animation budget, progress bar and slide number details, jump-button measurements, layout numbers.
style/house.mdYour values, separated from the mechanisms: palette rationale, density calibration, the author line, dates, button diction, closing wording. A stub in the public repo; fill it in.
assets/starter-template.qmdThe starter deck, rendering clean under yale-lecture-revealjs.
~/.claude/assets/quarto-yale/README.mdThe machinery: the filter's six jobs, staging internals, both gates, citations and refs packing, jump buttons, the progress bar, the silent breakers, handouts, fonts.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.