Skip to content

TrayLearn: Add mastery-first UK phonics app with local SRS, UI, and tests#3

Open
xoxoskeleton wants to merge 1 commit into
mainfrom
codex/build-traylearn-phonics-app-with-mastery-focus
Open

TrayLearn: Add mastery-first UK phonics app with local SRS, UI, and tests#3
xoxoskeleton wants to merge 1 commit into
mainfrom
codex/build-traylearn-phonics-app-with-mastery-focus

Conversation

@xoxoskeleton
Copy link
Copy Markdown
Owner

Motivation

  • Provide a local-first, mastery-first phonics app scaffolded into the repo so parents can run short, low-pressure UK-phonics sessions offline.
  • Enforce pedagogy constraints and stage-gating while offering a playful child-friendly session runner and seed content for fast trialing.
  • Ship a minimal V1 that is installable (pnpm i / pnpm dev) and covered by unit tests for core scheduling rules.

Description

  • Replace the previous sample with a TrayLearn app using Next.js + TypeScript + Tailwind and add local IndexedDB persistence via Dexie, seeded demo profile and starterCards in lib/content.ts and DB helpers in lib/db.ts.
  • Implement SRS and scheduling: tray movement and intervals in lib/srs.ts, session selection algorithm in lib/session.ts, and stage-gating/whole-word safeguards in lib/gating.ts.
  • Add the main parent/child UI and session runner in pages/index.tsx, a safe local API in pages/api/generate.ts, and UI styling/config in tailwind.config.ts, postcss.config.js, and styles/globals.css.
  • Add types (lib/types.ts), a sync stub/feature-flag (lib/sync.ts), export/print & custom card hooks, and update README.md with run instructions and where to find scheduling logic; update package.json and lockfile to include dependencies and test scripts.
  • Add unit tests and tooling: tests/srs.test.ts and tests/session.test.ts plus vitest.config.ts, and wire pnpm test script.

Testing

  • Ran pnpm test (Vitest) and all tests passed: 5 tests in 2 files (tray movement and session selection) — ✅ passed.
  • Ran pnpm lint (next lint) with no ESLint warnings or errors — ✅ passed.
  • Built the production site with pnpm build (Next.js) to validate type/compile output and static generation; build completed successfully — ✅ passed.

Codex Task

@vercel
Copy link
Copy Markdown

vercel Bot commented Feb 15, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
xy-0ors Ready Ready Preview, Comment Feb 15, 2026 8:40pm

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 886cef6acd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread lib/session.ts
const selectedIds = new Set(start.map((c) => c.id))

const reviewPool = due
.filter((c) => !selectedIds.has(c.id) && (c.tray === 'Frequent' || c.tray === 'Growing'))
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Exclude locked-stage cards from due review selection

This reviewPool filter pulls every due Frequent/Growing card regardless of stage, so isNew cards above unlockedStage can enter sessions through the due path. In this commit, starter cards for higher stages are seeded as due, which means advanced cards will surface before readiness gating is met once earlier cards are rescheduled. That bypasses the stage-unlock rule that newCards already enforces.

Useful? React with 👍 / 👎.

Comment thread pages/index.tsx
maxDailyDue: activeChild.settings.maxDailyDue,
unlockedStage: activeChild.unlockedStage
})
}, [cards, activeChild])
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Snapshot session cards instead of recomputing on every DB update

sessionCards is memoized from live-query cards and re-derived whenever cards changes, but each rating writes to Dexie and changes due/tray state mid-session. That causes the session list to reorder/shrink while cardIndex continues incrementing, which can skip cards or produce duplicates during a single run. The session should be fixed at start rather than rebuilt from mutable live data after each answer.

Useful? React with 👍 / 👎.

Comment thread pages/index.tsx
return current.percentile + ratio * (next.percentile - current.percentile);
const addCustomCard = async () => {
if (!activeChild || !customPrompt.trim()) return
if (!canUseWholeWordCard(customStage as 0 | 1 | 2 | 3 | 4, customTricky)) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Check card type before enforcing whole-word stage guard

This guard runs for every custom card regardless of customType, so non-tricky Stage 1/2 cards like SoundCard and DigraphCard are rejected even though only whole-word cards should be blocked. As written, users must mark unrelated cards as tricky to save them, which breaks normal custom-card creation for early stages.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant