Skip to main content
← Blog

Reminders Were Easier Than Expected

VauDium ·

Adding pre-start reminders to tasks. Turns out a single computed field was all it took.

Reminders Were Easier Than Expected

In Fecit, you can set a start time for tasks. Meeting at 2pm, gym at 7pm. But setting a start time and then forgetting about it defeats the purpose. I needed reminders.

Reminders. The word alone conjures complexity. Schedulers, timezone handling, recurring notifications, local vs push. I’d been putting it off.

Turns out it was surprisingly simple.

The Key Idea: A Computed Field

My first instinct was to query for tasks at “current time + offset” in the batch job. 5 minutes before, 15 minutes before, 30 minutes before — a separate query condition for each offset.

Then I realized there’s a simpler way.

reminder_at = start_date - reminder_offset

When saving reminder_offset (how many minutes before), compute reminder_at (the actual notification time) and store it alongside. Then the batch query becomes:

task_record_collection.find({
    'reminder_at': {'$gte': now, '$lt': now_end},
    'state': TaskState.REGISTERED,
})

Doesn’t matter how many offset options exist. Adding new ones doesn’t change the query. Only one index needed: reminder_at.

What If start_date Changes?

reminder_at is derived from two values: start_date and reminder_offset. If either changes, reminder_at needs recalculation.

  • When reminder_offset changes: read start_date, recompute
  • When start_date changes: read reminder_offset, recompute
  • If either is null: reminder_at = null (no reminder)

Follow this rule and it’s always correct.

The UI

The reminder picker only shows when a start date exists. No start date, no reminder — it wouldn’t make sense.

Options are straightforward:

  • At start date
  • 5 min before start date
  • 15 min before start date
  • 30 min before start date
  • 1 hour before start date
  • 1 day before start date

Select one, it saves to the server, reminder_at is computed automatically. To clear, tap the X button next to the value — same pattern as the start date clear button.

Looking Back

I overthought it. The core insight was just “pre-compute the notification time so the query stays simple.” Everything else followed existing patterns.

Should have done it sooner.