A few months ago, I built a Zakat calculator for my family. It was supposed to be a weekend project. It turned into a lesson in privacy, performance, and what "free" actually costs.
The stack: React, Vite, Tailwind CSS, hosted on Netlify.
The twist: I decided early that this would be completely privacy-focused. No backend. No database. No analytics. No email capture.
Here's what that decision taught me.
Why Privacy-First Architecture Matters
Most Islamic finance apps I tested required:
Email signup
Phone number verification
Account creation just to calculate a number
Your Zakat calculation reveals your complete financial picture—bank balances, investments, gold holdings, debts. That's sensitive data.
I didn't want to store that. Ever.
Technical approach:
100% client-side JavaScript
localStorage for temporary calculation state (clears on page close)
No API calls after initial page load
No cookies, no tracking pixels, no Google Analytics
Trade-off? I can't "improve the product" with user data. No heatmaps, no A/B testing, no usage analytics.
Win? Users trust it. They actually use it.
The Gold Price Problem
Zakat depends on the Nisab threshold—87.48 grams of gold. Gold prices change daily. If I don't update this, calculations are wrong.
Solution: Simple fetch from a free gold price API on page load, cached for the session.
// Fetch current gold price for Nisab calculation
const fetchGoldPrice = async () => {
const response = await fetch('https://api.goldprice.com/v1/spot');
const data = await response.json();
return calculateNisab(data.price);
};
If the API fails, I fall back to the last known price with a clear warning. Better than a broken calculator.
Client-Side State Management (Without the Bloat)
I needed to track:
Multiple asset categories (cash, gold, silver, stocks, crypto, business assets)
Deductible liabilities
Real-time calculation updates
Currency conversion
No Redux. No Context API hell.
Just React hooks:
const [assets, setAssets] = useState({
cash: 0,
gold: 0,
silver: 0,
stocks: 0,
crypto: 0,
business: 0,
other: 0
});
const [liabilities, setLiabilities] = useState({
debts: 0,
bills: 0
});
Calculate Zakat in real-time with a simple useEffect:
const totalAssets = Object.values(assets).reduce((a, b) => a + b, 0);
const totalLiabilities = Object.values(liabilities).reduce((a, b) => a + b, 0);
const zakatableWealth = totalAssets - totalLiabilities;
const zakatDue = zakatableWealth > nisabThreshold ? zakatableWealth * 0.025 : 0;
Result: 0.53MB total page size. 0.1s server response. 95+ Lighthouse performance score.
The Form UX Challenge
Zakat calculation requires ~10 input fields. That's intimidating.
Solutions I implemented:
- Progressive disclosure
Collapse sections by default
Expand on click
Show running total prominently at top
- Help text everywhere
Gold (market value)
Include jewelry, coins, bars (exclude daily-wear per some scholars)
- Visual feedback
Color-coded totals (green = safe, red = error)
Real-time Zakat calculation updates as you type
Clear "You owe $X" result with explanation
Accessibility & Internationalization
Accessibility wins:
Proper label associations
Keyboard navigation for all inputs
ARIA labels where needed
Color contrast ratios checked
Internationalization challenges:
Auto-detect user currency via IP geolocation
Format numbers correctly (1,000 vs 1.000 depending on locale)
Support for 50+ currencies
The auto-detection isn't perfect (VPNs break it), so I added manual override. Users appreciate control.
What "Free" Actually Costs
Building this taught me about hidden costs:
Cost Amount Notes
Domain $0 Using Netlify subdomain
Hosting $0 Netlify free tier
SSL $0 Let's Encrypt auto
Gold API $0 Free tier (100 calls/day)
My time 40+ hours Development, testing, content
"Free" tools aren't free. They monetize your data. I chose to monetize nothing—just solve a problem.
The Result
ZakatEasy—a calculator that:
✅ Updates Nisab daily with live gold prices
✅ Handles all modern assets (stocks, crypto, business inventory)
✅ Works in 50+ currencies
✅ Calculates in real-time as you type
✅ Never stores or transmits your financial data
✅ Loads in under 1 second
Page stats:
Size: 0.53MB
Load time: 0.8s (desktop), 3.1s (mobile)
Performance score: 95/100
Accessibility score: 100/100
Lessons for Fellow Developers
Privacy is a feature, not a bug—market it as such
Client-side only is viable for many use cases
Simple state > complex architecture
Help text reduces support burden
Free tiers are generous if you're resource-conscious
Try It / Contribute
Live site: zakateasy.netlify.app
Got ideas? Want to improve the calculation logic? Add a feature?
The codebase is clean, documented, and open for contributions. Drop suggestions in the comments or fork it if you want to build something similar.
What's your experience building privacy-first web apps? Trade-offs I missed? Better approaches? Tell me in the comments.
Top comments (0)