Welcome to CoderLegion 22s

Leader posted 3 min read

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

0 votes
0 votes

More Posts

[DISCUSS] The “Never 0.00” Challenge — design a resilient price pipeline (client → edge) together

Pocket Portfolio - Sep 29

From Simplicity to Complexity: My Love-Hate Journey with Next.js

Sibasish Mohanty - Sep 9

How To Build A Dynamic Modal In Next.js

chukwuemeka Emmanuel - Apr 5

Learn how to integrate Firebase AI Logic into your iOS app.

Francesco - Jun 8

Hello World! Welcome to the React Dev Group!

James Dayal - Sep 25
chevron_left