Advanced Recurring Tasks: Flexible Daily, Weekly, Monthly & Yearly Series

Hi :waving_hand:

I’ve been working on an expanded recurring-task implementation for Vikunja and now have a working version available for testing.

The goal is to make recurring tasks flexible enough for real-world schedules while keeping the setup understandable in the task UI.

What it adds

The implementation supports Daily, Weekly, Monthly and Yearly recurrence.

Daily

  • Every X days
  • Examples: every day, every 2 days, every 30 days

Weekly

  • Every X weeks
  • Select any combination of weekdays
  • Example: every 2 weeks on Monday and Thursday
  • Weekdays preset for Monday–Friday

Monthly

  • Every X months
  • Specific day of month, such as the 15th
  • Quarterly preset = every 3 months
  • Ordinal weekdays:
    • First
    • Second
    • Third
    • Fourth
    • Fifth
    • Last

Examples:

  • Every 3 months on the 15th
  • The first Monday of every month
  • The last Friday of every month
  • The fifth Friday of every month

For dates that don’t exist in every month, such as the 29th, 30th or 31st, the user can choose:

  • Use the last valid day of the month
  • Skip that occurrence

For a missing fifth weekday:

  • Skip that month
  • Use the last occurrence of that weekday
  • Use the first occurrence of that weekday in the following month

Yearly

  • Every X years
  • Fixed dates such as September 7
  • Relative schedules such as:
    • First Monday of January
    • Fifth Friday of May
    • Last Friday of December
  • The same missing-date policies used for monthly schedules are supported.

Schedule vs. completion

Two recurrence modes are supported:

Repeat on Schedule

The calendar schedule remains fixed even when a task is completed late.

For example, a task scheduled every Monday will continue following Mondays even if one occurrence is completed on Wednesday.

Repeat After Completion

The next occurrence is calculated from the actual completion time.

Example:

Every 90 days after completion

The implementation uses the task’s actual completion timestamp rather than the background scheduler execution time.

Start and end conditions

Every recurrence has a Start Date, which acts as the recurrence calendar anchor.

The task itself does not need to have a Due Date.

End conditions include:

  • Never
  • On a specified date
  • After X occurrences

Create tasks before the due date

When the task has a Due Date, the recurrence can create future tasks in advance.

For example:

Create 7 days before due date

The default is to create the task on its due date.

If the task does not use Due Dates, this option is simply hidden.

Weekend handling

Schedules can choose:

  • Keep the scheduled date
  • Previous business day
  • Next business day

The original recurrence date is kept separately from the adjusted task Due Date so the calendar schedule does not drift.

Missed occurrences

Two behaviors are available:

  • Next valid future occurrence — default
  • Generate every missed occurrence

The default avoids suddenly creating a large number of historical overdue tasks after a server has been offline or a recurrence has not been processed for some time.

Managing a recurring series

Recurring tasks can be:

  • Paused
  • Resumed
  • Removed from recurrence without deleting already-created tasks

For task changes and deletion, the user can choose:

  • This occurrence only
  • This and future occurrences
  • Entire series

This and future occurrences internally splits the recurrence series at the selected occurrence so the historical schedule remains intact.

Architecture

Rather than continuing to extend the existing single-task repeat behavior, this implementation introduces an explicit recurrence-series model.

A recurrence series stores the schedule definition, while occurrence records associate generated Vikunja tasks with:

  • the series
  • sequence number
  • scheduled recurrence date
  • actual Due Date
  • exception state

A planner calculates the next occurrence and a background materializer creates the corresponding Vikunja task when it becomes eligible.

Generated occurrences remain normal Vikunja tasks.

The materializer also preserves things such as:

  • assignees
  • labels
  • priority
  • color
  • relative start/end dates
  • reminder offsets

while resetting occurrence-specific state such as checklist completion.

Materialization is transactional and designed to be idempotent so the same series/sequence cannot accidentally create duplicate occurrences.

Human-readable summaries

The UI also generates summaries such as:

  • Every weekday
  • Every 2 weeks on Monday and Thursday
  • Every 3 months on the 15th
  • The first Monday of every month
  • The fifth Friday of every month, skipping months without one
  • Every 90 days after completion
  • Every year on September 7

Additional details such as the end condition and create timing are included when configured.

For example:

Every month, created 3 days before the due date, ending on September 27, 2026.

Current testing

I’ve completed testing of the main recurrence combinations, including:

  • Daily / Weekly / Monthly / Yearly
  • Selected weekdays
  • Monthly 29th/30th/31st handling
  • Fifth-weekday policies
  • Leap-day yearly schedules
  • Schedule-based recurrence
  • Repeat after completion
  • End dates and occurrence limits
  • Create-before timing
  • Weekend adjustment
  • Missed occurrences
  • Pause/resume
  • Scoped edits/deletes
  • Remove recurrence
  • Materialization
  • Tasks without Due Dates
  • Save/reload and recurrence summaries

There are also backend tests covering the planner, materializer, transaction rollback, duplicate protection and scoped series management.

Code / testing branch

The current implementation is available here:

GitHub:

It is currently based on the Vikunja 2.6 codebase.

Anyone interested is welcome to review the implementation or test it and let me know what could be improved before I prepare it for an upstream PR.

I’d especially appreciate feedback on:

  • whether the recurrence options cover the schedules people actually use
  • whether the UI is understandable without being overwhelming
  • whether any important recurrence edge cases are missing
  • whether any part of the implementation should be structured differently before upstream submission

Thanks!

Everytime I cleanup my todo list in Vikunja, I’m annoyed by the very rudimentary recurrence options.

Every second time I check the web whether somebody bothered to improve it and I’m very happy, I found your post.

I don’t have time to test it, but I wanted to thank you for your work and hope it gets integrated.

Good stuff!

This seems very similar to https://github.com/go-vikunja/vikunja/pull/3071 - except that yours has more UI features?

Thanks, really appreciate that. The recurrence limitations were exactly what motivated this work. I’ve tested the main scheduling combinations pretty extensively on staging, and I’m hoping to get it into a shape that can be contributed upstream.

Yes, there is definitely overlap.

I still need to do a proper line-by-line comparison with #3071, but this implementation grew beyond just exposing more recurrence rules in the UI.

In addition to the Daily / Weekly / Monthly / Yearly editor, it currently includes:

  • selected weekdays for weekly recurrence
  • day-of-month and ordinal weekday rules, including 5th / Last
  • explicit handling for missing 29th/30th/31st and missing fifth weekdays
  • fixed schedule vs. repeat-after-completion
  • recurrence Start Date independent of an optional task Due Date
  • end on date / after X occurrences
  • create X days before due date
  • weekend handling
  • missed-occurrence policies
  • pause/resume
  • materialized occurrence tracking
  • scoped edit/delete: this occurrence, this and future, or entire series
  • remove recurrence while preserving already-created tasks
  • plain-English recurrence summaries

The backend also uses a recurrence-series / occurrence model rather than only modifying the original task in place, so generated occurrences remain separate normal Vikunja tasks.

I’ll compare the implementation against #3071 more closely before preparing anything upstream. If parts of #3071 already provide the preferred recurrence foundation, I’m happy to adapt this work around that rather than duplicate it.

#3071 uses RRULE to express all kinds of schedules, that’s a IETF standard which is mostly used in calendars. IMHO the only thing that makes sense to use because they have all the edge cases already battle-tested.