Why I built it
I study Japanese with an online group, and most of us use WaniKani for kanji. WaniKani shows you your own progress but nobody else’s. We wanted to see who had studied that day and who was on a streak, and to get a reminder before the day ran out.
What it does
- Posts a recap every night at midnight in the group’s time zone, and a leaderboard once a week.
- Shows anyone their stats, a 30-day activity heatmap, or their streak when they ask for it.
- Reminds you before your day ends if you haven’t done your reviews. An LLM writes the reminder in Japanese at your level, using only kanji you’ve already learned, so reading it is a little extra practice. If the API is slow or down, the bot sends a plain message instead.
The tricky parts
Streaks took the most work. WaniKani has its own rules, including “offerings” that cover a missed day and take a week to recharge. The bot follows the same rules, so its streaks agree with the site even for days when the bot was offline.
It only asks the WaniKani API for what’s changed since the last sync, and waits when the API asks it to. It stores API keys encrypted and uses each person’s own time zone. Database changes go through numbered migration scripts.
Working as a pair
This is the one project I built with someone else. Our changes went through pull requests (26 merged so far). We also wrote a few admin scripts so either of us could look up a member’s data, recalculate streaks, or preview the next recap before it went out.
What I learned
If the bot’s numbers don’t match what people see on WaniKani, they stop trusting it, so most of the streak code is there to handle edge cases like time zones, missed days, and downtime.