<?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: AIO Spark</title>
    <description>The latest articles on DEV Community by AIO Spark (@aiospark).</description>
    <link>https://dev.to/aiospark</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3631316%2F99f2f26c-0d19-4ca5-9d8f-23dc4f048dc5.png</url>
      <title>DEV Community: AIO Spark</title>
      <link>https://dev.to/aiospark</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/aiospark"/>
    <language>en</language>
    <item>
      <title>How I Built a Private Finance Tool with Vanilla JS and Local Storage</title>
      <dc:creator>AIO Spark</dc:creator>
      <pubDate>Wed, 26 Nov 2025 19:40:44 +0000</pubDate>
      <link>https://dev.to/aiospark/how-i-built-a-private-finance-tool-with-vanilla-js-and-local-storage-1pel</link>
      <guid>https://dev.to/aiospark/how-i-built-a-private-finance-tool-with-vanilla-js-and-local-storage-1pel</guid>
      <description>&lt;p&gt;I work in e-commerce and SEO by day, so I spend a lot of time dealing with complex stacks, databases, and user tracking.&lt;/p&gt;

&lt;p&gt;But when I wanted to build a simple tool to track my own subscription spending, I didn't want any of that. I didn't want a database. I didn't want user accounts. And I definitely didn't want to handle sensitive financial data on a server.&lt;/p&gt;

&lt;p&gt;So I built &lt;strong&gt;FinTech Lite&lt;/strong&gt;, a suite of financial tools that runs 100% in the browser. Here is how (and why) I built the &lt;strong&gt;Subscription Auditor&lt;/strong&gt; using nothing but Vanilla JS, Tailwind, and the Local Storage API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vdjhnvwh2apil4nsz9t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1vdjhnvwh2apil4nsz9t.png" alt=" " width="800" height="711"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Constraint: Privacy by Architecture
&lt;/h2&gt;

&lt;p&gt;Most fintech apps follow the same pattern:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;User signs up (email/password).&lt;/li&gt;
&lt;li&gt;App requests bank credentials (Plaid/Yodlee).&lt;/li&gt;
&lt;li&gt;App sucks data into a database.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I wanted the opposite. I wanted a "dumb" calculator that remembers you but doesn't know you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Stack
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;HTML5: Semantic structure.&lt;/li&gt;
&lt;li&gt;Tailwind CSS: For rapid styling (loaded via CDN to keep it dead simple).&lt;/li&gt;
&lt;li&gt;Vanilla JavaScript: No React, no Vue, no build step. Just an &lt;code&gt;engine.js&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;Local Storage: The "database."&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The "Database" Logic
&lt;/h2&gt;

&lt;p&gt;Instead of a complex backend, I use a simple state object and persist it to &lt;code&gt;localStorage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the core logic from my &lt;code&gt;subscription-engine.js&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const DB_KEY = 'fintechLiteAuditorData';

let state = {
    subscriptions: [], // { id, name, amount, frequency }
    currency: 'USD',
    customSymbol: ''
};

function saveState() {
    const data = {
        subscriptions: state.subscriptions,
        currency: state.currency,
        customSymbol: state.customSymbol
    };
    localStorage.setItem(DB_KEY, JSON.stringify(data));
}

function loadState() {
    const data = localStorage.getItem(DB_KEY);
    if (data) {
        try {
            const parsedData = JSON.parse(data);
            state.subscriptions = parsedData.subscriptions || [];
            // ... rest of state hydration
        } catch (e) { console.error("Error loading state"); }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It’s incredibly simple. When a user adds a Netflix subscription, it pushes to the &lt;code&gt;state&lt;/code&gt; array and immediately syncs to &lt;code&gt;localStorage&lt;/code&gt;. When they refresh the page, &lt;code&gt;loadState()&lt;/code&gt; runs on &lt;code&gt;DOMContentLoaded&lt;/code&gt;, and their data is right where they left it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge: "Data Safety"
&lt;/h2&gt;

&lt;p&gt;The biggest downside to Local Storage is that it's ephemeral. If the user clears their cache, the data is gone.&lt;/p&gt;

&lt;p&gt;To solve this without adding a server, I added two features:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;JSON Export/Import&lt;/strong&gt;: A simple "Backup" button that dumps the &lt;code&gt;state&lt;/code&gt; object into a JSON file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CSV Report&lt;/strong&gt;: A function that loops through the state and generates a downloadable CSV for Excel users.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Simple JSON Export
function handleExportJson() {
    const data = localStorage.getItem(DB_KEY);
    const blob = new Blob([data], { type: 'application/json' });
    const url = URL.createObjectURL(blob);
    // ... create anchor tag and click it
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why "Lite" Matters
&lt;/h2&gt;

&lt;p&gt;We are so used to spinning up Next.js apps for everything that we forget how powerful the browser is on its own. By removing the server:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Hosting is free&lt;/strong&gt; (static files).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;GDPR compliance is automatic&lt;/strong&gt; (I don't process the data).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trust is built-in&lt;/strong&gt; (Network tab shows zero API calls).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you want to see it in action, check out the &lt;a href="https://www.fintechlite.com/subscription_auditor.html" rel="noopener noreferrer"&gt;Subscription Auditor&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let me know what you think. Does a "local-only" approach make you feel safer using financial tools, or do you miss the cloud sync?&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>css</category>
      <category>showdev</category>
      <category>privacy</category>
    </item>
  </channel>
</rss>
