<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alfred Chaos</title>
    <description>The latest articles on DEV Community by Alfred Chaos (@alfredchaos).</description>
    <link>https://dev.to/alfredchaos</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4169957%2Fe9cf424b-f7e6-48c2-852c-e6a4dca142f7.jpg</url>
      <title>DEV Community: Alfred Chaos</title>
      <link>https://dev.to/alfredchaos</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alfredchaos"/>
    <language>en</language>
    <item>
      <title>Why my period tracker predicts a window, not a single day</title>
      <dc:creator>Alfred Chaos</dc:creator>
      <pubDate>Mon, 02 Nov 2026 00:07:11 +0000</pubDate>
      <link>https://dev.to/alfredchaos/why-my-period-tracker-predicts-a-window-not-a-single-day-429p</link>
      <guid>https://dev.to/alfredchaos/why-my-period-tracker-predicts-a-window-not-a-single-day-429p</guid>
      <description>&lt;p&gt;A period tracker that tells you "your next period starts March 14" is lying to you.&lt;/p&gt;

&lt;p&gt;Not maliciously — just mathematically. Cycle length varies. For most people it bounces around by a few days each month, and the apps that print one confident little date are quietly averaging that variance out and hoping you won't notice when they're off by four days.&lt;/p&gt;

&lt;p&gt;When I built my own tracker — &lt;a href="https://www.moricycle.com" rel="noopener noreferrer"&gt;Mori&lt;/a&gt;, a free, no-account, offline Android app — the prediction design was the thing I spent the most time arguing with myself about. Here's where I landed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Windows, not dates
&lt;/h2&gt;

&lt;p&gt;Mori's home screen shows a range, like "expected between day 27 and day 31." The midpoint isn't hidden — it's just not presented as a promise.&lt;/p&gt;

&lt;p&gt;This turned out to be mostly a &lt;em&gt;presentation&lt;/em&gt; problem, not a math problem. The underlying estimate is the same either way; the difference is whether you show the error bars. Showing them costs you the marketing screenshot where the app looks psychic. I decided that was a screenshot worth losing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The inputs are boring, on purpose
&lt;/h2&gt;

&lt;p&gt;The estimate runs on your own recorded history and nothing else. No crowd data, no model trained on other people's bodies. A handful of your recent actual cycles is the whole training set, and the "model" is simple statistics over them — plain arithmetic you could verify with a calculator.&lt;/p&gt;

&lt;p&gt;With little history there's an honest problem: one recorded cycle is barely evidence of anything. So Mori just says so. If you skip the optional "average cycle length" field during setup and log nothing, the app shows "not enough data" instead of guessing. Every prediction carries a confidence label for the same reason — a stable history produces a tight, confident window; a volatile one produces a wider, lower-confidence estimate rather than fake precision.&lt;/p&gt;

&lt;h2&gt;
  
  
  Unusual records keep the record, lose the confidence
&lt;/h2&gt;

&lt;p&gt;One design rule I'm proud of: the app never silently "fixes" your data. If you log something odd — a very short gap between periods, an unusually long cycle — the record stays exactly as you entered it. What changes is the prediction's confidence, which drops, plus a gentle note. The app treats weird entries as real things that happen, not as corruption to be rejected. The only hard blocks are for inputs that can't actually be stored.&lt;/p&gt;

&lt;h2&gt;
  
  
  What this means in practice
&lt;/h2&gt;

&lt;p&gt;The fertile-window estimate works the same way: it's labeled as an estimate with uncertainty, never as a clinical result — and it's explicitly not a contraception method. That's a line I don't let the UI blur.&lt;/p&gt;

&lt;p&gt;None of this needs a server, which is the part I like most. The whole prediction pipeline — history, statistics, window, confidence — runs on the phone, offline. There's no account, so there's nothing to sync by default. When your period arrives a few days off the window, the app wasn't "wrong"; the window was the honest answer all along. Once that clicked for me, I couldn't go back to apps that pretend otherwise.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>android</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>What "delete all my data" actually has to delete</title>
      <dc:creator>Alfred Chaos</dc:creator>
      <pubDate>Thu, 22 Oct 2026 00:04:23 +0000</pubDate>
      <link>https://dev.to/alfredchaos/what-delete-all-my-data-actually-has-to-delete-442l</link>
      <guid>https://dev.to/alfredchaos/what-delete-all-my-data-actually-has-to-delete-442l</guid>
      <description>&lt;p&gt;When I added a "delete everything" button to Mori (a free period tracker for Android), I expected it to take an afternoon. It took three passes to get right, because "delete" is not one operation — it's a walk through every place data can hide.&lt;/p&gt;

&lt;p&gt;Here's the actual checklist, in case it helps someone building a local-first app. This is also why I'm skeptical of any app that claims "your data is deleted" while running servers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. The primary store is the easy part
&lt;/h2&gt;

&lt;p&gt;Mori keeps everything in SQLite. &lt;code&gt;DELETE FROM cycles;&lt;/code&gt; and friends. Done? Not even close.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Derived data
&lt;/h2&gt;

&lt;p&gt;The app doesn't just store records. It computes things from them: cycle statistics, predictions, the current phase. Some of that lives in caches keyed by derived ids. If you only wipe raw records, the UI can resurrect "ghost" predictions from cache. So the delete path walks the derived tables too — forecasts, statistics snapshots, everything.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Exports
&lt;/h2&gt;

&lt;p&gt;We let people export JSON / CSV / a readable summary. Those files go where the user puts them, but the app keeps a cache/index of export history. Deleting the data should not leave "exported on Tuesday" breadcrumbs in the UI. That index gets wiped too. (The already-saved files belong to the user — we don't reach into their files to delete them.)&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Scheduled notifications
&lt;/h2&gt;

&lt;p&gt;This one bit me. Period reminders are local notifications, and Android keeps them scheduled even if your database is empty. Delete all -&amp;gt; pending &lt;code&gt;PendingIntent&lt;/code&gt;s must be cancelled too, or the phone keeps pinging about a cycle that no longer exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Identity namespace
&lt;/h2&gt;

&lt;p&gt;We generate an anonymous install id so migrations know which records belong to "this device" — not an account, never uploaded. On delete-all, that id gets reset so a fresh install is indistinguishable from day one. If you keep the id, "delete" was cosmetic.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Sync tombstones
&lt;/h2&gt;

&lt;p&gt;Sync is optional and off by default. If someone enabled it, delete-all must also queue tombstones so the encrypted snapshot on the server shrinks to nothing — not just empty the local copy and leave the old blob up there. (Yes, the snapshot is ciphertext; no, that's not the point. The point is the delete has to mean &lt;em&gt;gone&lt;/em&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is easier offline-first
&lt;/h2&gt;

&lt;p&gt;The whole list is local. There's no "we'll delete it within 90 days", no support ticket, no export request form. Press the button, watch the app go empty, done. If you're evaluating any health app, try the delete path before you trust the record path — it's the part nobody demos.&lt;/p&gt;

&lt;p&gt;I built Mori around this exact constraint — records, predictions, exports, reminders all live on the phone. It's free and &lt;a href="https://www.moricycle.com/" rel="noopener noreferrer"&gt;lives here&lt;/a&gt; if you want to poke at it. Happy to answer "but what about X" in the comments.&lt;/p&gt;

</description>
      <category>dataownership</category>
      <category>privacy</category>
      <category>android</category>
      <category>indiedev</category>
    </item>
    <item>
      <title>Your period tracker doesn't need an ML model. It needs statistics.</title>
      <dc:creator>Alfred Chaos</dc:creator>
      <pubDate>Thu, 15 Oct 2026 00:59:40 +0000</pubDate>
      <link>https://dev.to/alfredchaos/your-period-tracker-doesnt-need-an-ml-model-it-needs-statistics-5g1p</link>
      <guid>https://dev.to/alfredchaos/your-period-tracker-doesnt-need-an-ml-model-it-needs-statistics-5g1p</guid>
      <description>&lt;p&gt;Every period tracker I tried wanted to predict my next cycle with "AI." Download a 200MB app, create an account, let the model learn my body. Meanwhile my actual question was simple: based on my last few cycles, roughly when should I expect the next one?&lt;/p&gt;

&lt;p&gt;That is not a machine learning problem. It's a statistics problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the "AI" actually does
&lt;/h2&gt;

&lt;p&gt;Cycle prediction, at its core, is: take your last N cycle lengths, compute a central estimate, add a window. A mean or median over your recent history, maybe weighted toward recent cycles. That's it. You don't need a neural net to average five numbers.&lt;/p&gt;

&lt;p&gt;The apps that market "AI-powered predictions" are mostly doing this same arithmetic, then wrapping it in language that sounds smart. The model isn't the point — the point is that you're creating an account and uploading your cycle history to their servers, where it becomes training data and a retention hook.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I built instead
&lt;/h2&gt;

&lt;p&gt;I made &lt;a href="https://www.moricycle.com/" rel="noopener noreferrer"&gt;Mori&lt;/a&gt;, a free Android period tracker that keeps everything on the phone. No account, no email, no cloud by default. The prediction is plain statistics on your own logged dates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Take up to your 6 most recent cycles&lt;/li&gt;
&lt;li&gt;Median cycle length as the central estimate&lt;/li&gt;
&lt;li&gt;A date range, not a single fake-precise day&lt;/li&gt;
&lt;li&gt;A confidence label that drops when your history is short or irregular&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When there's not enough data, it says "not enough data" instead of inventing a confident guess. Because it's deterministic, I can actually test it: feed the same cycle history, get the same answer, every time. No model drift, no silent retraining, no "the algorithm changed."&lt;/p&gt;

&lt;h2&gt;
  
  
  The uncomfortable part
&lt;/h2&gt;

&lt;p&gt;Predictions from a phone-side heuristic are less magical than what a billion-parameter model might promise. But cycle prediction was never the hard part. The hard part is that the data is sensitive, the app should work in airplane mode, and you shouldn't have to trade an account for basic arithmetic.&lt;/p&gt;

&lt;p&gt;If your tracker needs an ML model to tell you when your period is probably coming, it's solving a different problem than yours.&lt;/p&gt;




&lt;p&gt;Mori is free, one-time-purchase optional sync, APK direct download. Source of truth is on your device, not on our servers.&lt;/p&gt;

</description>
      <category>opensource</category>
    </item>
    <item>
      <title>I built a period tracker that never asks for an account</title>
      <dc:creator>Alfred Chaos</dc:creator>
      <pubDate>Thu, 08 Oct 2026 00:21:54 +0000</pubDate>
      <link>https://dev.to/alfredchaos/i-built-a-period-tracker-that-never-asks-for-an-account-140o</link>
      <guid>https://dev.to/alfredchaos/i-built-a-period-tracker-that-never-asks-for-an-account-140o</guid>
      <description>&lt;p&gt;This week I shipped the first public version of Mori, an Android period tracker. The product rule I started with was simple: no account, ever, for the core features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why that rule
&lt;/h2&gt;

&lt;p&gt;Period data is some of the most sensitive stuff on a phone. In most tracker apps it ends up on a company server, attached to an email, behind a login the app demands before it even opens. That model has real-world consequences — after Roe v. Wade fell, the White House literally warned people about period tracker apps because server-side reproductive data can be subpoenaed.&lt;/p&gt;

&lt;p&gt;So I built the opposite default: records live in a local SQLite database on the phone. Without cloud sync, nothing ever leaves the device. There is no signup screen. You open the app, mark your period days on the calendar, and it gives you a prediction window for next time — computed on-device from your own history, with an explicit confidence label and an explanation of what it based the estimate on. Predictions are deliberately boring: deterministic math over your records, not a black-box model.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's in it
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Calendar + cycle ring, tap to log/unlog dates&lt;/li&gt;
&lt;li&gt;Next-period range + ovulation/fertile-window estimates, always labelled as estimates (never as medical certainty)&lt;/li&gt;
&lt;li&gt;Optional local notifications that don't put health words in the notification body&lt;/li&gt;
&lt;li&gt;Full export and "delete everything" on-device&lt;/li&gt;
&lt;li&gt;English + Chinese&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The app itself has zero analytics. There is exactly one analytics script in the whole product, on the marketing landing page (GA4), because I needed to see if anyone found the thing.&lt;/p&gt;

&lt;h2&gt;
  
  
  The paid part
&lt;/h2&gt;

&lt;p&gt;The model is buy-once, not subscription. Everything above is free forever — logging, history, predictions, export, delete, turning reminders off. The only thing that costs money ($3.99, one-time) is optional encrypted cloud sync. The server side is Go + Postgres; the snapshot is encrypted on the device before upload, and the backend never sees plaintext records. I didn't call it "end-to-end" in the docs because the server can unwrap the DEK during account recovery — being honest about that felt like the whole point of the exercise.&lt;/p&gt;

&lt;h2&gt;
  
  
  State of it
&lt;/h2&gt;

&lt;p&gt;It's a side-loaded APK from the site (&lt;a href="https://www.moricycle.com/" rel="noopener noreferrer"&gt;https://www.moricycle.com/&lt;/a&gt;) — not on Google Play yet, which is the main friction right now. iOS is planned, not started.&lt;/p&gt;

&lt;p&gt;Ask me anything about the sync crypto design, the deterministic prediction approach, or why I spent a month arguing with myself about the word "private" on the landing page.&lt;/p&gt;

</description>
      <category>privacy</category>
      <category>android</category>
      <category>indiedev</category>
    </item>
  </channel>
</rss>
