Skip to content

Talks: one page per talk, generated from TOML records - #48

Open
gvegayon wants to merge 2 commits into
masterfrom
talks-pipeline
Open

Talks: one page per talk, generated from TOML records#48
gvegayon wants to merge 2 commits into
masterfrom
talks-pipeline

Conversation

@gvegayon

Copy link
Copy Markdown
Member

Talks only existed in the Google Calendar: the site linked out to calendar entries, and nothing about a past talk (abstract, speaker bio, slides, recording) survived anywhere. This adds a small pipeline so every talk gets a permanent page on the site.

How it works

  1. A talk is a TOML file in _data/talks/, e.g. 2026-09-04-george-vega-yon.toml — title, date/time, location, Zoom, slides, recording, abstract, and one [[speakers]] block per speaker (name, affiliation, website, photo, bio).
  2. make talks (scripts/generate_talks.py) turns each record into _talks/<name>.md, published at /talks/<name>/.
  3. Both files get committed. .github/workflows/talks.yml re-runs the generator with --check on every PR, so the pages can never drift from the records.

Why generate instead of reading TOML at build time? GitHub Pages builds Jekyll in safe mode, so custom plugins (the usual way to read TOML) are unavailable — the pages have to exist in the repo.

What is in this PR

_data/talks/*.toml 178 talk records, 2020 through 2026
_data/talks/_TEMPLATE.toml copy-me starting point, with every field documented
scripts/generate_talks.py TOML → _talks/*.md; validates records, removes orphans, --check mode for CI
scripts/import_calendar_talks.py seeds records from the calendar's public iCal feed
_layouts/talk.html the talk page: abstract, speaker bios and links, slides/recording buttons
talks.md /talks/ — upcoming talks, then past talks grouped by year
_includes/next_talks.html now reads the talk records instead of fetching Google Calendar in JavaScript
seminar.md next talk + next five upcoming talks + link to the archive; the calendar embed stays for subscribing
_config.yml talks collection, and future: true (Jekyll hides future-dated documents otherwise, which would have hidden every upcoming talk)
README.md how to add and update a talk

Verified by building the site with Jekyll 3.10 (the GitHub Pages version): 178 talk pages + the archive, no warnings.

About the seeded records

The 178 records were parsed from the calendar's iCal feed. Calendar descriptions are free-form, so this is a first pass: every imported record carries needs_review = true under [meta]. What came through well: titles, speaker names, dates, locations, and most abstracts and bios. What needs a human pass:

  • 4 talks whose calendar entry never had a real title (they read TBA, Orientation, VLM Agents)
  • ~78 older entries with no abstract in the calendar, and ~99 with no bio
  • affiliations are sparse for the 2020–2022 entries
  • no slides or recordings — those links were never in the calendar and have to be filled in by hand

Re-running make import-talks never overwrites an existing file, so corrections are safe.

Two things worth a decision:

  • Zoom links on past talks. The records keep them, but the page only shows the Zoom link while a talk is still upcoming — publishing ~150 old join links (several with embedded passcodes) seemed worse than useless. Easy to change in _layouts/talk.html if you disagree.
  • Scope of the archive. I imported everything back to 2020. If you would rather launch with, say, 2024 onward, deleting the older TOML files and re-running make talks is all it takes.

🤖 Generated with Claude Code

Talks were only recorded in the Google Calendar, so links pointed at calendar
entries and nothing about a past talk survived on the site. Each talk now has a
record in `_data/talks/*.toml` (title, speakers, bios, abstract, location, Zoom,
slides, recording, ...) and its own page under `/talks/<date>-<speaker>/`.

GitHub Pages builds Jekyll in safe mode, so the pages cannot be produced by a
plugin at build time: `scripts/generate_talks.py` turns the TOML records into
`_talks/*.md` and both are committed. A new workflow re-runs the generator with
`--check` on every PR so the two can't drift apart.

- `scripts/import_calendar_talks.py` seeds records from the public calendar feed
  (178 talks, 2020-2026); imported records are flagged `needs_review = true`
- `_layouts/talk.html` renders a talk: abstract, speaker bios and links, slides,
  recording; Zoom links are only shown while a talk is still upcoming
- `/talks/` lists upcoming talks, then past talks by year
- `seminar.md` and `_includes/next_talks.html` now read from these records
  instead of fetching the Google Calendar with JavaScript
- `future: true` in `_config.yml`, otherwise Jekyll hides upcoming talks
- README documents how to add a talk

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Comment on lines +15 to +26
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Check that _talks/ matches _data/talks/
run: python3 scripts/generate_talks.py --check
@github-actions

github-actions Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Thank you for your contribution @gvegayon 🚀! Your jekyll-site is ready for download 👉 here 👈!
(The artifact expires on 2026-11-17T01:19:27Z. You can re-generate it by re-running the workflow here.)

- every record gets tags from a fixed ~20-term vocabulary (23 topics);
  scripts/tag_talks.py fills them in from the title, abstract, and bio, and
  never touches tags that were set by hand
- /talks/ gains a search box (title, speaker, affiliation, abstract, location,
  date), plus tag, speaker, and year filters, all running in the browser over
  the list the page already ships -- no index, no service, and the full list
  still renders without JavaScript
- filters are shareable as links (/talks/?tag=robotics), and the tags on a talk
  page link back into the filtered archive
- speaker websites now show as an explicit link on the talk page, not only as a
  hyperlink on the name

Also fixes calendar-import parsing that had been mangling records: summaries
shaped "Data Science Lecture Series. Speaker: Name, Affiliation" (all of fall
2023) lost their speaker, logistics lines ("Zoom link: ...", "Talks will be
held in LNCO 1100") were being read as talk titles, and "A and B" speaker pairs
were mistaken for titles. Non-talks (orientations, info sessions) are skipped,
and a talk whose title is genuinely unknown is now titled "Talk by <speaker>"
rather than "TBA".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@gvegayon

Copy link
Copy Markdown
Member Author

Pushed the follow-ups from review:

Speaker websites. The talk page now shows an explicit link (engineering.nyu.edu) under the speaker's name and affiliation, in addition to the name itself being a link. 91 of the imported records have a website; the rest are blank in the calendar and need filling in by hand.

Tags. Every record now carries tags drawn from a fixed vocabulary of 23 topics. Distribution across the 176 talks:

machine learning 52 algorithms & theory 37 natural language processing 30 fairness & ethics 26
statistics 22 networks & graphs 20 deep learning 19 society & policy 19
large language models 18 visualization 16 biology & genomics 14 health & medicine 14
data management 13 education 13 optimization 13 human-centered computing 12
computer vision 10 climate & environment 8 robotics 8 physics & astronomy 7
causal inference 5 geospatial 5 privacy & security 4

scripts/tag_talks.py assigns them by matching title (weighted x3), abstract, and bio against the vocabulary, capped at 4 tags per talk. It skips any record that already has tags, so hand-picked tags always win — the automatic pass is a starting point, not a permanent owner. 10 records with no abstract or bio matched nothing and were left untagged. The vocabulary lives at the top of that script; adding or renaming a topic is a one-line edit followed by --overwrite.

Search. /talks/ now has a search box plus tag, speaker, and year filters. It all runs in the browser over the list the page already renders — no search service, no index to build, no dependency. Search covers title, speaker, affiliation, tags, location, date, and the full abstract text. Filters compose (tag + year + text), empty year groups collapse, and the result count updates as you type. Filter state lives in the URL, so /talks/?tag=robotics or /talks/?speaker=Anna%20Fariha is shareable — and the tags on each talk page link back into the filtered archive. Without JavaScript the complete list still renders; only the filter controls are hidden.

Verified against a local build: 176 talk pages, searching "robot" narrows to 9, the robotics tag to 8, "measles" finds the one talk that mentions it only in its abstract, and the speaker dropdown carries 169 names.

One thing worth flagging: wiring up the tags surfaced parsing bugs in the calendar import that I had missed on the first pass, so this push also re-imports the records. All of fall 2023 had Data Science Lecture Series. Speaker as the speaker name (that summary shape wasn't handled), some records had taken Zoom link: https://... or Talks will be held in LNCO 1100 as their title, and "Madison Golden and Kaylee Alexander" had been read as a title rather than two speakers. Those are fixed, non-talks (orientations, the Sandia info session) are now skipped, and the count moved from 178 to 176 records. A talk with no known title is now titled "Talk by <speaker>" rather than "TBA" — 5 of those.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants