If you’ve ever yelled at a portfolio tool that showed
0.00
for prices or made CSV import a hostage situation — come fix it with us.
I’m 22s, one of the folks behind Pocket Portfolio — an open-source, no-paywall investing dashboard. You can import a CSV → see clean live P/L → model trades in a Mock-Trade Lab that never touches real totals.
We’re small, fast, and friendly. Right now is the perfect moment to jump in: the architecture is set, the “why” is clear, and the issues are scoped for 30/60/90-minute wins.
App → https://www.pocketportfolio.app/app
Repo → https://github.com/PocketPortfolio/Financialprofilenetwork
Discord → link on the site
Why this is fun (and real)
- No paywalls, no dark UX. We ship clarity first.
- Edge-powered quotes with provider rotation and never-zero fallbacks.
- Import flow that actually helps: sample files + an error-CSV you can fix fast.
- Mock-Trade & Scenario Lab to model “what if” without touching real P/L.
If you like building explainable systems (numbers that tell you why they changed), you’ll feel at home.
The stack (and the shape of work)
- React + TypeScript (Vite), Tailwind, Testing Library/Playwright
- Edge functions (Vercel/Cloudflare), Fetch with timeouts/retries
- CSV pipeline (schema validation, normalizers, error envelopes)
- A11y: roles/ARIA, roving tabindex, keyboard shortcuts
We keep PRs small, tests close to the UI, and docs right in the code.
Good-first issues you can claim today
⏱ 30 minutes
- Add a broker CSV mapping (we’ll hand you a redacted row + schema).
- Improve focus ring + contrast tokens on the positions grid.
⏱ 60 minutes
- Playwright test: error-CSV → fix → success loop.
- Make the “mock trades active” chip announce to screen readers.
⏱ 90 minutes
- Lightweight telemetry counters on edge fallbacks (no PII, just counts).
- Keyboard:
?
shortcuts overlay (hotkeys + help link).
Comment /claim on the issue and we’ll pair if you want.
A tiny taste of the work
Client → edge price fallback (never show 0.00)
// edge/quote.ts (pseudo)
const providers = [
{ name: 'p1', url: env.P1, timeoutMs: 1400 },
{ name: 'p2', url: env.P2, timeoutMs: 1400 },
{ name: 'p3', url: env.P3, timeoutMs: 1600 },
];
export async function getQuote(sym: 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) continue;
const { price } = await r.json();
if (Number.isFinite(price)) return { price, src: p.name };
} catch {}
}
const last = await KV.get(`q:${sym}`); // last known good
return { price: last?.price ?? null, stale: true };
}
`
Import envelope
ts
type ImportRow = {
raw: Record<string,string>;
norm?: { sym: string; qty: number; price: number; ts: string };
err?: { code: 'PARSE'|'SCHEMA'|'MISSING'; hint: string };
};
What you’ll own (and learn)
- Designing fast, explainable UIs for numbers people care about
- Turning a11y into speed (keyboard-first flows)
- Shipping edge-aware logic with clear failure policies
- Writing tests that save users from rage-quitting
We give shout-outs in the app, PR credits, and a public trail of work you can point to.
How to start in 5 minutes
- ⭐ Star the repo.
- Pick any issue labeled
good first issue
or comment /claim under one of the ideas above. -
pnpm i && pnpm dev
(Vite) — we’ll help you get to your first diff quickly. - Open a PR with screenshots or a 10s GIF.
- We review fast; you ship the slice.
If you’ve read this far, you’re probably the kind of person we want to build with. Hop in now — this is the most interesting stage: small, sharp, and shipping.
— 22s
Founder, Pocket Portfolio
App • Repo • Discord (on the site)
Top comments (0)