EdTech Platform

Activity Details Page

Consolidated five distinct activity types — assessment, flashcard, lesson, interactive video, and reading passage — into a single page component. Led adoption of the design system, streamlined monetization logic, and improved metrics by an average of 5pp across all CTAs.

Vue 3Composition APITypeScriptDesign SystemProvide/InjectSSR-Compatible

THE PROBLEM

The platform supported five different content types — assessments, flashcards, lessons, interactive videos, and reading passages — but each had a fragmented preview experience. Passage and interactive video were second-class citizens with incomplete rendering, and adding a new content type meant duplicating page scaffolding across multiple files.

Monetization logic (CTAs, content gating, sign-up prompts) was inconsistent across types, leading to missed conversion opportunities. The design system had been adopted piecemeal with no stability testing on a high-traffic public page.

+5pp

Average improvement across all CTAs

5 Types

Assessment, Flashcard, Lesson, Video, Passage

3 Versions

V1 (mobile-first) → V2 (sidebar) → V3 (tabs)

CONTENT TYPE MATRIX

A single page component handles five completely different content shapes. The rendering path is determined by the quiz type and the presence of comprehension questions.

Content TypeMain ContentSide ContentSpecial Features
AssessmentQuestions listStudent previewContent gate after 10 Qs
FlashcardQuestions listStudent previewTerm + definition cards
LessonSlideshow (desktop) / Questions (mobile)No quality card, no preview
Interactive VideoQuestions listVideo player + transcriptTimestamp markers link to questions
Reading PassageQuestions listPassage viewer (resizable)Narration link, split view

How Content Type is Detected

quiz.type === FLASHCARD

Flashcard rendering

quiz.type === LESSON

Lesson slideshow

COMPREHENSION_VIDEO in questions

Interactive video split

COMPREHENSION in questions

Reading passage split

Default (no match)

Standard assessment

COMPONENT ARCHITECTURE

A leaf package with no stores and no services. All data flows through props and provide/inject — making it consumable by any host application.

Top-Down Data Flow

Host Application

Fetches quiz data, recommendations, determines page version

Activity Details Page (V1 / V2 / V3)

quiz: Quizrecommendations[]popularResources[]subjectResources[]breadcrumbs[]qualifiers[]

Provide / Inject to Children

openAuthModalopenShareModalopenReportModalfireClickEventfireModalViewEventkatex (lazy)

Activity Info

Activity card (desktop + mobile)
Grade range display
Play count
Author info
Difficulty indicator
Standard alignment tags
Breadcrumbs

Content Preview

Interactive video player + transcript
Reading passage viewer
Lesson slideshow renderer
Student quiz preview
Compact mini preview

Questions Section

Questions container with content gate
Question detail cards (shared package)
Content blocker overlay
Mobile lesson question list

Recommendations

Similar resources carousel
Popular resources carousel
Subject resources carousel
Activity display cards with type badges

THREE PAGE VERSIONS

Same data contract, different layouts. Each version gets progressively simpler while adding features — enabling A/B testing and gradual rollout via feature flags.

V1

Single Column

Mobile-first, fully responsive
636 lines — handles all content types
Vertical stack: info → content → questions → recommendations
Fixed action bar on scroll
Mobile sticky bottom CTA

V2

3 + 9 Grid

Desktop sidebar with related activities list
410 lines — desktop-optimized
Sidebar: activity card list (vertical)
Main area: full V1 content
Added AI enhancement action chips

V3

4 + 8 Grid

Sticky sidebar with activity details
237 lines — simplest version
Tab-based content: Questions | Student Preview
Actions consolidated into dropdown
Cleanest component decomposition

Progressive Simplification

V1

636 lines

V2

410 lines

V3

237 lines

DATA FLOW

The useActivityDetails composable filters comprehension questions from the quiz data to drive the entire layout decision — split view or single list.

Raw Quiz (prop)

Full quiz object with all questions including comprehension parents

useActivityDetails(quiz)

Filters out COMPREHENSION and COMPREHENSION_VIDEO questions from the array

Output determines layout

filteredQuiz

Questions minus comprehension

passageQuestion

The COMPREHENSION question (if any)

containsPassage

Boolean → show passage split

containsVideo

Boolean → show video split

Layout Decision

Single Column

Standard assessment / flashcard

Split View

Passage or video + questions

CONTENT GATING

A growth/conversion mechanism: anonymous users see a preview, authenticated users see everything. This directly contributed to the +5pp CTA improvement.

Quiz has < 10 questions

Show all questions immediately — no gate

Quiz has 10+ questions

Questions 1–6: Fully visible

Content Blocker overlay appears

"Sign up to see all questions" CTA

Questions 7–10: Rendered but hidden

Pre-rendered for SEO, hidden from view

User signs up or has cookie

showHiddenQuestions = true → all questions visible, blocker removed

ACTION SYSTEM

Left Actions (Utility)

EditAUTH
Worksheet
Share
Save

Right Actions (Primary CTAs)

Previewsecondary
Use this activityprimary

Dropdown Actions

PrintEmbedReport an issue

KEY DECISIONS

Leaf Package with No Stores

The Activity Details Page has zero coupling to data fetching — it receives a Quiz object as a prop and renders it. No Pinia stores, no API services. This makes it consumable by any host application (SSR or SPA) and trivially testable with mock data.

Comprehension Filtering as Layout Driver

Rather than using explicit type checks everywhere, the useActivityDetails composable detects passage/video comprehension questions and separates them. This single filter drives the entire layout decision: split view (passage + questions or video + questions) vs. single column. Adding a new comprehension type requires zero layout changes.

Three Versioned Components, One Data Contract

V1, V2, and V3 all accept the same props interface. The host application picks which version to render via feature flag. This enabled safe A/B testing (V1 vs V2), gradual rollout (V2 → V3), and instant rollback — all without changing the data layer.

Content Gating for Growth

The 10-question gate with a sign-up wall after question 6 was a deliberate conversion mechanism. Questions 7-10 are pre-rendered (for SEO) but hidden. On sign-up, a cookie is set that immediately reveals all content. This single pattern directly contributed to the +5pp improvement across all CTAs.

Design System Adoption as Proving Ground

Led adoption of the company's design system on this high-traffic public page — the first major consumer. This tested the system's stability under real conditions, uncovered edge cases (responsive grid, conditional slots, theming), and gave confidence for broader rollout across the platform.

Back to all Projects

Built with Vue 3, Composition API, TypeScript, and the Design System