One screen, seven days, nothing else.
A free, fully open-source weekly to-do app for Android, built in Flutter.
No accounts · No cloud sync · No tracking · No ads · No paywall
Jump to: Features · Screenshots · Tech Stack · Getting Started · Contributing · Security · License
Loopweek is an original, clean-room implementation of the "one screen, seven days" concept — no calendar grid, no month view, no navigation between screens for the core loop. 100% local, on-device storage.
| Feature | Description |
|---|---|
| 📅 | Single-screen week view — All seven days live on one screen as an accordion; today is expanded by default, tapping a collapsed day expands it and collapses the open one. |
| ⏳ | Date-specific tasks, no auto-rollover — Incomplete tasks stay on their original date forever unless you manually move them. |
| 🔁 | Independent recurring occurrences — Completing or deleting one occurrence never affects past or future occurrences; stop future recurrence without touching history. |
| 🎨 | One accent color drives everything — Pick Orange / Pink / Blue / Green in Settings; the same color fills checkboxes, segmented controls, toggles, primary actions, and the home-screen widget. |
| 🌗 | Light / dark theme — Follows the system setting with a manual override. |
| 🔔 | Optional reminders — Notification permission is requested only when you actually switch a reminder on — never at startup. |
| 📱 | Home-screen widget — Today's tasks on your launcher, with checkboxes that toggle completion in the background without opening the app. |
| 🧭 | Drag-and-drop reordering — Reorder tasks within a day by dragging. |
| 🔒 | No ads · No analytics · No accounts — Your data never leaves the device. |
Captures are stored in
docs/images/. Add more by dropping files there and referencing them above.
| Layer | Technology |
|---|---|
| 💻 Language | Dart (null-safe) |
| 📱 Framework | Flutter (stable channel) |
| 🎨 UI | Material 3 (Material widgets + custom theme tokens) |
| 🏛️ Architecture | Clean separation: data / domain / presentation |
| 🗃️ Database | Drift (SQLite) for tasks & recurrence |
| 🔄 State | Riverpod (flutter_riverpod) |
| 🔔 Notifications | flutter_local_notifications + timezone |
| 📱 Widget | home_widget for the Android App Widget |
| ⚙️ Preferences | shared_preferences |
| 🧪 Testing | Flutter test (flutter test) — recurrence suite is the canonical coverage |
📦 Full dependency list
flutterSDKcupertino_iconsdrift,sqlite3_flutter_libs,path_provider,pathflutter_riverpoduuidflutter_local_notifications,timezonehome_widgetshared_preferencesintl,collection,url_launcher- dev:
flutter_test,flutter_lints,drift_dev,build_runner
- Flutter stable channel (3.11.x / SDK
^3.11.4) - JDK 17 or newer (for Android Gradle builds)
- Android SDK 36 (
compileSdk = 36,targetSdk = 36),minSdk= Flutter default - An Android device or emulator (API 21+)
# 1. Clone the repository
git clone https://github.com/ZaryabKhan/loopweek.git
cd loopweek
# 2. Install dependencies
flutter pub get
# 3. Generate the Drift database code (rerun after any change to tasks_table.dart)
dart run build_runner build --delete-conflicting-outputs
# 4. Run on a device/emulator
flutter run
# 5. Build a debug APK
flutter build apk --debugThe debug APK will be at build/app/outputs/flutter-apk/app-debug.apk.
🎁 JDK note for CLI builds
Gradle uses the JDK on your JAVA_HOME/PATH. To pin a specific JDK for local
CLI builds, set org.gradle.java.home=... in ~/.gradle/gradle.properties
(user-level, not committed).
lib/
├── core/
│ └── theme/ AppTheme + AccentColors (light/dark/system, accent)
├── data/
│ ├── database/ Drift [Tasks] table, [LoopweekDatabase], [TaskMapper]
│ ├── repositories/ TaskRepository — persistence + recurrence materialization
│ └── services/ SettingsService, NotificationService, HomeWidgetService
├── domain/
│ ├── models/ Task, ColorTag, Recurrence
│ └── services/ RecurrenceGenerator (pure date logic — unit tested)
├── presentation/
│ ├── providers.dart Riverpod providers (DB, repository, settings, …)
│ ├── week/ WeekView, DayHeader, TaskTile, week_providers
│ ├── task_sheet/ Add/Edit Task modal sheet
│ └── settings/ Settings screen (color, theme, alerts, widget preview)
└── main.dart App entrypoint + home-widget background callback
lib/domain/services/recurrence_generator.dart is a pure, dependency-free
class that computes forward occurrence dates for a given rule within an
inclusive window. The storage layer (TaskRepository.materializeOccurrences)
uses it to generate independent rows linked back to the source rule by
recurrenceParentId. Unit tests in test/recurrence_generator_test.dart
cover daily/weekly step math, window boundaries, anchor inclusion, anchor
exclusion, and multi-month spans.
flutter analyze # lint
flutter test # unit + widget testsThe recurrence suite is the canonical coverage for the most bug-prone logic;
the smoke test in test/widget_test.dart verifies the app boots and renders
the week heading.
The widget ships as native Android XML (RemoteViews):
android/.../LoopweekWidgetProvider.kt— thees.antonborri.home_widget.HomeWidgetProvidersubclass that renders the list and routes checkbox taps to a background isolate.android/.../res/layout/loopweek_widget.xml— the row layout.android/.../res/xml/loopweek_widget_info.xml—AppWidgetProviderInfo(medium size, resizable).
Flutter pushes a compact snapshot of today's tasks through
HomeWidget.saveWidgetData; the native side parses a newline-separated
marshalled string of rows (id|done|title|HH:MM|). Tapping a row fires a
broadcast that the Dart isolate callback registered in lib/main.dart turns
into a one-line UPDATE tasks SET is_completed = (1 - is_completed) WHERE id = ?
— toggling completion without launching the app.
Loopweek stores everything on the device. There is no network code in the release build, no analytics, no telemetry, and no crash reporting that sends data anywhere. Notification permission is requested only when you opt into a reminder; nothing else asks for any permission.
Contributions are welcome! Please read CONTRIBUTING.md to learn how to set up the project and submit pull requests.
Loopweek is intentionally small. The spec is "one screen, seven days, nothing else." Out-of-scope ideas (cloud sync, accounts, calendar view, subtasks, tags beyond the four colors, ads, analytics, IAP) won't be merged even if the code is good. When unsure, open an issue first and ask.
Looking for a good place to start? Check for issues labeled
good first issue
and help wanted.
# Fork → Branch → Commit → PR
git checkout -b feat/my-awesome-feature📜 Code of conduct
By participating you agree to abide by the Code of Conduct. Be kind and respectful.
Found a vulnerability? Please do not open a public issue. See SECURITY.md for how to report it privately.
See the Releases page for version history. For how to publish a release, see RELEASE.md and RELEASE-CHEATSHEET.md.
Loopweek is licensed under the MIT License — see LICENSE. Loopweek is an original product; it is not derived from any other app's name, logo, or code.
Built with ❤️ by Zaryab Khan & contributors.
If Loopweek is useful to you, consider ⭐ starring the repo to support development.
Report a bug · Request a feature · Discussions





