Memory Rhythm
A local-first learning companion built around the SM-2 spaced-repetition algorithm, bringing knowledge back at the right time for long-term retention.
View source on GitHub ↗Project screenshots
Memory Rhythm

Why I made it
Saving knowledge is easy; meeting it again before it fades is the harder part. Memory Rhythm turns scattered notes into a sustainable review plan. After recording an item, the learner simply rates each review as Again, Hard, Good, or Easy, and the application dynamically schedules when that knowledge should return.
The project also reflects my concern for personal data ownership. It requires no account, cloud service, or network connection. Learning data stays in a local SQLite database, and users can move that database between locations or devices without being locked into a platform.
The core experience
I designed the product around a simple loop: capture, review, and reflect. It includes a daily review queue, rich-text knowledge capture, browsing and subject organization, a review calendar, and learning statistics. Four clear ratings make the original SM-2 scale easier to use, while a 365-day contribution graph, streaks, and review history make long-term progress visible.
Knowledge items support formatted text and code blocks, and can be filtered by subject. The complete database can be exported to or restored from JSON using either replace or merge strategies. Before a destructive replacement, the application automatically creates a snapshot of the current database.
What I contributed
I took the project from product structure through full-stack implementation. I translated SM-2 review states into a clear four-choice interaction, designed the Today, Browse, Subjects, Calendar, Statistics, and Settings experiences, and implemented the backend for knowledge items, review history, backup and restore, and database migration.
The project uses open-source components including Vue, Element Plus, ECharts, Quill, and DOMPurify for the interface, charts, rich-text editing, and content sanitisation. My contribution was not to recreate those foundations, but to shape them into a coherent personal learning tool that works offline, while also handling data safety, desktop packaging, and release builds.
How it works
The backend is built with FastAPI, SQLAlchemy, and SQLite, with the SM-2 scheduling logic isolated as a pure function. The frontend uses Vue 3, Element Plus, ECharts, and Quill without a build step. Every third-party asset is vendored locally, so the full experience continues to work offline.
Alongside the browser version, I wrapped the application in a native macOS window with PyWebView and made it packageable as a standalone app through py2app. The database location can also be switched at runtime, leaving users in control of where their information lives.
Problems and lessons
The hardest trade-off was between convenience and data reliability. Letting users switch database locations at runtime is flexible, but it also introduces risks from incorrect files, symbolic links, and damaged databases. A replace import is straightforward, but it must preserve a path back to the previous data. I addressed these cases with approved migration locations, SQLite file-signature checks, sanitised errors, strict backup validation, and automatic snapshots before replacement.
The project taught me that local software is not automatically safe, and that working features are not necessarily dependable features. A personal tool intended for long-term use also needs recovery paths, portable data, and carefully defined security boundaries. The result is more than a dashboard of learning features: it is an offline, portable, and recoverable memory workflow designed to support sustained personal learning.