The Challenge System is the core learning interface where users complete coding exercises, projects, quizzes, and other educational content. It manages the entire lifecycle of a challenge from initial load through code editing, testing, and submission. This page provides an overview of the architecture and data flow.
For details on specific challenge types and their rendering logic, see Challenge Types and Rendering. For information about the code editor, execution environment, and test runner, see Code Editor and Execution.
The challenge system follows a layered architecture with clear separation between data, state, presentation, and execution:
Sources: client/src/templates/Challenges/classic/show.tsx1-625 client/src/templates/Challenges/redux/index.js1-299
Challenges are defined as markdown files with YAML frontmatter and validated against a strict schema. The ChallengeFile type represents individual code files within a challenge:
Key Types:
| Type | Location | Purpose |
|---|---|---|
ChallengeNode | client/src/redux/prop-types.ts187-252 | Complete challenge data from GraphQL |
ChallengeFile | shared/utils/polyvinyl.ts13-24 | Individual code file with metadata |
ChallengeMeta | client/src/redux/prop-types.ts492-503 | Runtime metadata (paths, state) |
Test | client/src/redux/prop-types.ts368-382 | Test definition with assertion code |
Sources: client/src/redux/prop-types.ts187-252 client/src/templates/Challenges/classic/show.tsx18-31
The challenge state is managed in the challenge namespace (denoted as ns in selectors) with the following structure:
Key Actions:
| Action | Location | Purpose |
|---|---|---|
createFiles | client/src/templates/Challenges/redux/actions.js5 | Initialize challenge files |
executeChallenge | client/src/templates/Challenges/redux/actions.js22 | Run tests via saga |
initTests | client/src/templates/Challenges/redux/actions.js15 | Load test definitions into state |
updateChallengeMeta | client/src/templates/Challenges/redux/actions.js33 | Update challenge runtime metadata |
Key Selectors:
| Selector | Location | Purpose |
|---|---|---|
challengeFilesSelector | client/src/templates/Challenges/redux/selectors.js18 | Get current file state |
challengeMetaSelector | client/src/templates/Challenges/redux/selectors.js19 | Get challenge metadata |
challengeTestsSelector | client/src/templates/Challenges/redux/selectors.js22 | Get test results |
isChallengeCompletedSelector | client/src/templates/Challenges/redux/selectors.js30-37 | Check completion status against user history |
Sources: client/src/templates/Challenges/redux/actions.js1-71 client/src/templates/Challenges/redux/selectors.js1-130
The complete lifecycle from page load to submission follows this flow:
Initialization Phase (client/src/templates/Challenges/classic/show.tsx372-405):
The component calls initTests, updateChallengeMeta, and challengeMounted inside useEffect on mount. For classic challenges, createFiles initializes the editor content from the challenge seed or saved state via mergeChallengeFiles (client/src/templates/Challenges/classic/saved-challenges.ts1-35).
Execution Phase (client/src/templates/Challenges/redux/execute-challenge-saga.js110-172):
The executeChallengeSaga handles the build and test flow:
challengeDataSelector (client/src/templates/Challenges/redux/selectors.js74-122).buildChallenge from the challenge-builder.getTestRunner (client/src/templates/Challenges/utils/build.ts23-36).Sources: client/src/templates/Challenges/classic/show.tsx372-405 client/src/templates/Challenges/redux/execute-challenge-saga.js110-172 client/src/templates/Challenges/utils/build.ts23-36
Different challenge types use different React templates, routed by challengeType:
Template Mapping:
| Template | File Path | Key Features |
|---|---|---|
ShowClassic | client/src/templates/Challenges/classic/show.tsx195-568 | Monaco editor, Live Preview, Xterm (Python) |
ShowQuiz | client/src/templates/Challenges/quiz/show.tsx91-272 | useQuiz hook, shuffled distractors, audio support |
ShowExam | client/src/templates/Challenges/exam/show.tsx142-443 | Timed exams, prerequisite checks, result summaries |
ShowFillInTheBlank | client/src/templates/Challenges/fill-in-the-blank/show.tsx81-272 | Multi-blank validation, Pinyin support for Chinese |
ShowGeneric | client/src/templates/Challenges/generic/show.tsx110-344 | Video player, assignment checkboxes, MCQ nodules |
ShowCodeAlly | client/src/templates/Challenges/codeally/show.tsx116-374 | External IDE instructions, user token generation |
Sources: client/src/templates/Challenges/classic/show.tsx195-568 client/src/templates/Challenges/quiz/show.tsx91-272 client/src/templates/Challenges/exam/show.tsx142-443 client/src/templates/Challenges/fill-in-the-blank/show.tsx81-272
The ShowClassic component composes several sub-components to provide the coding environment:
react-reflex for instructions, editor, and preview panes.Sources: client/src/templates/Challenges/classic/desktop-layout.tsx98-395 client/src/templates/Challenges/classic/show.tsx168-187 client/src/templates/Challenges/classic/multifile-editor.tsx55-179