-
-
Rurira_AppIcon
-
Home Screen-The entry point where you can enter all logs.
-
Calendar-See at a glance on the calendar which days you've logged.
-
From beauty and health to managing your care products, choose the log that best suits your needs.
-
Track exercise, supplements, and mental well-being.
-
Organize and revisit your beauty and wellness records.
-
Manage your items and routines in one place.
Inspiration
Modern apps have become remarkably good at sharing. With a user's consent, schedules, workouts, and health data can all be shared with someone else.
But not every woman wants to share her period, her salon appointments, or her self-care routine. Some things are recorded for yourself. Some things you want to look back on without anyone watching.
I built RURIRA because I felt there was still room for something more personal — a place for beauty and health records that exists not to be shared, but to help you understand yourself and take care of yourself.
What it does
RURIRA is a personal, local-first log for self-care, inner care, exercise, mental state, and menstrual cycles, together with the cosmetics and items that support them.
There is no account or cloud sync for your records. Core records stay on the device by default, which is also why export and restore matter.
You can save a record with photos, notes, and ratings. You can register skincare, makeup, supplements, and healthcare items, then connect them to your Routines and to individual records — a single record can carry several cosmetics or healthcare items at once.
The Calendar lets you look back over your logs and upcoming plans. Archive lets you search across everything and organize it by category. My Items keeps your products in one place, linked to the records where you actually used them.
Sharing exists, but it is opt-in. If you want to post something, an SNS card lets you publish just that part. Whether anything leaves the app is always the user's choice.
How I built it
I have spent about five years building apps with Unity. This was my first Flutter project.
RURIRA is built with Flutter and Dart, using Riverpod for state management and Isar for on-device storage. Beauty logs, healthcare, My Items, Routine, Calendar, and Archive are designed to share a common data structure as much as possible, so records created in one place can be surfaced anywhere else. I worked through the project alongside Codex and Claude, leaning on the data-modeling habits I had built up in Unity.
Because users' core records are stored locally by default, I added ZIP export and restore so users can hold their own records and referenced images together. Purchase state, entitlement state, and other device-specific settings remain separate from the portable backup.
RevenueCat is integrated to define Premium entitlements and the purchase and restore paths. One principle decided where the boundary went: what a user writes down is her own asset, and I did not want to hold it hostage to get her to pay. Basic recording and recent review remain available without Premium, while Premium extends calendar history, routines, photos per record, detailed search, and ad-free use. The app does not grant Premium solely from an unverified local value; verified store entitlement data is the authority when it is available.
Challenges I ran into
The obvious challenge was holding a lot of different information — cosmetics, supplements, exercise, mental state, periods, and salons — without the screen becoming a burden. I handled that with categories, cards, spacing, color, and input screens that reveal fields step by step.
The work that actually consumed my time, though, was behind the screen.
Reshaping a data model without breaking existing data. Partway through, the supplement-only model had to grow into a general healthcare item record covering medicine, eye care, and hygiene. By then, real records already existed. Deleting the old collection and replacing it looks cleanest, but it severs every reference held by past logs and Routines. So I kept the old collection in place and upserted into the new one under the same UUID. Because identifiers never change, existing records migrate without rewriting a single reference.
For the same reason, even adding one category to an existing model required care: Isar persists enums by name, and re-running code generation can overwrite manual adjustments made to other models. Hand-editing only the generated mapping tables became a documented rule for the project. Every new feature meant re-checking that old records could still be read.
Making sure photos never disappear. A photo attached to a record cannot be bought again. I store the image file and the references to it — which records use this image — separately, so deleting a record only detaches a reference. Even when an image's reference count reaches zero, it is not deleted on the spot; it is marked as pending deletion and kept. I wanted to rule out the case where someone deletes a record and loses a photo she never meant to lose.
Keeping backup from becoming a loophole. While building ZIP export and restore, I realized the format had a hole. If trial state could be exported and restored wholesale, a user could take a backup before starting the trial and restore it repeatedly to extend the trial indefinitely. A feature meant to protect the user's data was quietly becoming a way around the purchase boundary.
The fix was to exclude trial state from the portable backup entirely and treat secure device storage as the source of truth. Even if a value is present in the ZIP, the secure value takes precedence on restore. Not being able to reach the store is not, by itself, a reason to unlock anything.
An estimate must not arrive late. Cycle estimation averages the gaps between past start dates:
$$\overline{C} = \frac{1}{n-1}\sum_{i=1}^{n-1}\left(s_{i+1} - s_i\right)$$
At first I rounded that average and used the same number everywhere. Using the app myself, I realized the unease of an estimated start date arriving later than the real one is greater than the reverse. So I split the number the screen shows from the number the estimate uses: the display keeps statistically correct rounding, while the estimate floors the value so it does not fall later than the average.
$$C_{\text{display}} = \operatorname{clamp}\bigl(\operatorname{round}(\overline{C}),\,20,\,45\bigr), \qquad C_{\text{estimate}} = \operatorname{clamp}\bigl(\lfloor \overline{C} \rfloor,\,20,\,45\bigr)$$
The same average, rounded two different ways, because the correctness of a number and the feelings of the person reading it are separate design problems.
Accomplishments I'm proud of
Shipping a first Flutter app that is not a prototype. Beauty logs, healthcare, My Items, Routine, Calendar, and Archive all run on one shared data structure, so a record saved in one place shows up correctly everywhere else.
I am most proud of the parts nobody sees. I designed each schema change so existing records would not be lost. Photos are protected by reference tracking and a deletion grace period rather than by hope. Backup and restore round-trip a user's real data — records and images included — without opening a loophole in the purchase boundary. Those are the things that decide whether an app is still trustworthy a year from now, and they were the hardest to get right.
And the rounding decision in cycle estimation. It is three lines of code, and it is the change I am happiest about.
What I learned
Adding convenient features does not, by itself, make a good app.
Information about a woman's self-care splits in two: some of it she may want to share, and some she wants to keep entirely to herself. So RURIRA separates recording, looking back, and sharing, and lets the user decide each one. Even with a lot of information on hand, a screen that overwhelms is a failure — reveal what is needed when it is needed, and let the looking-back happen calmly in Calendar and Archive.
Product names and notes a user saves are her own words. When the app's display language switches to English, those personal sentences must not be translated with it. Localizing the interface and touching the user's data are two different things, and keeping that line clean took real attention — categories, subcategories, and already-saved records all had to be checked.
Technically, the habit Unity gave me — decide how the data is held before building the screen — carried over intact. What I had not done before was design for a database meant to live on a device for years. "Once you have saved data in a shape, you are no longer free to change that shape" is a constraint whose weight I could only learn by building.
What's next for RURIRA | Beauty Log, Cosmetics Tracker & Calendar
RURIRA started from records kept for yourself, not records kept to be seen.
There are already excellent beauty and health apps. Even so, I think there is still a shortage of apps that respect each woman's own values and privacy, and let her enjoy self-care on her own terms.
Knowing your own state, keeping your items in order, and looking back on how things have changed — at your own pace. That is the experience RURIRA is aiming for.
Log in or sign up for Devpost to join the conversation.