Show meeting activity content to unauthenticated users
Implement the following plan:
Show meeting activity content to unauthenticated users
Problem
When a logged-out user visits a meeting page with activities (e.g. /spring2026/meetings/2026-01-27-ai-scavenger-hunt), ActivityStages replaces all stage content with a compact ActivityStagesPreview showing only stage labels and a "Log in" CTA. This hides the rich educational content (explanations, missions, strategies) that makes the page valuable to visitors.
Approach
Add a lightweight "preview mode" rendering path. Instead of hiding all stage content, render it read-only with interactive components showing disabled/placeholder states.
Component tree after changes (unauthenticated):
<GroupActivity> → "Partner Activity" banner + children (no change)
<ActivityStagesPreview> → overview card with login CTA (kept at top)
<ActivityStagesPreviewProvider> → NEW: minimal context with isPreview: true
<ActivityStageClient> → renders header + content, no controls
<FacilitationNotes> → returns null (isAdmin: false, correct)
<GroupRoleContent> → shows all roles with role badges
<TextSubmission> → shows "Log in to submit" placeholder
File changes
1. apps/web/components/mdx/activity-stage-context.tsx
- Add
isPreview: booleantoActivityStagesContextValueinterface - Set
isPreview: falsein existingActivityStagesProvidervalue - Add new
ActivityStagesPreviewProvider— minimal client component that provides the context with all stages unlocked, no API polling,isPreview: true,isAdmin: false
2. apps/web/components/mdx/activity-stages.tsx
- Change the
!session?.userbranch (line 175) from returning only<ActivityStagesPreview>to rendering both the preview card AND the indexed children wrapped in<ActivityStagesPreviewProvider>
3. apps/web/components/mdx/activity-stage-client.tsx
- Destructure
isPreviewfromuseActivityStages() - Add early return when
isPreview: render stage number, label, and content only — no completion buttons, pause/stop overlays, countdown timers, or admin badges
4. apps/web/components/mdx/group-role-content.tsx
- Check
useOptionalActivityStages()?.isPreviewbefore the existing "no group context" null return - When in preview mode: show all role content with role badges (similar to instructor view but with distinct color)
5. apps/web/components/mdx/text-submission.tsx
- Check
getUserRole()for"guest"before renderingTextSubmissionClient - Return a styled "Log in to submit a response" placeholder instead — prevents the client component from mounting and making 401 API calls
6. E2E test: testing/e2e/tests/activity-stages.spec.ts
- Update the unauthenticated test to expect both
activity-stages-previewANDactivity-stage-0to be visible - Assert no completion buttons in preview mode
Files NOT changed (already correct)
facilitation-notes.tsx— checks!context?.isAdmin, returns null (preview setsisAdmin: false)instructor-only.tsx— checksgetUserRole(), returns null for guestsgroup-activity.tsx— already shows banner + passes children for unauthenticated users
Verification
- Visit
/spring2026/meetings/2026-01-27-ai-scavenger-huntwhile logged out — should see full stage content with role badges and "Log in to submit" placeholders - Same page while logged in as student — no change to existing behavior
bun run tsc— type check passesCI=true bun run test:e2e— E2E tests pass (after updating the activity-stages test)
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/2dc8bc0a-d241-45e2-8339-890a14b16cce.jsonl
I'll start by reading the key files that need to be modified to understand their current structure.
Now let me also read the roles utility and the ActivityStagesPreview component to understand the existing patterns.
Good, I have a clear picture of all the files. Let me create tasks to track this work and then start implementing.
Now let me start implementing. Task 1 first.
Now add isPreview: false to the existing provider's value object:
Now add the ActivityStagesPreviewProvider at the end of the file, before the CurrentStageIndexContext section:
Now task 2 — update ActivityStages to render content in preview mode.
Now replace the unauthenticated branch to render preview card + content:
Now add the unauthenticated branch back after the indexedChildren block, before the API fetch:
Task 3 — add preview mode rendering to ActivityStageClient.
Now add the early return for preview mode, right after the destructuring and before the state hooks:
Wait — early return before hooks would violate React's rules of hooks. The hooks (useState, useEffect, useCallback) must always be called. I need to restructure this differently. Let me put the preview check after all hooks and before the render logic.
Now place the preview check after all hooks — after handleComplete and before the shouldShow check:
Task 4 — update GroupRoleContent to show all roles in preview mode.
Task 5 — add guest placeholder to TextSubmission.
Task 6 — update the E2E test.
Task 7 — run verification. Let me start with the TypeScript check and check if the dev server is running.
TypeScript check passes. Dev server is running. Now let me run the E2E tests for the activity-stages project.
All 15 tests pass, including the updated unauthenticated test.
All done. Here's a summary of the changes:
1. activity-stage-context.tsx — Added isPreview: boolean to the context interface, set it to false in the existing ActivityStagesProvider, and added a new ActivityStagesPreviewProvider client component that provides the context with isPreview: true, isAdmin: false, all stages unlocked, and no API polling or socket connections.
2. activity-stages.tsx — The !session?.user branch now renders both the ActivityStagesPreview overview card and the indexed stage children wrapped in ActivityStagesPreviewProvider, instead of hiding all content.
3. activity-stage-client.tsx — When isPreview is true, renders only the stage number, label, and content — no completion buttons, pause/stop overlays, countdown timers, or admin badges.
4. group-role-content.tsx — In preview mode, shows all role content with blue role badges (distinct from the amber badges used in instructor view), bypassing the group formation requirement.
5. text-submission.tsx — Checks for "guest" role before rendering the client component. Returns a "Log in to submit a response" placeholder, preventing 401 API calls.
6. activity-stages.spec.ts — Updated the unauthenticated test to expect both the preview card and read-only stage content, while asserting no completion buttons are present.
Your task
First, run git status, git diff, and git log --oneline -10 to understand the current state.
Then add and commit all modified files with a descriptive message. Break the changes into multiple commits if appropriate. If there are untracked files, ask if they should be added or added to the appropriate .gitignore file. The user may also want to take over at this point, so provide an abort option as well. Always check changes for unnecessary debugging statements or logging that might have been accidentally included. Prompt the user if you find any, and offer to remove each one by one. Do not use interactive git staging (git add -p) as it does not work.
No untracked files, no debugging statements or stray logging in the diff. All changes are cohesive — this is a single logical feature. I'll commit it as one.
Committed as 8c1aac7. Working tree is clean.
We need to simplify deployment. Currently it requires me following a bunch of steps, but there must be a better way. I'd like one command the does the right thing and doesn't generate a lot of unnecessary output except on failure.
(no content)
Let me start by reading the existing plan file and exploring the current deployment setup.
Different task — I'll start fresh. Let me explore the current deployment setup.
(no content)
Good, I have a comprehensive picture of the deployment setup. Let me read a few key scripts to understand the exact output patterns and error handling.
Let me check one more thing — how drizzle migrations work and whether we can detect pending ones.
I have a thorough understanding of the deployment setup. Let me ask one question before writing the plan.
I'd rather these be set up as bun run deploy:dev and bun run deploy:prod rather than as scripts. Same thing with things like k8s restarts.
(no content)
Good point. Let me check the current package.json scripts to see what's already wired up and what needs to change.
Now I have a complete picture. Let me write the plan.