Feature guide

Progress, review and personalisation

Browser learner state, attempts, streaks, daily missions, spaced review, saved work, cloud sync, and conflicts.

← Technical overview

What this domain owns

The learner snapshot and the rules that turn activity into progress. It does not decide lesson visual layout.

Feature flow diagram

Learner action
        │
        v
recordAttempt / markActivity / updateState
        │
        v
Browser snapshot ──save──> local browser storage
        │
        ├──> review + streak + mission rules
        └──> authenticated cloud sync ──> /api/progress ──> PostgreSQL

This diagram shows the normal direction of control and data. Follow it before changing a boundary or adding a dependency.

Class and relationship diagram

┌──────────────────┐ updates ┌────────────────────┐ syncs ┌───────────────┐
│ Activity action  │────────▶│ LearnerState       │──────▶│ /api/progress │
└──────────────────┘         ├────────────────────┤       └───────┬───────┘
                             │ + attempts          │               ▼
                             │ + reviews           │        ┌───────────────┐
                             │ + streak            │        │ PostgreSQL    │
                             └───┬────────────┬─────┘        └───────────────┘
                                 ▼            ▼
                         ┌────────────┐ ┌──────────────┐
                         │ Browser     │ │ ReviewSchedule│
                         │ storage     │ │ + schedule()  │
                         └────────────┘ └──────────────┘

Boxes show the important data types or services. Their fields and main methods are listed inside; arrows show the primary dependency or data relationship.

Sequence diagram

Learner
Activity
Progress store
Browser storage
Review scheduler
/api/progress
Database
submit answer or finish task
recordAttempt / markActivity
save snapshot
save confirmed
derive due items
due queue
sync when authenticated
validate and persist snapshot

Read this from top to bottom: each arrow is the next interaction in the normal successful path.

Start here in the code

Choose any filename to open it directly in VS Code.

How it works

  1. An activity calls a progress action.
  2. The browser snapshot validates and saves locally.
  3. Review/streak/mission rules derive the next state.
  4. Authenticated sync writes to the server and reconciles conflicts.

Read this code

lib/store.tsOpen in VS Code — Update local learner state safely

export function updateState(fn: (s: State) => State) {
  const next = fn(getState());
  writeBrowserStorage(KEY, JSON.stringify(next));
  current = next;
  emit();
}

export function markActivity(id: string) {
  updateState((state) => markStudyActivity(state, id));
}

What each part is doing

  1. Callers provide a pure state transformation instead of mutating the current snapshot.
  2. The new snapshot is persisted before subscribers re-render.
  3. markActivity delegates actual completion rules to the domain function.

This is a deliberately short excerpt of the real pattern, with unrelated details omitted. Read the named file for the complete implementation.

Related API and server boundaries

  • GET /api/progress loads the signed-in snapshot.
  • PUT /api/progress validates and saves a snapshot; 409 means conflict.

Tests to read and run

Implementation notes

This is the home for detailed explanations, decision records, request examples, and diagrams for this feature. Add new feature-specific documentation here instead of expanding the platform overview.