Skip to content

Python Guides — Level Personification Design

Date: 2026-06-23 Status: Approved, ready for implementation planning Scope: Visual only. No teaching content is rewritten in this phase.

Summary

Turn the three Python reading levels (Beginner / Intermediate / Deep Dive) into three named guides with personalities and avatars. The learner "picks a guide" during onboarding, and from then on every recap callout (<CharacterMessage>) in the Python course speaks as that guide — its avatar and name reflect the selected guide, while the recap's existing topic title is preserved as a sub-label.

The guides reuse the personas from the existing /persona-preview test (Crooked Orbit crew): Juno (beginner), Ace (intermediate), Sol (deep dive).

This is a deliberately contained, visual-only change. The bubble body text is not rewritten in this phase — only the speaker identity (avatar + name) and a topic eyebrow are added.

Goals

  • Personify the three levels as guides with avatar + name + one-line personality.
  • "Pick your guide" onboarding flow (reuse the existing WelcomeModal level step).
  • Every Python recap callout shows the selected guide's avatar and name, live-updating when the learner switches guide.
  • Keep each recap's existing topic title (currently in the name attribute) visible as a sub-label so nothing is lost.
  • Zero markdown content edits across the ~370 existing <CharacterMessage> callouts.

Non-Goals

  • Rewriting any teaching content or recap body text (future phase).
  • Adding per-guide voice/tone to the bubble copy (future phase).
  • Applying guides to the How AI Works track or any non-Python pages.
  • Changing the bughouse project page, which has its own named characters.

Key Context (verified)

  • Level state lives in docs/.vitepress/theme/composables/useDocPrefs.ts as level: 'beginner' | 'intermediate' | 'advanced', persisted to localStorage and global.
  • showLevel: true frontmatter is present on exactly the 13 leveled Python chapters (and their localized copies under es/, pt/, etc.). It is not present on how-ai-works/* or python/bughouse.md. This makes it a clean, Python-only signal for "guide mode."
  • CharacterMessage.vue currently picks an avatar by: explicit char prop → CHARACTER_CHARS name lookup (only Juno/Ace/Sol mapped) → hash of the name string. In leveled Python chapters, name holds the recap topic (e.g. "Storing a value"), so today each recap shows a topic title + a hash-random avatar.
  • Named-character bubbles (Cass, Dex, Pip, Zee, Orla) appear only in python/bughouse.md, which has no showLevel, so they are naturally excluded from guide mode and remain unchanged.
  • The three guide avatars already exist:
    • docs/public/pixel_chars/f468.webp (Juno)
    • docs/public/pixel_chars/f704.webp (Ace)
    • docs/public/pixel_chars/f509.webp (Sol)
  • The existing onboarding entry point is WelcomeModal.vue (first-visit modal asking language + level + theme). Level pickers also live in FloatingDocPrefs.vue and DocLevelBadge.vue.

Design

1. Guide config — single source of truth

New file: docs/.vitepress/theme/composables/guides.ts.

Exports a map keyed by DocLevel:

levelnamepronounsbarsavatarblurb
beginnerJunoshe/her1/pixel_chars/f468.webpOnboarding lead. Warm and patient.
intermediateAcethey/them2/pixel_chars/f704.webpSystems engineer. Practical, build-first.
advancedSolshe/her3/pixel_chars/f509.webpChief engineer. Dry, jaded, kind underneath.

Each entry also carries the existing level label string (Beginner / Intermediate / Deep Dive) so the pickers can drop their duplicated label lists. Type the map as Record<DocLevel, Guide> and export a Guide interface.

All consumers (CharacterMessage, WelcomeModal, FloatingDocPrefs, DocLevelBadge) import from here. No level→label or level→avatar data is duplicated anywhere else after this.

2. CharacterMessage.vue — guide mode

Add awareness of guide mode:

  • Import useData (for frontmatter), useDocPrefs (for level), and GUIDES.
  • Compute guideMode = frontmatter.value.showLevel === true.
  • When guideMode is true:
    • Speaker name = GUIDES[level].name (rendered in the existing .cm__name style).
    • Avatar = GUIDES[level].avatar.
    • The incoming name prop is rendered as a topic eyebrow beneath the guide name (new small, muted label).
    • Reactive: switching level re-renders all bubbles live.
  • When guideMode is false: behavior is unchangedname is the speaker, avatar via char prop → CHARACTER_CHARS → hash fallback. This preserves bughouse and how-ai-works.

Rendered layout in guide mode:

[Juno avatar]  JUNO
               STORING A VALUE      <- topic eyebrow (was the `name` attr)
               A variable is a labelled box you...   <- existing slot body

The char prop still works as an explicit override if ever needed; an explicit char should take precedence even in guide mode (escape hatch), though no current page uses it.

3. "Pick your guide" surfaces

All read guides.ts:

  • WelcomeModal.vue — rename the "Your level" section to "Pick your guide". Each option becomes a card showing the guide avatar, name, level label (with bars), and the one-line blurb. Selecting a card sets selectedLevel exactly as today. Confirm/skip logic unchanged.
  • FloatingDocPrefs.vue — the level chips show the guide name with the level (e.g. "Beginner · Juno"). Keep the LevelBars icon. Selection logic and URL-variant sync unchanged.
  • DocLevelBadge.vue — show the active guide's name (and optionally avatar) alongside the level label, sourced from guides.ts. Tooltip copy can reference "your guide."

4. Scope guard

Guide mode is gated solely on frontmatter.showLevel === true. Today that is exactly the leveled Python chapters and their translations. No route checks needed. How AI Works, bughouse, and other pages are untouched. Localized Python pages inherit guide mode automatically: guide names are proper nouns, and the topic eyebrow uses the already- translated name value.

Affected files

  • New: docs/.vitepress/theme/composables/guides.ts
  • Edit: docs/.vitepress/theme/components/CharacterMessage.vue
  • Edit: docs/.vitepress/theme/components/WelcomeModal.vue
  • Edit: docs/.vitepress/theme/components/FloatingDocPrefs.vue
  • Edit: docs/.vitepress/theme/components/DocLevelBadge.vue
  • No markdown content edits.

Risks / edge cases

  • A leveled Python chapter that intentionally wants a real named character in a bubble would be overridden by guide mode. None exist today (verified: named characters are bughouse-only). The explicit char override plus a possible future as/fixed prop is the escape hatch if this ever comes up.
  • useData() frontmatter access inside a deeply nested component: already proven safe — DocLevelBadge.vue does exactly this.
  • SSR: guide name/avatar depend on the level ref, which defaults to beginner on the server and hydrates from localStorage on the client (same pattern as today's level system).

Future phases (out of scope)

  • Rewrite recap body copy in each guide's voice (the persona-preview demonstrates this).
  • Extend guides to the How AI Works track.
© 2026 Scrimba