Add McLuhan Chapter 1 as Annotated Reading
Implement the following plan:
Add McLuhan Chapter 1 as Annotated Reading
Overview
Add Chapter 1 of Marshall McLuhan's Understanding Media ("The Medium is the Message") as an annotated reading on the course website. Extract text from BOOK.epub, convert to MDX, annotate with <Sidenote> components connecting McLuhan's ideas to modern generative AI, gate behind authentication, and create a /readings/[slug] route.
Steps
1. Extract Chapter 1 from EPUB
Use a tool (e.g. bunx epub-to-text or a script) to extract Chapter 1 text from /BOOK.epub. Convert to clean Markdown. The chapter is "The Medium is the Message."
2. Create the MDX reading file
File: content/spring2026/readings/understanding-media-ch1.mdx
Structure:
---
title: "The Medium is the Message"
author: "Marshall McLuhan"
source: "Understanding Media: The Extensions of Man (1964), Chapter 1"
slug: "understanding-media-ch1"
---
<LoggedInOnly>
<Sidenote>
Provided to CS 199 UAI students under academic fair use.
</Sidenote>
# The Medium is the Message
[Chapter text with inline <Sidenote> annotations throughout...]
</LoggedInOnly>
Key decisions:
- Wrap entire content in
<LoggedInOnly>so only authenticated users see it - Use
<Sidenote>for annotations — block-level asides with accent border that sit inline with the text. These are visually distinct from the reading itself and work well for longer contextual notes - Use
<Footnote>sparingly for brief term definitions where a tooltip is more appropriate than breaking the reading flow - Fair use notice as the first
<Sidenote>at the top, following the pattern from societyand.technology: "Provided to CS 199 UAI students under academic fair use."
3. Annotation strategy
Add <Sidenote> annotations that:
- Aid comprehension: Explain McLuhan's denser passages, define unfamiliar terms or historical references (e.g. who General Sarnoff was, what the "electric light" metaphor means)
- Connect to course themes: Draw parallels between McLuhan's ideas and modern generative AI — e.g. "McLuhan's point about the medium reshaping society applies directly to how LLMs are changing writing: the tool shapes the output regardless of the 'content' fed into it"
- Prompt reflection: Occasionally ask students to pause and consider a question
Target roughly one annotation per major paragraph or key passage — enough to guide students through a difficult text without overwhelming the reading itself.
4. Create the readings route
New file: apps/web/app/[semester]/readings/[slug]/page.tsx
Follow the meetings page pattern (apps/web/app/[semester]/meetings/[slug]/page.tsx):
generateStaticParams()— scancontent/{semester}/readings/for.mdxfiles- Dynamic import:
await import(@content/${semester}/readings/${slug}.mdx) - Render inside
<ProseWithToc>for table of contents support - Wrap in a container div with
data-testid="reading-page"
New file: apps/web/lib/readings.ts
Reading discovery utility following apps/web/lib/meetings.ts pattern:
getReadingSlugs(semesterId)— returns slugs fromcontent/{semester}/readings/*.mdx- Used by
generateStaticParams()
5. Link from meeting/activity pages
No header nav entry needed. Link directly from relevant places:
- Add a link in
content/spring2026/weeks.mdfor the Feb 10 week referencing the reading - The guest lecturer's meeting page (if one exists for Feb 10) can link to
/spring2026/readings/understanding-media-ch1
Files to create/modify
| File | Action |
|---|---|
content/spring2026/readings/understanding-media-ch1.mdx | Create — extracted + annotated chapter |
apps/web/app/[semester]/readings/[slug]/page.tsx | Create — readings route |
apps/web/lib/readings.ts | Create — reading slug discovery |
content/spring2026/weeks.md | Modify — add reading link for Feb 10 week |
Verification
bun run tsc— no type errorsbun run lint— no lint errors- Visit
/spring2026/readings/understanding-media-ch1while logged in — full annotated text visible with sidenotes - Visit same URL while logged out — content hidden by
<LoggedInOnly> - Sidenotes render as accent-bordered asides inline with the reading text
If you need specific details from before exiting plan mode (like exact code snippets, error messages, or content you generated), read the full transcript at: ~/.claude/projects/-Users-challen-www-usingandunderstanding-ai/acb4a880-d5f0-4ec6-ba51-76047bbbe940.jsonl
I'll start by exploring the existing codebase patterns and extracting the chapter from the EPUB. Let me do several things in parallel.
Good, I have the codebase patterns and the extracted chapter text. Let me read the key files I need to follow as patterns, and the extracted chapter text.
Now let me create all four files. Let me start by creating the task list and reading a few more files to confirm patterns.
Now I'll create the annotated MDX reading. This is the main piece of work — the full chapter text with <Sidenote> annotations connecting McLuhan to modern AI.
Now I need to figure out which week corresponds to Feb 10. Looking at the weeks.md, I see Week 3 is about the deep learning revolution and AlphaGo. But the plan says "Feb 10 week" — let me check the course schedule to find the right place to add the link. Looking at the weeks, the McLuhan reading on "the medium is the message" fits thematically with multiple places. Let me check what meeting is around Feb 10.
So the existing meetings are Feb 3 and Feb 5 (Week 2). Feb 10 would be Week 3, which is the AlphaGo discussion week. The reading about "the medium is the message" fits naturally there — students could read McLuhan before discussing how AlphaGo (the medium of AI in game-playing) changed the game of Go itself regardless of any specific move. Let me also look at the config to understand the weekly structure.
Now let me add the McLuhan reading reference to weeks.md. Looking at the structure, Week 3 (deep learning revolution / AlphaGo discussion) has the Feb 10 meeting. I'll add the McLuhan reading there as a pre-reading for the discussion.
Both tsc and lint pass cleanly.
All done. Here's a summary of what was created:
New files:
apps/web/lib/readings.ts— Reading slug discovery utility (scanscontent/{semester}/readings/for.mdxfiles)apps/web/app/[semester]/readings/[slug]/page.tsx— Dynamic readings route withgenerateStaticParams,generateMetadata, andProseWithToclayoutcontent/spring2026/readings/understanding-media-ch1.mdx— Full annotated Chapter 1 with 16<Sidenote>annotations wrapped in<LoggedInOnly>
Modified files:
content/spring2026/weeks.md— Added McLuhan reading link to Week 3
Annotations cover:
- McLuhan's core thesis (the medium reshapes society regardless of content) connected to AI
- The Sarnoff "technology is neutral" argument and its modern AI equivalent
- How "content" distracts from structural transformation (the "meat for the watchdog" metaphor)
- Sequential vs. instantaneous processing (mechanical vs. electric, traditional code vs. LLMs)
- Cubism and the absence of "point of view" in AI-generated content
- De Tocqueville and "mastering the grammar" of a medium as an analogy for this course
- McLuhan's warning about unconscious adoption of a medium's assumptions
- The Jung/slaves passage reframed for AI's psychological influence
Both bun run tsc and bun run lint pass with no errors.
Students will probably find this material challenging. Are the sidenotes written to help them?
(no content)
Let me re-read the sidenotes with fresh eyes.
Honestly, I think the sidenotes have a significant gap. They do one thing — connect McLuhan to AI — but they don't do enough of the other thing the plan called for: helping students actually understand a difficult text.
Specific problems:
-
They don't explain who people are. McLuhan name-drops Hans Selye, David Hume, Alexis de Tocqueville, E. H. Gombrich, Wyndham Lewis, J. M. Synge, Arnold Toynbee, C. P. Snow, A. J. Liebling, C. G. Jung, and more. Only Sarnoff gets a gloss. CS students won't know most of these figures, and not knowing who's being cited makes the argument harder to follow.
-
They skip past the hardest passages. The long de Tocqueville section about print culture, the French Revolution, and English common law (lines 214-235) is dense and abstract — exactly where students will get lost — but there's no comprehension help there. Same for the cubism passage, the Japan/money passage, and the Toynbee "etherialization" section.
-
They don't define McLuhan's vocabulary. Words like "somnambulism," "concatenation," "etherialization," "Narcissus trance" will trip up students. The plan mentioned using
<Footnote>for quick definitions, but none were used. -
The AI connections are repetitive. Many follow the same formula: quote McLuhan, say "this applies to AI," give an AI example. After the third or fourth one, students will start skimming.
-
They're commentary, not scaffolding. They tell students what to think about the text ("This is one of the most important ideas") rather than helping them parse what McLuhan is actually saying.
Want me to revise the sidenotes to better balance comprehension support with the AI connections? I'd add more explanatory notes in the dense middle sections, use <Footnote> for vocabulary/person glosses, and vary the AI connections so they don't all sound the same.
Yes, but aren't we using the stuff^[Footnote] syntax?
Let me check how footnotes are actually used in the existing content.
No existing usage in content. Let me check how the Footnote component works and whether there's any remark/rehype plugin for the ^[...] syntax.
There's a custom remark plugin. Let me read it.
Continue.
(no content)
Right — the ^[...] syntax gets transformed into <Footnote> tooltips by the remark plugin. So I should use ^[...] inline for quick glosses (who people are, what words mean) and reserve <Sidenote> for longer commentary. Let me rewrite the file.
Continue.
Now I'll rewrite the file with ^[...] inline footnotes for glosses and improved sidenotes.
Now let me verify the build still passes.
All clean. Here's what changed in the revision:
Added ^[...] inline footnotes for 22 people and terms that students won't know:
- People: Selye, Sarnoff, Theobald/Rostow/Galbraith, Hume, Gombrich, de Tocqueville, Newman, Matthew Arnold, Gibbon, Wyndham Lewis, Synge, C.P. Snow, Rowse, Toynbee, Schramm, Doob, Liebling, Nef, Jung, Forster, Sansom
- Terms: somnambulism, Narcissus (McLuhan's specific usage), concatenation, lineal, etherialization, Plutus, Dagwood, semaphore telegraph, Gutenberg technology
Improved sidenotes:
- Added a comprehension sidenote for the electric light metaphor (previously un-annotated)
- Added a comprehension sidenote explaining the Selye analogy (previously jumped straight to AI)
- Added a comprehension sidenote for cubism explaining what cubism actually is before connecting it to AI
- Added a comprehension sidenote for the dense de Tocqueville/France/England section explaining why McLuhan cares about print and revolutions
- Added a comprehension sidenote for the "staples" analogy near the end
- Rewrote the sequential/electric sidenote to actually explain the concepts before making the AI connection
- Varied tone — some explain, some connect to AI, some pose genuine reflection questions
- Removed formulaic phrasing ("This is McLuhan at his most radical," "This is one of the most important ideas")
- Moved the Sarnoff biographical info from a sidenote to a footnote, freeing the sidenote for the actual argument
Nice! Now, let's create next Tuesday's meeting document. It should simply state that my friend and colleague, [redacted], will lead a discussion on the reading. How would you summarize that? Please link to this website: https://philosophy.illinois.edu/directory/profile/zbiondi. And can we add a section to the meetings page for upcoming meetings? It should be next, upcoming, and then previous.
(no content)
Let me look at the current meetings listing page and understand how meetings are displayed.
Now I understand the structure. Currently the page has "Next Meeting" (singular) and "Previous Meetings." The user wants three sections: Next, Upcoming, and Previous. Let me also look at the existing meeting frontmatter to match the format.
Let me check if getMeetingsByStatus is used elsewhere.
Good, only used in the meetings page. Now let me also quickly check who Zach Biondi is so the summary is accurate.
Good context. Now I'll make all three changes: create the meeting file, update the meetings utility to split next/upcoming/past, and update the meetings page.
Now update the meetings utility to return next, upcoming, and past.
Now update the meetings page to use the three sections.
Now let me check if there are any e2e tests that reference the old data-testid values.
No tests to update. Let me verify the build.
This page is blank: https://[local-hostname]/spring2026/readings/understanding-media-ch1
(no content)
Let me investigate the MDX import configuration and how the content alias resolves.
Do I need to restart the server?
Yes, almost certainly. The new readings route files were created after the dev server started, so Next.js won't have picked them up. Restart the dev server and try again.
Nope. Still blank.
(no content)
Let me check what's happening — could be an MDX compilation error or a rendering issue.
Returns 200, so the page loads but renders empty. Let me check whether you're logged in — everything is inside <LoggedInOnly>. Let me also check the response body size and look for any error output from the server.
The HTML does contain the content (McLuhan, Medium, etc.) and "reading-page" is present. But there are multiple "error" strings. Let me look at what's happening more specifically.
I logged in and now see the content. However, there are other issues. Let's have the page redirect to login if needed. Second, we need to work on the sidenotes. We need to attach them visually to the content somehow. Is there a way to do that? Ideally they'd be horizontally aligned with their anchor. Also put the author under the title and follow that with the fair use bit.
(no content)
Here's a long discussion of effective sidenotes: https://gwern.net/sidenote. We may also want to use both sides of the page, and limit their size while allowing them to scroll or be opened fully on hover.
(no content)
(no content)
There are several interconnected changes here. Let me explore how auth redirects work in this app, then implement everything.
Let me check if sidenotes are used anywhere besides the reading.
Only used in our reading. That simplifies things — I can freely change the sidenote CSS without worrying about other pages. Now let me check the full globals.css file for context around the sidenote section.
Good, I have everything I need. Let me now implement all the changes. I'll do them in parallel where possible.
Now update the MDX — remove the <LoggedInOnly> wrapper and the first sidenote (fair use + reading tips are now rendered by the page), but keep the reading tips as the first sidenote.
Now I need to check if semesterInfo has a shortTitle field. Let me verify.
But semesterInfo is from the semesters registry, not the course config. Let me check what the semester object looks like.
SemesterInfo doesn't have shortTitle. Let me fix the reading page to just hardcode the course name since it comes from the config, not the semester.
Now let me verify the build.
All clean. Let me also run lint.
Much better! Now, can the side note bits bracket the text they annotate somehow, using almost a mathematical brace pattern? And can the left-side notes have that on the right? Also, when the page gets too large these are hidden. It would be better at that point to make sure that they are still visible somehow and open them on hover, similar to a footnote.
(no content)
Oh, and the footnotes need to work a bit better. They should open on the bottom if they are close to the top of the screen when hovered.
(no content)
Actually, wait, sorry. Rather than brackets, can we add underlines to the Sidenote somehow to connect them with the main text? So some of the main text is underlined and then there's a sidenote. That would work better and also support thin displays, on which the underline should just work like a footnote.
(no content)
What's up? Do we need to plan a bit?
Yes, let's plan. There are several interconnected pieces and I want to make sure we get the design right before writing code. Let me summarize what I'm hearing:
- Sidenotes should connect to specific text — underline a span of the main text, and the sidenote is visually linked to that underlined span
- On wide screens — the sidenote appears in the margin, aligned with the underlined text
- On narrow screens — the underlined text acts like a footnote trigger; hover/tap reveals the sidenote inline (like the existing
<Footnote>tooltip, but for longer content) - Footnote positioning — should open downward when near the top of the screen instead of always popping above
This changes the MDX authoring format. Currently sidenotes are standalone blocks between paragraphs. To connect them to specific text, we'd need something like:
McLuhan's opening argument is the thesis^[sidenote content here] of the entire book.
But that's already the ^[...] footnote syntax. So we need a different marker for "this is a margin note, not a tooltip." Or we could have a single system where short notes become tooltips and longer notes become margin notes.
Alternatively, we could do something like wrapping the anchor text:
<Note anchor="McLuhan's opening argument is the thesis of the entire book">
Commentary that appears in the margin on wide screens, or as a popover on narrow screens.
</Note>
That would underline the anchor text and render the note content in the margin.
Let's say that sidenotes can connect to specific text. This might require two pieces: the sidenote itself, and then a marker in the text. One pattern I've used in the past is special links, so this text connects to sidenote2, or whatever. We can design that syntax if needed if it's helpful. Markdown is a bit limited here but you can work around it.
Now let me design the new plan. Let me also quickly check how the a component override would work with the ~id~ href pattern.
You don't have to use that pattern. That was just an example. The idea is to use some format that could not be mistaken for an actual link.
(no content)
Good point. I'll use [text](sn:note-id) — sn: isn't a real URI scheme, so it can't be confused with a link. Let me write up the plan.