<?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: Umeh Chisom</title>
    <description>The latest articles on DEV Community by Umeh Chisom (@chisom_auvirasystems).</description>
    <link>https://dev.to/chisom_auvirasystems</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%2F3804237%2F60fb2334-3ece-4184-ac91-cfe743b9e633.png</url>
      <title>DEV Community: Umeh Chisom</title>
      <link>https://dev.to/chisom_auvirasystems</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chisom_auvirasystems"/>
    <language>en</language>
    <item>
      <title>The Sovereign Vault: Why JSON is the ultimate database for privacy-conscious apps.</title>
      <dc:creator>Umeh Chisom</dc:creator>
      <pubDate>Mon, 09 Mar 2026 16:40:55 +0000</pubDate>
      <link>https://dev.to/auvira_systems/the-sovereign-vault-why-json-is-the-ultimate-database-for-privacy-conscious-apps-5b5e</link>
      <guid>https://dev.to/auvira_systems/the-sovereign-vault-why-json-is-the-ultimate-database-for-privacy-conscious-apps-5b5e</guid>
      <description>&lt;p&gt;Most modern software treats your data like a hostage.&lt;/p&gt;

&lt;p&gt;If you use a cloud-based accounting tool, your financial history lives in their Postgres database, behind their API, subject to their subscription terms. If they go bust or change their pricing, your data is a headache to move.&lt;/p&gt;

&lt;p&gt;When I started building AccIQ under Auvira Systems, I wanted to build "Sovereign Software." I wanted a system where the "user",not the "platform", is the source of truth.&lt;/p&gt;

&lt;p&gt;Here is why I ditched the cloud database and built the &lt;strong&gt;Sovereign Vault&lt;/strong&gt; using nothing but JSON and browser APIs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. The "Local-First" Problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building a local-first app in React is great for speed (zero latency), but it creates a massive risk: &lt;strong&gt;Device Lock-in.&lt;/strong&gt;&lt;br&gt;
If your data only lives in your browser's localStorage, what happens when you buy a new laptop? Or if you clear your browser cache?&lt;/p&gt;

&lt;p&gt;To solve this, I built the Sovereign Vault. It’s a simple but powerful concept: Your entire financial existence should be reducible to a single, portable file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Why JSON is the ultimate "Database"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a double-entry ledger, JSON is actually superior to a live SQL database for the end-user:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Human Readable:&lt;/strong&gt; You can open your "Vault" in any text &lt;br&gt;
editor. You don't need my app to see your data.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Versionable:&lt;/strong&gt; You can drop your Vault into a Git repo and see exactly how your finances changed over time.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Platform Agnostic:&lt;/strong&gt; If I stop maintaining Finance-OS tomorrow, you can write a simple Python script to parse your JSON and move it to Excel or another tool.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;3. The Technical Challenge: Validating the Import&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The hardest part of a "Sovereign Vault" isn't the export—it's the &lt;strong&gt;Import.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a user uploads a JSON file, my React application has to treat it as "untrusted input." If the JSON is malformed or if someone manually edited a number so that the ledger no longer balances (Assets ≠ Liabilities + Equity), the entire app state will corrupt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Validation Logic:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;I implemented a strict validation pipeline during the import process:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Schema Check:&lt;/strong&gt; Ensuring every transaction has a debit, credit, timestamp, and id.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrity Check:&lt;/strong&gt; Re-running the entire ledger logic from the first transaction to the last to ensure the final balances match the imported totals.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Atomic Update:&lt;/strong&gt; We only replace the localStorage state if the entire validation passes.&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// A simplified look at the validation flow&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleImport&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonFile&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="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;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;jsonFile&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 1. Validate Schema&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;isValidLedgerSchema&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid Vault Format&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 2. Verify Ledger Balance&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;isBalanced&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;transactions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;tx&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isBalanced&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Ledger Imbalance Detected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// 3. Commit to Local Storage&lt;/span&gt;
  &lt;span class="nx"&gt;localStorage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;finance_os_vault&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nb"&gt;window&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;reload&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="c1"&gt;// Refresh to boot from new state&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;4. Software as a Tool, Not a Service&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;By building the Sovereign Vault, I’ve essentially made my own business model "opt-in."&lt;/p&gt;

&lt;p&gt;I don't own your data. I don't charge you a "ransom" (subscription) to access your own history. I provide the &lt;strong&gt;IDE&lt;/strong&gt; (the interface), and you provide the &lt;strong&gt;Vault&lt;/strong&gt; (the data).&lt;/p&gt;

&lt;p&gt;This architecture isn't just a technical choice; it's a statement about privacy and ownership in the age of "Big Cloud."&lt;/p&gt;

&lt;p&gt;Try the Architecture&lt;/p&gt;

&lt;p&gt;You can test the Sovereign Vault yourself. Open the AccIQ demo, log a few transactions using the AI command bar, and hit the "Export Vault" button in the settings in the sovereign vault section. You'll get a clean JSON file of your data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://acciqmvp3.vercel.app" rel="noopener noreferrer"&gt;👉 Launch AccIQ (Guest Mode)&lt;/a&gt;&lt;br&gt;
I’d love to hear from other devs: Are we moving toward a "Local-First" future, or is the convenience of the cloud too hard to give up?&lt;/p&gt;

&lt;p&gt;I'm Chisom, founder of Auvira Systems. We build sovereign software for founders.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>architecture</category>
      <category>privacy</category>
    </item>
    <item>
      <title>Building a "Privacy Shield" in React: How I obfuscated financial data for working in public</title>
      <dc:creator>Umeh Chisom</dc:creator>
      <pubDate>Fri, 06 Mar 2026 03:31:23 +0000</pubDate>
      <link>https://dev.to/auvira_systems/building-a-privacy-shield-in-react-how-i-obfuscated-financial-data-for-working-in-public-285p</link>
      <guid>https://dev.to/auvira_systems/building-a-privacy-shield-in-react-how-i-obfuscated-financial-data-for-working-in-public-285p</guid>
      <description>&lt;p&gt;As a solo founder building AccIQ (a local-first financial IDE), I spend a lot of time working in coffee shops and coworking spaces.&lt;/p&gt;

&lt;p&gt;The problem? I’m often looking at my own cash flow, runway, and burn rate. Having those numbers visible on a 14-inch screen in a crowded cafe is... stressful.&lt;/p&gt;

&lt;p&gt;I needed a way to "hide" the data instantly without breaking the UI or reloading the page. So, I built a global Privacy Shield.&lt;/p&gt;

&lt;p&gt;Here is the simple React + Tailwind pattern I used to build it.&lt;/p&gt;

&lt;p&gt;The Logic: &lt;strong&gt;Blur, Don't Hide&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most common way to hide data is to replace it with asterisks (****). But that breaks the visual rhythm of a dashboard. It makes it hard to see if a column is balanced or if a graph is trending correctly.&lt;/p&gt;

&lt;p&gt;Instead, I chose to use CSS Filters. By applying a blur, you maintain the "shape" of the data (you can tell if it's a large number or a small one) without it being legible to someone sitting at the next table.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Global State
I used a simple React Context (or a global state hook) to manage the isPrivacyMode boolean.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const [isPrivacyMode, setIsPrivacyMode] = useState(false);

const togglePrivacy = () =&amp;gt; 
setIsPrivacyMode(!isPrivacyMode);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;The Tailwind Pattern
The implementation is incredibly clean thanks to Tailwind's utility classes. I created a reusable PrivacyText component that wraps any sensitive integer.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;interface PrivacyTextProps {
  value: string | number;
  className?: string;
}

const PrivacyText = ({ value, className = "" }: PrivacyTextProps) =&amp;gt; {
  const { isPrivacyMode } = usePrivacy(); // Your global state hook

  return (
    &amp;lt;span 
      className={`
        transition-all duration-300 ease-in-out
        ${isPrivacyMode ? 'blur-md opacity-40 select-none pointer-events-none' : 'blur-0 opacity-100'}
        ${className}
      `}
    &amp;gt;
      {value}
    &amp;lt;/span&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Why this works:&lt;br&gt;
blur-md: This is the sweet spot. It makes text completely unreadable but keeps the layout intact.&lt;/p&gt;

&lt;p&gt;opacity-40: Adding a slight transparency makes the blurred text look "disabled," signaling to the user that the shield is active.&lt;/p&gt;

&lt;p&gt;select-none: This prevents someone from accidentally (or intentionally) highlighting the text to reveal it.&lt;/p&gt;

&lt;p&gt;transition-all: A smooth 300ms transition makes the toggle feel like a premium feature rather than a glitchy UI jump.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Keyboard Shortcut&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;A privacy shield is useless if you have to hunt for a button while someone is walking behind you. I mapped it to a global keyboard listener (typically Cmd + Shift + P).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;useEffect(() =&amp;gt; {
  const handleKeyDown = (e: KeyboardEvent) =&amp;gt; {
    if (e.metaKey &amp;amp;&amp;amp; e.shiftKey &amp;amp;&amp;amp; e.key === 'P') {
      togglePrivacy();
    }
  };
  window.addEventListener('keydown', handleKeyDown);
  return () =&amp;gt; window.removeEventListener('keydown', handleKeyDown);
}, []);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Result&lt;/p&gt;

&lt;p&gt;This small feature has become one of the most talked-about parts of AccIQ. It’s a "quality of life" detail that shows you actually understand your users' environment.&lt;/p&gt;

&lt;p&gt;You can see the Privacy Shield in action (and toggle it yourself) in the Finance-OS demo here:&lt;/p&gt;

&lt;p&gt;👉&lt;a&gt; Launch AccIQ (Guest Mode)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm curious—what other "public-friendly" UI features have you seen or built? Let me know in the comments!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>tailwindcss</category>
      <category>uxdesign</category>
    </item>
    <item>
      <title>Building a Local-First Financial IDE: How I forced Gemini AI to do strict Double-Entry Accounting</title>
      <dc:creator>Umeh Chisom</dc:creator>
      <pubDate>Tue, 03 Mar 2026 19:51:58 +0000</pubDate>
      <link>https://dev.to/auvira_systems/building-a-local-first-financial-ide-how-i-forced-gemini-ai-to-do-strict-double-entry-accounting-p1h</link>
      <guid>https://dev.to/auvira_systems/building-a-local-first-financial-ide-how-i-forced-gemini-ai-to-do-strict-double-entry-accounting-p1h</guid>
      <description>&lt;p&gt;I got tired of accounting software that feels like a slow, cloud-based spreadsheet from 2010.&lt;br&gt;
As a developer, I spend my day in VS Code—it's fast, keyboard-driven, and local. I wanted my financial tools to feel the exact same way. So, I decided to build Finance-OS under my new studio, Auvira Systems.&lt;br&gt;
My strict requirements were:&lt;br&gt;
Zero Cloud Database: Financial data is sensitive. It should live in the browser, not on my servers.&lt;br&gt;
Double-Entry Ledger: It had to be mathematically rigorous. No "editing" history, only reversals.&lt;br&gt;
AI Command Bar: I wanted to type "Paid $50 for AWS hosting" and have the system automatically balance the books.&lt;br&gt;
Here is how I architected it using React 19, Vite, and Gemini, and the massive technical hurdles I ran into along the way.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Local-First Architecture
The biggest paradigm shift was dropping Postgres/MongoDB.
Instead, the entire application state—every transaction, account, and predictive forecast—lives in the user's browser using localStorage (and eventually IndexedDB for scale).
The benefit? Zero latency. When you switch between the Chart of Accounts and the Forecasting Engine, it's instant.
The challenge? Data portability. To solve this, I built a "Sovereign Vault" feature. Users can export their entire ledger as a single, encrypted JSON file and import it on another machine. You own your database.&lt;/li&gt;
&lt;li&gt;Forcing an LLM to do strict accounting
This was the hardest part. LLMs are notoriously bad at math and strict formatting. If the AI hallucinates a number, a double-entry ledger (where Assets = Liabilities + Equity) will break instantly.
To fix this, I used Google Gemini as a stateless parser, not a database.
When a user types a command, the app sends it to a stateless proxy. The prompt strictly enforces a JSON schema:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// The AI is only allowed to return this structure
interface AIResponse {
  debitAccount: string;
  creditAccount: string;
  amountInCents: number; // NEVER use floats for currency!
  description: string;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Golden Rule: The AI does not touch the ledger. It only suggests the JSON payload. The local React application catches the JSON, verifies that the accounts exist, ensures the debits equal the credits, and then commits the transaction to the local state.&lt;br&gt;
If the AI hallucinates, the local TypeScript logic rejects it.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The "Privacy Shield" (A fun UI detail)
Because the app is local, I found myself using it in coffee shops. But having my runway and cash burn visible on my screen in public was stressful.
I built a global "Privacy Shield" toggle. When activated, it applies a Tailwind blur-md and reduced opacity to all sensitive financial integers across the entire app.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// A simple but highly effective UI pattern
&amp;lt;p className={`text-2xl font-mono ${isPrivacyMode ? 'blur-md opacity-50' : ''}`}&amp;gt;
  {formatCurrency(totalCash)}
&amp;lt;/p&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Try it out (No Sign-up Required)&lt;br&gt;
Building complex, stateful applications entirely in the browser has been an incredible learning experience. We are just scratching the surface of what "Local-First" web apps can do.&lt;br&gt;
Because there is no backend database, I built a frictionless Guest Mode. You can click the link below, jump straight into the IDE, and test the AI command bar yourself. Your data will stay on your machine.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://acciqmvp3.vercel.app/" rel="noopener noreferrer"&gt;👉 Try Finance-OS Live Here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd love to hear your thoughts on local-first architectures and if you've ever tried forcing an LLM to interact with strict mathematical systems!&lt;/p&gt;

&lt;p&gt;I'm Chisom, founder of Auvira Systems. We build sovereign software for founders.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>programming</category>
      <category>react</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
