Hi ![]()
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
Weekdayspreset for Monday–Friday
Monthly
- Every X months
- Specific day of month, such as the 15th
Quarterlypreset = 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 weekdayEvery 2 weeks on Monday and ThursdayEvery 3 months on the 15thThe first Monday of every monthThe fifth Friday of every month, skipping months without oneEvery 90 days after completionEvery 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!




