Plan: Full-screen display page + sidebar link
Implement the following plan:
Plan: Full-screen display page + sidebar link
Context
The display page is meant for the classroom projector. Currently it renders the entire MDX file (including non-activity content like the title, intro paragraphs, <hr>) and shows all stages stacked before session start. The user wants:
- Full-screen, no-scroll experience that just works — put it up and forget it
- "Waiting for class to start..." before session starts
- Only the current stage content during the session, auto-advancing via sockets
- A sidebar link for instructors to quickly open it
Files to Modify
1. apps/web/components/display/display-activity-stages.tsx
Make this component take over the full viewport. Wrap content in a fixed inset-0 z-50 bg-background container that covers the entire page — this hides the non-activity MDX content (title, paragraphs, <hr>) behind it without needing to change the page layout. Flex-center for vertical alignment.
2. apps/web/components/display/display-activity-stage.tsx
Two states:
Pre-session (!sessionExists): Only stage index 0 renders a centered "Waiting for class to start..." message with the meeting title if available. All other stages return null.
Active session: Only the current stage renders. Show:
- Stage number badge + label at the top
- Stage content below with comfortable padding and max-width for projector readability
- Overflow-y-auto on the content area in case a stage has long content, but the container itself is viewport-height
3. apps/web/components/print-links.tsx
Add a "Display" section above the "Print" section with a link to /{semester}/meetings/{slug}/display that opens in a new tab.
Verification
bun run tsc- Open display page before starting session → "Waiting for class to start..." centered on full screen
- Start session from instructor view → display shows current stage content, full screen, no surrounding MDX content visible
- Advance stages → display updates in real-time, no scrolling needed
- Instructor sidebar → "Display View" link opens display in new tab
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/70622967-6f9b-4513-8833-2462cf8441aa.jsonl
If this plan can be broken down into multiple independent tasks, consider using the TeamCreate tool to create a team and parallelize the work.
Let me read the files I need to modify.
Now let me check the meeting context to understand what data is available.
Let me check the display page layout and how meeting titles are accessed.
Now I have a clear picture. Let me implement all three changes.
Now let me verify totalStages is available from the activity stage context.
Good, totalStages is available. Now let me run the type check.
All three changes are done and TypeScript passes cleanly. Here's a summary:
display-activity-stages.tsx— Outer container is nowfixed inset-0 z-50with centered flex layout, covering the entire viewport (hiding MDX content behind it).display-activity-stage.tsx— Pre-session shows "Waiting for class to start…" (only stage 0 renders). Active session shows only the current stage with a number badge, label, and stage counter.print-links.tsx— Added a "Display" section above "Print" with a link to the display page that opens in a new tab.
Now for your follow-up — you want estimated times shown on the display page. I can see from the screenshot that the instructor view shows 4:11 / 15:00 (elapsed / estimated). Let me check how the stage metadata (specifically estimatedTimeSeconds) is accessed so I can add it to the display stage.
Let me check how the instructor view renders the estimated time to understand what you want on the display.
The estimatedTime prop is already available on DisplayActivityStage from the MDX. I just need to use it in the display. Let me update the component.
Now add the estimated time to the stage header display.
TypeScript passes. The display stage header now shows the estimated time (e.g., "15:00") followed by the stage counter (e.g., "3 / 8"), separated by a middle dot. It'll look like:
(3) Class Discussion 15:00 · 3 / 8
The estimated time only appears when the MDX stage has an estimatedTime prop set.
Nice! Can we also add actual wall clock times once the activity starts, to help me time things and understand when boundaries should happen? These should be updated to be correct as the activity proceeds.
Let me understand what timing data is available from the context.
Now let me read the current display-activity-stage.tsx to see what I'm working with.
TypeScript passes. Here's what the display stage now shows during an active session:
Header row: (3) Class Discussion with 15:00 · 3 / 8 on the right
Timeline row (updates every second):
Started 2:15 PM— actual wall clock time the stage beganElapsed 4:11 / 15:00— effective elapsed vs estimated (turns red when overtime)Ends ~2:30 PM— projected end time that adjusts for pauses (orOver by 1:23if past the estimate)Pausedindicator when the session is paused- Future stage projections in lighter text:
Strategy Review ~2:40 PM · Class Discussion ~2:55 PM
The projected times account for pauses — if you pause, the "Ends ~" time pushes forward. And the future stage timeline lets you see at a glance when the whole activity should wrap up.
For today's activity next time let's have the link share happen to signal completion of each lab section: practice testing, build a study aid.
Let me find today's meeting content to understand the current stage structure.
Weren't people supposed to submit Gemini links for this?
Looking at the meeting content, students are asked to submit AI conversation share links in the <TextSubmission> sections (lines 123-126 and 161-163), and the instructions mention how to create share links for ChatGPT, Claude, and Gemini (lines 105-106, 121, 143).
So yes, the link sharing is already part of the share-out stages. Were you asking whether there's a specific requirement to use Gemini specifically (rather than ChatGPT/Claude/Gemini as options)? Or did you mean something else about enforcing Gemini links?
Right, but it should be to signal completion of the previous stage. Also some students are sharing text. Is that allowed?
Let me check what validation TextSubmission does on the input.
Right now there's no URL validation — TextSubmission accepts any text. So yes, students can submit plain text without a link and it'll go through.
Two things to address:
-
Move the
<TextSubmission>into the lab stages (Practice Testing, Build a Study Aid) so submitting the link signals completion of the work, rather than being in the separate Share Out stages. -
Require a URL in the submission — do you want me to add validation to
TextSubmissionthat requires at least one URL to be present before allowing submit? Something like arequireLinkprop so it's opt-in per usage?
I thought we would have students submit a link and an optional description? Then validate the link? But I guess it's fine. Do we scan for Claude / Gemini / GPT links?
Let me check what link detection exists.
No — there's no link validation or detection anywhere. The TextSubmission component is just a free-text box with no awareness of URLs.
So for next time, the plan would be:
- Move
<TextSubmission>into the Practice Testing and Build a Study Aid stages to signal completion - Add a
requireLinkprop (or similar) that validates the submission contains a recognized AI chat share link (ChatGPT, Claude, Gemini share URLs) before allowing submit - Optionally separate the form into a link field + an optional description/reflection field so it's clearer what's expected
Want me to build the link validation into TextSubmission (with a requireLink prop), or would you prefer a separate dedicated component for link submissions? A separate component might be cleaner since the UX is different — a URL input field + optional text area rather than a single big textarea.
I'd like to have a way to have students submit a verified GPT / Gemini / Claude share link, verified using the library we developed, and potentially text describing the link. We can use this in the future.
Let me find the share link library.
Good, I have a thorough understanding of the system. Let me design the plan.
Now let me write the final plan.