Offline-first social tasks

Nudge

Nudge was built as a simple social task app on the surface, powered by an offline-first collaborative architecture underneath.

Nudge is a lightweight social task experience for repeated group planning, built with a simple gesture surface and a local-first sync architecture underneath.

React NativePowerSyncSupabasePostgreSQLSupabase AuthRLS
Role
Full Stack Developer
Experience context
Ownpath · Nov 2025–Present
Client / company
Vendaka Pvt. Ltd.
Article length
9 sections
Three iPhone screens showing the Nudge social task app interface
Nudge task deck across owner and collaborator flows
Local-firsttask creation before network confirmation
2 rolesowner and nudger collaboration model
4 gesturescomplete, postpone, nudge, archive
01

Overview

Nudge is a social task app for people who plan together repeatedly: friends arranging a trip, housemates sharing routines, or small groups coordinating an event. A person creates a task, adds the people involved, and the group can keep that work moving without turning the task into a chat thread.

The product was deliberately small. Its interaction model used four gestures—complete, postpone, nudge, and archive—while the system underneath handled local state, shared ownership, permissions, and synchronization.

02

The problem

In many groups, planning is shared in theory but managed by one person in practice. That person remembers the plan, follows up, and keeps track of what remains unfinished. Nudge was designed to distribute that responsibility while keeping the experience as immediate as a personal task app.

The difficult part was not rendering a card or adding swipe animation. A task had to work with an unreliable network, multiple participants, distinct roles, remote updates, and lifecycle states without allowing an invalid action or leaving people with conflicting views of the same work.

03

Technical approach

Local-first task creation

Offline support was part of the product promise from the beginning. PowerSync provided a local data layer that could respond immediately and synchronize with Supabase when a connection became available.

When someone saved a task, the app generated its ID and wrote it to the local store first. The task appeared without waiting for a network request; the sync layer replicated the change to Supabase when the device was online. This made task creation feel responsive while preserving a clear path to the shared source of truth.

04

Relationship and sync boundaries

Nudge was relationship-heavy: a task connected its creator, participants, participant roles, and people who could receive activity or notifications. Supabase could model those relationships, but the legacy PowerSync Sync Rules setup could not express the JOIN and outer-join patterns that some local views needed.

I treated replication and relationship assembly as separate concerns. Task, participant, and user records synchronized independently; the task service resolved their explicit IDs and applied the product's relationship logic. That boundary made it possible to investigate missing local data without guessing whether the issue was in the database, schema, sync configuration, or service layer.

05

RLS, participants, and attachments

Access control

Row Level Security protected the shared data, but it also made authentication and relationship visibility part of the feature. A valid query was not enough: the current user needed the right participant relationship, and task images needed the correct Supabase Storage access path.

Participant reads and image access were tested as distinct authenticated flows. Rather than bypassing RLS, I aligned the ownership model with Supabase Auth, made participant reads policy-aware, and treated upload and readback as separate recoverable operations.

06

Collaboration model

The core data model stayed deliberately small: a user represented a person in the group, a task represented the work and its lifecycle, and a participant connected the two with a role. The two roles—owner and nudger—gave the app shared accountability without giving every collaborator the same permissions.

Creating a task exposed an important timing dependency. The task could appear locally before its remote record existed, while participant records depended on that remote record. The app therefore showed the new task immediately, waited for Supabase to make it available, created the owner and contributor relationships, and refreshed the local view in the background. Users experienced one flow even though the write sequence had to be staged.

07

Role-aware gestures

The swipe deck was the point where interaction, task state, and permissions met. Before an action, the app loaded relevant participant data and resolved the current user's role; the task creator also provided an immediate owner signal while role data was still loading.

The interface guided people toward the actions available to them, and the service layer checked the same permissions before completing, archiving, or nudging. That paired UI and data validation kept collaboration lightweight without making it ambiguous.

08

Making the system observable

A missing task could originate in the mobile interface, local PowerSync database, Supabase database, authentication policy, participant relationship, sync rules, or network state. Because the visible symptom was often distant from the cause, the project needed diagnostics as much as product code.

I added schema comparison and Supabase inspection tools, clean-start and reset flows, local insertion helpers, and sync simulations. These tools made local and remote state easier to compare, reproduce, and recover when they drifted apart.

The result reached test and internal demo builds with stable local-to-Supabase synchronization, participant-aware visibility, role-aware actions, notifications, images, and recovery behavior. The visible product remained a small task app; the engineering outcome was a dependable collaborative system underneath it.

09

What guided the work

The technical decisions all worked backward from the product feeling: capture a task quickly, make shared responsibility clear, and ensure every gesture has a predictable result. Local-first creation supported immediacy; the participant model supported accountability; explicit states, role-aware actions, and recovery tooling supported clarity.

The architecture was successful when users did not have to think about it.

We built Nudge as a simple social task app on the surface, powered by an offline-first collaborative architecture underneath.

My contribution

What I owned across this build.

  • Designed the local-first task creation and PowerSync-to-Supabase synchronization flow.
  • Built the owner/nudger participant model that connected gestures to real permissions.
  • Aligned Supabase Auth, RLS, Storage, local schema, and sync rules across task and attachment flows.
  • Created schema inspection, clean-start, reset, local insertion, and sync simulation tooling for debugging.