This document translates the existing project docs into an execution plan for implementation.
It is the primary source for generating GitHub issues.
Read this after:
PRD.mdCONTENT-SCHEMA.mdSTATE-SCHEMA.mdARCHITECTURE.mdSTACK-DECISIONS.md
This file exists to:
- sequence the MVP work in a dependency-aware order
- define issue-sized implementation units
- make it easy for agents or humans to pick the next task
- support a workflow where one branch contains many commits from different issues
- support a later single bundled PR once the issue set is complete
Mathinik implementation is expected to follow this execution style:
- one long-lived implementation branch
- one GitHub issue = one commit
- multiple issue commits accumulate on the same branch
- each commit should be scoped tightly to a single issue
- the branch should remain healthy as work progresses
- one final PR can be opened after the planned batch or MVP is complete
Use one implementation branch for the active build phase.
Suggested branch name example:
feat/mathinik-mvp
Each issue should produce exactly one coherent commit whenever practical.
Suggested commit format:
feat: scaffold app shell (#12)feat: add local profile persistence (#13)test: add lesson engine progression tests (#24)
- do not mix unrelated issues into one commit
- do not leave the branch in a broken state after a commit
- do not skip referenced docs when implementing an issue
- if an issue is too large for one coherent commit, it should be split before implementation
Each task below includes:
- ID — stable plan identifier
- Title — suggested GitHub issue title
- Why — why the task matters
- Depends on — prerequisite tasks
- References — source docs to read before implementation
- Acceptance criteria — definition of done
- Suggested commit scope — what should fit in the commit for that issue
When creating GitHub issues from this plan:
- use one issue per task unless explicitly grouped
- copy the
ReferencesandAcceptance criteriainto the issue body - keep issue order dependency-aware
- label issues that are safe for agents, for example
agent-ok
Why Create the baseline project structure for all later work.
Depends on
- none
References
ARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- TanStack Start app is scaffolded in the repo
- TypeScript is configured and working
- base app routes render successfully
- the app runs locally in development
- the app builds successfully for production
Suggested commit scope Initial app scaffold, baseline route structure, and minimal startup wiring only.
Why Establish consistent local development commands.
Depends on
- MIP-001
References
STACK-DECISIONS.md
Acceptance criteria
- pnpm is used consistently
- scripts exist for dev, build, test, lint/format, and preview
- Biome is configured and runnable
- repository README/setup instructions are updated if needed
Suggested commit scope Tooling and scripts only; no feature work.
Why Provide styling primitives for the shell and support surfaces.
Depends on
- MIP-001
References
STACK-DECISIONS.mdARCHITECTURE.md
Acceptance criteria
- Tailwind is configured and working
- shadcn/ui is installed/configured for selective use
- basic shell styling primitives render correctly
- no learner-facing core interaction UI is implemented in this issue
Suggested commit scope Styling system and support primitives only.
Why Ensure new work can be verified from the start.
Depends on
- MIP-001
References
STACK-DECISIONS.mdARCHITECTURE.md
Acceptance criteria
- Vitest is configured
- Testing Library is configured
- Playwright is configured
- at least one smoke test exists for each layer
- CI-friendly test commands exist
Suggested commit scope Testing infrastructure only.
Why Make deployment part of implementation from the start.
Depends on
- MIP-001
References
STACK-DECISIONS.md
Acceptance criteria
- project can build for Cloudflare Pages
- deployment configuration is present
- preview or deploy instructions are documented
- basic deployed shell can be verified
Suggested commit scope Deployment baseline only, not full offline/PWA behavior.
Why All lesson content depends on safe validated content loading.
Depends on
- MIP-001
References
CONTENT-SCHEMA.mdschemas/mathinik-content.schema.jsonARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- content pack JSON can be loaded from the app
- Ajv validates content packs at runtime
- invalid content fails clearly
- normalized content access layer exists
- example content pack loads successfully
Suggested commit scope Content repository + schema validation + example pack loading.
Why Profile/progress persistence is a core product requirement.
Depends on
- MIP-001
References
STATE-SCHEMA.mdschemas/mathinik-state.schema.jsonARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- persistence abstraction exists
- localStorage-backed implementation exists
- saved state validates at load boundaries
- invalid or missing state is handled safely
- example local state can be loaded
Suggested commit scope State store abstraction + local persistence + runtime validation.
Why The rest of the app should not depend on raw JSON layout details.
Depends on
- MIP-006
- MIP-007
References
ARCHITECTURE.mdCONTENT-SCHEMA.mdSTATE-SCHEMA.md
Acceptance criteria
- normalized lesson/activity/profile models exist
- raw schema objects are not passed everywhere in UI code
- adapter/mapper layer is covered by tests
Suggested commit scope Normalization/adaptation layer only.
Why Parent-managed local child profiles are core to MVP.
Depends on
- MIP-007
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- parent can create a child profile locally
- profile includes display name and starting grade
- created profile persists across refresh
- invalid input is handled cleanly
Suggested commit scope Create-profile UI + persistence wiring only.
Why Multiple local child profiles on one device are part of MVP.
Depends on
- MIP-009
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- user can switch between child profiles
- active profile selection persists locally
- wrong profile data is not leaked into another profile’s state
Suggested commit scope Profile switching and active-profile resolution only.
Why The app must support manual starting choice and optional placement.
Depends on
- MIP-009
- MIP-006
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- parent can manually choose a starting grade/path
- placement entry point exists as an optional path
- placement result can be stored in local state
- recommendation fields are persisted correctly
Suggested commit scope Onboarding path selection and placement persistence shell; not full placement intelligence.
Why The lesson engine is the backbone of the learning loop.
Depends on
- MIP-006
- MIP-007
- MIP-008
References
PRD.mdARCHITECTURE.md
Acceptance criteria
- lesson can start from content definitions
- lesson session tracks current activity index
- lesson can advance between activities
- lesson can produce a session summary shell
Suggested commit scope Lesson runner skeleton only; no rich interaction logic yet.
Why Short 5–10 minute sessions require strong resume behavior.
Depends on
- MIP-012
- MIP-007
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- in-progress lesson state is persisted
- reopening the app restores resumable lesson context
- resume can continue from last known activity
- restart remains possible
Suggested commit scope Resume-state persistence and restoration only.
Why The app needs a clean way to route activities to mechanic-specific components.
Depends on
- MIP-012
- MIP-008
References
CONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- activity renderer routes by
type - core activity component boundaries exist
- unsupported activity types fail safely
Suggested commit scope Activity rendering dispatch and component boundaries only.
Why This is one of the two core MVP mechanics.
Depends on
- MIP-014
References
PRD.mdCONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- numbers/operators/groups can be dragged into equation slots
- success can be evaluated from content-defined answers
- interaction works on mobile/touch screens
- component behavior is tested
Suggested commit scope Equation builder mechanic only.
Why This is the second core MVP mechanic.
Depends on
- MIP-014
References
PRD.mdCONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- objects/groups can be manipulated according to activity definitions
- result can be evaluated against content rules
- interaction works on mobile/touch screens
- component behavior is tested
Suggested commit scope Object manipulation mechanic only.
Why Touch forgiveness is a make-or-break product quality requirement.
Depends on
- MIP-015
- MIP-016
References
PRD.mdARCHITECTURE.md
Acceptance criteria
- accidental mis-drags can be corrected easily
- snap/drop behavior is clear and forgiving
- touch targets are usable on mobile
- wrong drops do not feel punitive
- interaction tests cover correction flows
Suggested commit scope Shared touch forgiveness behavior only.
Why Support mechanics are needed, but must not dominate the product.
Depends on
- MIP-014
References
PRD.mdCONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- multiple-choice and numeric-input activity components exist
- components are clearly treated as support formats
- no lesson flow assumes quiz formats are primary
Suggested commit scope Support activity components only.
Why The app must separate raw interaction results from educational interpretation.
Depends on
- MIP-015
- MIP-016
- MIP-018
References
ARCHITECTURE.mdCONTENT-SCHEMA.md
Acceptance criteria
- activity result evaluation is centralized
- success modes are interpreted correctly
- evaluation logic is testable in isolation
Suggested commit scope Evaluation rules only.
Why This scaffolded feedback loop is core to the learning experience.
Depends on
- MIP-019
- MIP-012
References
PRD.mdCONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- hints can be shown before answer reveal
- retry flow works correctly
- explanations can be shown after repeated struggle
- lesson engine integrates the flow correctly
Suggested commit scope Scaffolded feedback flow only.
Why The app should avoid shallow brute-force success.
Depends on
- MIP-019
- MIP-020
References
PRD.mdCONTENT-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- follow-up representation logic can be triggered
- second-step confirmation can be enforced when configured
- tests cover guessing-resistance behavior
Suggested commit scope Second-representation flow only.
Why Lesson completion drives progression and rewards.
Depends on
- MIP-019
- MIP-012
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- lesson completion is computed deterministically
- stars are calculated and stored correctly
- replay can preserve or improve best stars
Suggested commit scope Lesson completion + star logic only.
Why Mastery is essential to progression and parent summary.
Depends on
- MIP-022
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- mastery values update correctly per skill
- status transitions (
practicing,mastered, etc.) work correctly - state persists correctly across refresh
Suggested commit scope Mastery update logic only.
Why Progression requires completion plus minimum mastery.
Depends on
- MIP-022
- MIP-023
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.mdCONTENT-SCHEMA.md
Acceptance criteria
- unlock rules can be evaluated from lesson metadata
- newly unlocked lessons are persisted
- badges/rewards are granted and stored correctly
Suggested commit scope Unlock + reward logic only.
Why The child home screen is the hub of short-session usage.
Depends on
- MIP-013
- MIP-024
References
PRD.mdARCHITECTURE.md
Acceptance criteria
- active child home screen renders
- resume card appears when a lesson is resumable
- progression entry point is visible
- child-facing UI remains mobile-friendly
Suggested commit scope Home screen shell and core child-entry flow only.
Why Map progression is a major motivational layer.
Depends on
- MIP-024
- MIP-025
References
PRD.mdARCHITECTURE.md
Acceptance criteria
- unlocked vs locked lessons are visually distinct
- next recommended lesson is clear
- progress path reflects stored state
Suggested commit scope Map/progression presentation only.
Why The app needs satisfying closure after a lesson.
Depends on
- MIP-022
- MIP-024
References
PRD.mdARCHITECTURE.md
Acceptance criteria
- lesson completion screen shows stars and progress outcome
- next-step choice is clear
- reward/badge presentation works
Suggested commit scope Lesson-complete UI only.
Why Light personalization is part of the product feel.
Depends on
- MIP-009
- MIP-025
References
PRD.mdSTATE-SCHEMA.md
Acceptance criteria
- child name appears in appropriate places
- lightweight mascot/avatar selection is supported
- personalization persists locally
Suggested commit scope Personalization baseline only.
Why Parent-assisted usage requires a simple progress summary.
Depends on
- MIP-023
- MIP-024
References
PRD.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- parent summary shows completed lessons
- mastery summary is visible
- rewards/stars are visible
- view is derived from local state only
Suggested commit scope Parent summary UI and derivation only.
Why Offline-first is part of the product promise.
Depends on
- MIP-005
References
STACK-DECISIONS.mdARCHITECTURE.md
Acceptance criteria
- app is installable as a PWA
- service worker is active
- app shell caches correctly
- app starts correctly after prior load when offline
Suggested commit scope PWA installability and shell cache only.
Why Offline curriculum access depends on explicit content caching.
Depends on
- MIP-006
- MIP-030
References
CONTENT-SCHEMA.mdARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- content packs are cached for offline use
- app can detect newer content version when online
- update path is explicit and safe
Suggested commit scope Content caching and update detection only.
Why Updates must not quietly break local progress and resume state.
Depends on
- MIP-031
- MIP-007
References
CONTENT-SCHEMA.mdSTATE-SCHEMA.mdARCHITECTURE.md
Acceptance criteria
- content updates do not wipe learner state
- known lesson/profile references remain stable when possible
- update failure degrades safely
Suggested commit scope Safe refresh and state-preservation logic only.
Why The app needs real content beyond examples.
Depends on
- MIP-006
References
PRD.mdCONTENT-SCHEMA.md
Acceptance criteria
- at least one real skill/topic slice exists for Grade 1
- content validates successfully
- content exercises both core mechanics
Suggested commit scope Initial real content only.
Why Word problems are in MVP only in a constrained way.
Depends on
- MIP-033
- MIP-018
References
PRD.mdCONTENT-SCHEMA.md
Acceptance criteria
- word-problem content remains limited in scope
- reading burden is low
- visuals meaningfully support comprehension
- content validates successfully
Suggested commit scope Limited word-problem content only.
Why The app’s logic-heavy modules need confidence before release.
Depends on
- MIP-019
- MIP-022
- MIP-023
- MIP-024
References
ARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- evaluation, mastery, unlock, and persistence behaviors have direct tests
- core component tests exist for interaction components
- failures are meaningful and maintainable
Suggested commit scope Test coverage additions only.
Why Touch-heavy flows and resume/progression behavior require E2E verification.
Depends on
- MIP-025
- MIP-026
- MIP-027
- MIP-030
References
PRD.mdARCHITECTURE.mdSTACK-DECISIONS.md
Acceptance criteria
- E2E tests cover profile creation
- E2E tests cover starting a lesson
- E2E tests cover completing a lesson
- E2E tests cover resume behavior
- E2E tests cover offline-start or offline-return flows where practical
Suggested commit scope Critical-path E2E tests only.
Why A working local build is not enough.
Depends on
- MIP-005
- MIP-030
- MIP-031
- MIP-036
References
STACK-DECISIONS.mdARCHITECTURE.md
Acceptance criteria
- deployed build is reachable
- app shell works on deployed environment
- content loads in deployed environment
- basic learner flow works in deployed environment
- no obvious deployment-only failures remain
Suggested commit scope Deployment verification and environment-specific fixes only.
Why Before the final PR, the long-lived branch needs a holistic readiness check.
Depends on
- all prior MVP tasks intended for the current release batch
References
PRD.mdARCHITECTURE.mdSTACK-DECISIONS.md- this file
Acceptance criteria
- build passes
- relevant tests pass
- docs are up to date enough for implementation handoff
- branch health is acceptable for final PR
- known blockers are documented explicitly if any remain
Suggested commit scope Release-readiness fixes, small cleanup, and explicit documentation updates only.
Recommended initial order:
- MIP-001
- MIP-002
- MIP-003
- MIP-004
- MIP-005
- MIP-006
- MIP-007
- MIP-008
- MIP-009
- MIP-010
- MIP-011
- MIP-012
- MIP-013
- MIP-014
- MIP-015
- MIP-016
- MIP-017
- MIP-018
- MIP-019
- MIP-020
- MIP-021
- MIP-022
- MIP-023
- MIP-024
- MIP-025
- MIP-026
- MIP-027
- MIP-028
- MIP-029
- MIP-030
- MIP-031
- MIP-032
- MIP-033
- MIP-034
- MIP-035
- MIP-036
- MIP-037
- MIP-038
If a task is discovered to be too large for one issue/one commit, split it before implementation. Do not quietly inflate issue scope on the long-lived branch.
If an agent is executing issues from this plan:
- choose only issues whose dependencies are satisfied
- stay within the currently assigned batch
- read all listed
Referencesbefore implementing - keep commit scope aligned with
Suggested commit scope - run relevant validation/tests before finalizing the commit
- stop and ask when an issue is ambiguous, blocked, or larger than planned
This plan is successful if:
- GitHub issues can be created directly from it
- each issue is small enough to map to one coherent commit
- the issue order preserves branch health
- the final implementation branch can be reviewed as an ordered stack of issue commits
If opencode or another agent is asked to implement an issue from this plan:
- read the referenced markdown docs first
- implement only the issue’s intended scope
- keep the branch healthy after the commit
- assume one issue should normally map to one commit on the long-lived branch t on the long-lived branch