<?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: Aradar</title>
    <description>The latest articles on DEV Community by Aradar (@aradar46).</description>
    <link>https://dev.to/aradar46</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%2F4091066%2F1e668543-2a9f-4017-8bee-ae1161028ec0.jpg</url>
      <title>DEV Community: Aradar</title>
      <link>https://dev.to/aradar46</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aradar46"/>
    <language>en</language>
    <item>
      <title>Why I Built an Open-Source, Zero-Cloud Period Tracker with React 19 &amp; Capacitor</title>
      <dc:creator>Aradar</dc:creator>
      <pubDate>Sun, 23 Aug 2026 17:11:13 +0000</pubDate>
      <link>https://dev.to/aradar46/why-i-built-an-open-source-zero-cloud-period-tracker-with-react-19-capacitor-hmb</link>
      <guid>https://dev.to/aradar46/why-i-built-an-open-source-zero-cloud-period-tracker-with-react-19-capacitor-hmb</guid>
      <description>&lt;p&gt;In an era where health data is increasingly commodified, tracked, and exposed in data breaches, personal data privacy isn't just a bonus feature — it's a fundamental requirement.&lt;/p&gt;

&lt;p&gt;Most period and cycle tracking apps require cloud accounts, transmit deeply intimate health telemetry to remote servers, and integrate third-party ad SDKs. When data lives on a central server, it is vulnerable to leaks, corporate sales, and subpoenas.&lt;/p&gt;

&lt;p&gt;We asked a simple engineering question: &lt;strong&gt;What if the server simply didn't exist?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That philosophy led to &lt;a href="https://github.com/aradar46/Mooneva-Cycle-Private-Period-Tracker" rel="noopener noreferrer"&gt;&lt;strong&gt;Mooneva Cycle&lt;/strong&gt;&lt;/a&gt; — a 100% offline-first, private, and open-source (GPL-3.0) period &amp;amp; cycle tracker built for web, iOS, and Android.&lt;/p&gt;




&lt;h2&gt;
  
  
  🎯 Core Architectural Philosophy: Zero Trust, Zero Cloud
&lt;/h2&gt;

&lt;p&gt;Our design rule from day one: &lt;strong&gt;Data that never leaves the user's device cannot be leaked or compromised.&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Traditional Cloud Trackers&lt;/th&gt;
&lt;th&gt;Mooneva Cycle&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Stored on third-party cloud databases&lt;/td&gt;
&lt;td&gt;Stored exclusively on-device (&lt;code&gt;localStorage&lt;/code&gt; / Secure Storage)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Third-party analytics &amp;amp; telemetry trackers&lt;/td&gt;
&lt;td&gt;Zero analytics, zero ad SDKs, zero crash loggers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requires email/phone registration&lt;/td&gt;
&lt;td&gt;No account, no signup, instant access&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Susceptible to remote breaches&lt;/td&gt;
&lt;td&gt;No centralized database to breach&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  🛠️ The Tech Stack
&lt;/h2&gt;

&lt;p&gt;To deliver a snappy, native-like mobile experience across iOS and Android without maintaining separate native codebases, we opted for a modern web-to-native stack:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend Core:&lt;/strong&gt; &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React 19&lt;/a&gt; + &lt;a href="https://www.typescriptlang.org/" rel="noopener noreferrer"&gt;TypeScript&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Build Tool:&lt;/strong&gt; &lt;a href="https://vitejs.dev/" rel="noopener noreferrer"&gt;Vite 6&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Native Runtime:&lt;/strong&gt; &lt;a href="https://capacitorjs.com/" rel="noopener noreferrer"&gt;Capacitor 8&lt;/a&gt; (iOS &amp;amp; Android bridge)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Styling:&lt;/strong&gt; Tailwind CSS + Vanilla CSS tokens&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Internationalization:&lt;/strong&gt; &lt;code&gt;i18next&lt;/code&gt; (supporting 12 languages + RTL layout)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reporting &amp;amp; Export:&lt;/strong&gt; &lt;code&gt;html2pdf.js&lt;/code&gt; for on-device clinical PDF reports&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testing:&lt;/strong&gt; &lt;a href="https://vitest.dev/" rel="noopener noreferrer"&gt;Vitest&lt;/a&gt; + &lt;code&gt;@testing-library/react&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔐 Key Technical Highlights &amp;amp; Design Decisions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Local-First Encrypted Backups with PBKDF2 &amp;amp; AES-GCM
&lt;/h3&gt;

&lt;p&gt;Since there is no remote database to restore from, data portability and secure backup exports are critical. We use standard &lt;strong&gt;Web Crypto APIs&lt;/strong&gt; for user backups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Password-derived cryptographic keys via &lt;strong&gt;PBKDF2&lt;/strong&gt; (high iteration counts + dynamic salt).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AES-GCM (256-bit)&lt;/strong&gt; authenticated encryption for backup archives.&lt;/li&gt;
&lt;li&gt;Zero external cryptographic dependencies needed — fully native to modern Web and WebView runtimes.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Client-side key derivation &amp;amp; encryption flow&lt;/span&gt;
&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;deriveKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Uint8Array&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;CryptoKey&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;enc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TextEncoder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;importKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;raw&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;enc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;password&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PBKDF2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deriveKey&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;subtle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;deriveKey&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;PBKDF2&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;salt&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;iterations&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;250&lt;/span&gt;&lt;span class="nx"&gt;_000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SHA-256&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="nx"&gt;baseKey&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;AES-GCM&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;encrypt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;decrypt&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Push-Less Local Notifications
&lt;/h3&gt;

&lt;p&gt;Most apps use FCM (Firebase Cloud Messaging) or Apple APNs coupled with backend cron jobs to send reminders. &lt;/p&gt;

&lt;p&gt;To eliminate cloud triggers, Mooneva schedules all alerts strictly on-device using &lt;code&gt;@capacitor/local-notifications&lt;/code&gt;. The device OS manages the alarm queue locally for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Predicted cycle &amp;amp; period starts&lt;/li&gt;
&lt;li&gt;Ovulation &amp;amp; fertile windows&lt;/li&gt;
&lt;li&gt;Daily symptom/mood logging reminders&lt;/li&gt;
&lt;li&gt;Contraceptive pill/patch/ring adherence schedules&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. "Discrete Mode" &amp;amp; Local PIN Protection
&lt;/h3&gt;

&lt;p&gt;Privacy extends to shoulder-surfing. We engineered:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Discrete Mode:&lt;/strong&gt; Disguises the app launcher icon and name into a neutral utility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Biometric &amp;amp; PIN Lock:&lt;/strong&gt; Guarding the interface with configurable timeouts using encrypted storage for authentication state.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Non-Gregorian Calendar &amp;amp; True RTL Support
&lt;/h3&gt;

&lt;p&gt;Health apps often overlook regional accessibility. Mooneva includes full support for the &lt;strong&gt;Persian (Jalaali) solar calendar&lt;/strong&gt; alongside Gregorian dates, accompanied by automatic bidirectional (RTL) layout switching via Tailwind's logical directions.&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Migration Freedom (Import from Flo, Clue &amp;amp; drip)
&lt;/h3&gt;

&lt;p&gt;Vendor lock-in is hostile to user autonomy. We implemented client-side parsers that ingest export files from major platforms (Flo, Clue, drip), normalizing historical cycle dates, flow intensities, and logs into Mooneva's local schema directly in the browser/app memory.&lt;/p&gt;




&lt;h2&gt;
  
  
  🚧 Challenges Solved
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Deterministic Predictions on Sparse Data:&lt;/strong&gt;
Designing cycle prediction algorithms that run entirely on client hardware without heavyweight ML dependencies, providing robust rolling-average predictions while gracefully handling irregular cycles and birth-control withdrawal bleeds.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;True Air-Gapped Verification:&lt;/strong&gt;
Configuring mobile manifests (&lt;code&gt;AndroidManifest.xml&lt;/code&gt; and &lt;code&gt;Info.plist&lt;/code&gt;) to ensure no extraneous network privileges or background tracking services are requested.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Platform PDF Generation:&lt;/strong&gt;
Generating doctor-ready clinical PDF summaries on the fly directly inside mobile WebViews using canvas and DOM rendering without leaking document data to an external PDF generation API.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  🤝 Open Source &amp;amp; Contributing
&lt;/h2&gt;

&lt;p&gt;Mooneva Cycle is 100% free and open source under &lt;strong&gt;GPL-3.0&lt;/strong&gt;. There is no venture capital, no monetization through data harvesting, and no paywalls on essential features.&lt;/p&gt;

&lt;p&gt;If you care about local-first software, client-side encryption, and accessible health tools:&lt;/p&gt;

&lt;p&gt;⭐ &lt;strong&gt;Star the repository:&lt;/strong&gt; &lt;a href="https://github.com/aradar46/Mooneva-Cycle-Private-Period-Tracker" rel="noopener noreferrer"&gt;github.com/aradar46/Mooneva-Cycle-Private-Period-Tracker&lt;/a&gt;&lt;br&gt;&lt;br&gt;
📱 &lt;strong&gt;Try it on Google Play:&lt;/strong&gt; &lt;a href="https://play.google.com/store/apps/details?id=com.mooneva.app" rel="noopener noreferrer"&gt;Mooneva on Google Play&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🍎 &lt;strong&gt;Try it on App Store:&lt;/strong&gt; &lt;a href="https://apps.apple.com/us/app/mooneva-cycle/id6761208425" rel="noopener noreferrer"&gt;Mooneva Cycle on iOS&lt;/a&gt;&lt;br&gt;&lt;br&gt;
🌐 &lt;strong&gt;Website:&lt;/strong&gt; &lt;a href="https://mooneva.se/" rel="noopener noreferrer"&gt;mooneva.se&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We welcome contributions — from translations and UI tweaks to cryptographic audits and prediction algorithm improvements!&lt;/p&gt;

</description>
      <category>react</category>
      <category>opensource</category>
      <category>webdev</category>
      <category>mobile</category>
    </item>
    <item>
      <title>Silence Is a Feature</title>
      <dc:creator>Aradar</dc:creator>
      <pubDate>Sun, 23 Aug 2026 17:03:40 +0000</pubDate>
      <link>https://dev.to/aradar46/silence-is-a-feature-2om5</link>
      <guid>https://dev.to/aradar46/silence-is-a-feature-2om5</guid>
      <description>&lt;p&gt;Originally published at &lt;a href="https://aradar.top/posts/silence-is-a-feature/" rel="noopener noreferrer"&gt;aradar.top.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The server room is too loud. You picture blue LEDs blinking in the dark. It’s actually a wall of sound - thousands of small fans screaming in slightly different keys, a noise that gets into your teeth. I had the yellow ear protection on and could still feel it in my jaw. Aaron didn’t seem to notice. Or he noticed years ago and made his peace.&lt;/p&gt;

&lt;p&gt;He walked the row, found the machine, pressed the release. The drive slid out. He held it up, turned it once in the light, and pointed at it with his chin. Grab this.&lt;/p&gt;

&lt;p&gt;He seated the new one, waited for the light to go from amber to green, and that was it. Upstairs, a lab full of people kept working on data that had never stopped being there. Not one of them looked up.&lt;/p&gt;

&lt;p&gt;Past the double doors, when the noise dropped away and my ears were still ringing, he said: “Silence is a feature.”&lt;/p&gt;

&lt;p&gt;I said something. Something like sure.&lt;/p&gt;

&lt;p&gt;“No, it’s a feature. Somebody pays for it. You pay, I pay, everybody pays. It’s just not free.” He tapped the dead drive in my hand. “This is the bill.”&lt;/p&gt;

&lt;p&gt;We walked. He wasn’t done.&lt;/p&gt;

&lt;p&gt;“Think about it. No alert. No status page. No email from IT. That’s the product. That big boring nothing - that’s what all the money buys. And when it breaks, the first thing you lose is the quiet. Then somebody walks back in there.” He tipped his head toward the doors behind us. “Everybody loves builders. Fine. But what you actually depend on, every hour, is maintainers. Water at the pressure you expect. Electricity that’s just there. Cables under the ocean so you can reach the whole world without once wondering how. Somebody is awake right now so that all of it feels like nothing to you.”&lt;/p&gt;

&lt;p&gt;He dropped the dead drive in a bin by the door with a dozen others just like it. He had a ticket to close and lunch to get.&lt;/p&gt;

&lt;p&gt;Somebody has to deal with the noise so you never feel the lack of silence.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>careerdevelopment</category>
      <category>opensource</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
