
Building finance tools people actually trust: a practical playbook (from the Pocket Portfolio trenches)
I’m 22s, one of the folks behind Pocket Portfolio — an open-source, no-paywall investing dashboard where you can import a CSV -> get clean live P/L, and model trades in a Mock-Trade & Scenario Lab without touching real totals.
I’ve shipped and broken my fair share of features. This post is the short list of things that made a night-and-day difference for us — equal parts tech, product, and what’s next.
Use anything here in your own project. If you want to kick the tires, the app + repo are at the end.
1) Technical: design for “no 0.00s” (fallbacks that fail gracefully)
Finance UI dies when prices flicker to 0.00. Our rule: client -> edge fallbacks with light telemetry and circuit-breakers.
// edge/fallbackQuote.ts (pseudo)
const providers = [
{ name: 'p1', url: env.P1_URL, timeoutMs: 1400 },
{ name: 'p2', url: env.P2_URL, timeoutMs: 1400 },
{ name: 'p3', url: env.P3_URL, timeoutMs: 1600 },
];
export async function getQuote(sym: string) {
const errors: string[] = [];
for (const p of providers) {
try {
const ctl = new AbortController();
const t = setTimeout(() => ctl.abort(), p.timeoutMs);
const r = await fetch(`${p.url}/q?symbol=${sym}`, { signal: ctl.signal, cf: { cacheTtl: 10 }});
clearTimeout(t);
if (!r.ok) throw new Error(`${p.name}:${r.status}`);
const { price } = await r.json();
if (!isFinite(price)) throw new Error(`${p.name}:NaN`);
return { price, src: p.name };
} catch (e: any) {
errors.push(String(e.message));
// soft failover: keep trying; never return 0
}
}
// last resort: return "stale but not zero"
const cached = await KV.get(`q:${sym}`); // store last good
return { price: cached?.price ?? null, stale: true, errors };
}
````
Why it works
* Fast happy path from provider 1 with short TTL.
* Soft failover and never-zero fallback (last known good).
* Errors are counted, not logged to death.
---
## 2) Technical: CSV imports that don’t make people rage-quit
You will never have every broker format. Make it survivable:
```ts
type ImportRow = {
raw: Record<string, string>; // source columns intact
norm?: { sym: string; qty: number; price: number; ts: string };
err?: { code: 'PARSE'|'SCHEMA'|'MISSING'; hint: string };
};
UX rules that helped immediately
- Always show a sample file (eToro/Coinbase/Generic) and a Download error CSV when something fails.
- Ask users to paste one redacted row in an issue; ship the mapping the same day.
- Keep the import stateless — users can re-run safely.
3) Product: ship the “Are we sure?” layer
If you build tools that move money, people need a rehearsal. Our answer: a Mock-Trade & Scenario Lab that is:
- Instant: Add
TSLA +2 @ 260
with zero setup.
- Isolated: Mock totals never touch real P/L.
- Obvious: A big "mock trades active" chip, and a reset.
This one feature cut buyer’s remorse reports to near zero. Whatever you’re building, ask: What’s the one safe preview my user needs before a hard commit?
4) Business: one metric that punches above its weight
Time-to-first-insight (TTFI)
From first page load -> the moment a user sees something true about their portfolio. We track it like performance.
Things that reduce TTFI:
- Sample CSVs in the modal
- Default scenario ("add 1 share") with undo
- Fallback quotes (the “no 0.00s” rule)
If your TTFI is < 60 seconds, activation will feel different.
5) Next frontier (where we’re headed)
- Keyboard-first dashboards: a11y that doubles as speed. Arrow/Home/End for the grid;
M
opens Mock-Trade; ?
shows shortcuts.
- Explainers, not black boxes: when totals change, show why ("+2 TSLA @ 260 changed delta P/L +$48"). Debuggable numbers build trust.
- Local-first where it matters: scenarios and recent quotes cached on device; sensitive bits never have to round-trip.
If you’re exploring the same things, I’d love to swap notes.
What we’re building (and where to try it)
Pocket Portfolio is open-source and free to use:
Good first issues right now
- CSV mapping for a new broker format (drop one redacted row)
- Playwright test for the error-CSV -> fix -> success loop
- Light UI polish on the Mock-Trade modal
If you have thoughts on price fallbacks, import UX, or keyboard nav, hit me. I’ll review your project back — README, a11y, or a small PR.
— 22s
Founder, Pocket Portfolio
