Skip to content

Notifications

Softly uses a combination of local notifications (scheduled on-device) and push notifications (sent from the backend via Expo Push API).

Local Notifications

Task reminders are scheduled locally using expo-notifications. When a task has reminder_days set (e.g. [1, 7]), the mobile app schedules local notifications for 1 day and 7 days before the due date.

Local notifications are re-scheduled whenever:

  • A task is created or updated
  • The app returns to foreground
  • A task is completed (cancels its pending notifications)

The scheduling logic lives in services/notifications.ts.

TIP

Local notifications work offline and don't require the backend. They're the primary reminder mechanism for most users.

Push Notifications

Push notifications are used for server-initiated messages that can't be scheduled locally, like the weekly digest.

Device Token Registration

On app launch (or when push permissions are granted), the app registers its Expo push token with the backend:

POST /api/v1/device_tokens

Tokens are stored per-user and per-platform. When a user logs out, the token is deactivated:

DELETE /api/v1/device_tokens

Expo Push API

The backend sends push notifications via ExpoPushService, which calls the Expo Push API. Push delivery is handled asynchronously via SendPushNotificationJob (Solid Queue).

Weekly Digest

Every Sunday, WeeklyDigestJob runs via Solid Queue's cron scheduler (config/recurring.yml). For each user with active device tokens, it:

  1. Counts tasks due in the coming week
  2. Counts overdue tasks
  3. Sends a push notification summarizing the week ahead

Example: "You have 5 tasks this week and 2 overdue. Let's get on top of it!"

Reminder Scheduling

Tasks support flexible reminder scheduling via the reminder_days array field:

ValueMeaning
[0]Remind on the due date
[1]Remind 1 day before
[1, 7]Remind 1 day and 7 days before
[0, 1, 7]Remind on due date, 1 day before, and 7 days before

If a task has a due_time set, notifications fire at that time. Otherwise, they default to 9:00 AM local time.

Internal documentation — not for public distribution