v0.5.x porting plan — pulling patterns from Dominic Stars

Status: planning artefact (operator asked Mavis to read Dominic Stars source)

Date: 2026-06-17

Source: /workspace/dominics-tasks/ (cloned from avidtech6/DominicsTasks)

What I read

I read the actual source of the original Dominic Stars app (committed at b327bba1 in my read-only clone). Not just a comparison — the real modules. Here's what I found and how to port it.

Architectural pattern: Behaviour class vs Zustand store

Dominic Stars uses a class-based behaviour with subscribe/notify pub-sub:


// TaskBehaviour.ts
export class TaskBehaviour {
  private tasks: Task[] = []
  private subscribers: Set<...> = new Set()
  subscribe(callback) { this.subscribers.add(callback); return () => this.subscribers.delete(callback) }
  private notify(event) { this.subscribers.forEach(cb => cb(event)) }
  async getTasks() { return [...this.tasks] }
  async createTask(task) { ... }
}

Home-studio uses Zustand stores (per the FW v8 §18 mirror pattern, "freshcards modules can use Zustand; home-studio modules can use either").

Verdict: both work. The class pattern is more framework-light (no Zustand dependency in the behaviour layer). The Zustand pattern is more idiomatic for React. Don't switch home-studio's pattern — it's already proven. Just be aware that when reading the original, the class-singleton-with-subscribers is the equivalent of home-studio's useApp() + Zustand.

Pattern 1: PIN pad for parent mode (genuinely good)

File: src/components/PinPad.tsx (524 lines)

A full ATM-style numeric pad for entering a parent PIN. Not just an input field. Why this is better than a text input:

Port priority: HIGH — this is the real "parent approval" gate (finding N from the depth audit).

How to port to home-studio:

Why this is better than "skip": if home-studio is the real family app, kids WILL mark their own tasks done to get EP. Without a parent gate, the reward system is meaningless. Real EP-as-money needs a real gate.

Pattern 2: ConfettiCelebration (genuinely delightful)

File: src/components/ConfettiCelebration.tsx (92 lines) + ConfettiCelebrationBehaviour.ts (130 lines)

A real celebration animation:

Port priority: MEDIUM — operator's "growth not glory" concern means we shouldn't go overboard. But a single moment of celebration when a kid earns a level-up or major achievement is welcome.

How to port to home-studio:

Ethos alignment check: confetti is positive reinforcement, not shame. It's about celebrating, not punishing. Aligned.

Pattern 3: Profile-first device flow (better than topnav)

File: src/components/ProfileSelectionScreen.tsx (866 lines)

When the app opens, instead of going straight to Today/whatever, the user picks a profile first. Each family member has their own avatar + colour. The "parent mode" is locked behind a PIN.

Why this is better than home-studio's current topnav-only member picker:

Port priority: MEDIUM — for a single-child family, the current topnav works. For multi-child, the profile-first flow is much better.

How to port to home-studio:

Note: home-studio's data model already has multi-member support (SEED_MEMBERS has 4). The UI just doesn't expose it well.

Pattern 4: Comments on tasks (in peek panel)

File: src/components/CommentsModal.tsx (163 lines) + CommentsModalBehaviour.ts (60 lines)

A modal for adding comments to a specific task. Each comment has author, timestamp, body. Appears in the task detail view.

Port priority: MEDIUM — was the addendum finding "no comments / activity log in peek". This is the cleanest implementation of that finding.

How to port to home-studio:

Pattern 5: AchievementBadge with unlock animation

File: src/components/AchievementBadge.tsx (67 lines) + AchievementBadgeBehaviour.ts (60 lines)

Achievement cards with:

Port priority: LOW — home-studio's Awards view already has the badge grid. Missing only: unlock animation when first earned, and click-for-detail.

How to port:

Pattern 6: Evidence submission (Levels 0-3)

File: src/behaviours/TaskBehaviour.ts has approveTaskCompletion(approvalId) and rejectTaskCompletion(approvalId, reason) methods, but they're stubs (just console.log).

Reality check: this is a STUB in the original too. The architecture has approval IDs and workflow methods, but no actual implementation. Evidence upload (via Firebase Storage) is mentioned in the README but not implemented in the methods I read.

Port priority: SKIP for v0.5.x — both apps are at the same level of "approval exists in the data model, not in the UI". Port the WORKFLOW first (PIN gate + approve button), then add evidence.

Pattern 7: Behaviour-Component split (validated)

Observation: the original uses Component.tsx + ComponentBehaviour.ts (separate file). Home-studio uses the same idea but with hooks (Component.tsx + useComponent.ts in same dir).

Why the original is more verbose: separate files force you to scan TWO files to understand a component. Slower debugging.

Why home-studio is cleaner: hook in same dir, no file-hopping. The §30 modular file-size rule still applies (one concern per file).

Verdict: home-studio's pattern is better. Don't switch.

What I learned that affects v0.5.x priorities

v0.5.x proposed work order

| Version | Feature | Effort | Files |

|---|---|---|---|

| v0.5.0 | Parent PIN gate + approve EP | 4-6 hrs | PinPad.tsx, ParentPinModal.tsx, useParentMode.ts, db.ts parentMode field, schema migration |

| v0.5.1 | ConfettiCelebration (subtle) | 2-3 hrs | celebration/*.tsx, particles.ts, styles.ts, useCelebration.ts |

| v0.5.2 | Profile-first device flow | 3-4 hrs | ProfileSelectionScreen.tsx, ProfileTile.tsx, useProfiles.ts |

| v0.5.3 | Comments in peek panel | 2-3 hrs | comments.ts (db helper), PeekPanel.tsx extension |

| v0.5.4 | Evidence submission (photo proof) | 4-5 hrs | Supabase Storage setup, photo upload component |

| v0.5.5 | AchievementBadge refactor + unlock animation | 2 hrs | Badge.tsx, useAchievements.ts |

Total: ~17-23 hours. Spread over multiple weeks.

Operator decision needed

I have NOT started implementing any of this. This is the plan, not the work.

Reference: source files I read