Favorites, assignment, and attachments — the details that change everything
There are big features and there are "small" additions that make a product truly usable.
Favorites
Favoriting a task is a toggle. A boolean. It should take 30 minutes. In practice: column, RLS, feed filter, star animation, Realtime synchronization. The star's bounce took me longer than the business logic.
Task Assignment
The model is a linking table collaborative.task_assignments. The real challenge is the FilterBar with three modes (All / Created by me / Assigned to me) combined with the hierarchical group filter.
Attachments — The Architectural Choice
Two possible approaches: JSONB (simple, fast) or relational tables (more work, more scalable). I chose relational tables (privat.task_attachments, privat.memo_attachments) for querying performance, clean cascading deletion, and individual RLS.
The Signed URL Trap
Supabase Storage generates signed URLs that expire after one hour. My solution: a StorageService.refreshAttachmentUrlsBatch() that regenerates URLs in batches via the storage_path. This is the kind of invisible detail — when it works, no one notices. When it breaks, everyone sees it.