PredictsWorld
Predict every World Cup 2026 match and compete with friends on live leaderboards.

I design, engineer and operate web applications, browser products, dashboards and automated systems, from the first problem to the live product.
Live web applications, browser products, a private spend analyser, a dashboard and an experiment. Each one carried from first problem to shipped product.
Predict every World Cup 2026 match and compete with friends on live leaderboards.


Autonomous options-trading system with real-time risk controls, multi-channel alerts, and a live dashboard.
A private, browser-only spend analyser for Indian bank statements.


Export an Adobe Launch container to Excel and audit it, entirely in-browser.
A zero-network Chrome extension that blurs sensitive on-screen data before you share your screen.
See which trackers are watching you on every website, and stop them instantly.
An animated, interactive proposal flow with a "No" button that refuses to be clicked.

End-to-end product development, from interface to infrastructure. Select a technology to see where it actually grows.
Select a technology to see which real projects it grows in.
How a product crosses from an idea to something that runs in production, and stays running.
Start from the real problem and the person who has it. Pin down the job to be done, the constraints, and what 'good' actually means before writing a line of code.
Design the data model, boundaries, and failure modes up front. Decide where state lives, what's authoritative, and how the system behaves when things go wrong.
Ship in typed, testable increments. Server-first where it belongs, interactive where it earns it, with automated tests guarding the logic that matters.
Deploy, monitor, and keep it running. Real traffic surfaces the hard bugs, connection pools, worker restarts, irregular data, and I own them end to end.
Real issues met under production load, kept as short journal entries: situation, cause, decision, result.
Under production traffic the app hit intermittent 500s and pages that loaded forever.
PostgreSQL connection-pool exhaustion against Supabase's transaction pooler (a hard 200-connection cap): the pooled postgres.js client was re-created per request instead of cached across warm serverless invocations, and postgres.js has no built-in wait-timeout, so a saturated pool made server components hang rather than fail.
Cache the pooled client across invocations, tune pool size and idle_timeout / connect_timeout, wrap hot-path DB calls in an application-level timeout, and add Next.js error boundaries.
Failures now surface as errors with a retry UI instead of infinite spinners, and the pool no longer exhausts under load.
Naive strike-selection could pick a strike that doesn't exist in the real option chain, or a stale contract with no active market.
Live option-chain data isn't uniformly spaced, some underlyings mix legacy corporate-action-adjusted strikes with the current grid at irregular intervals, so 'round to the nearest step' arithmetic breaks.
Select strikes from the broker's actual listed-strike data rather than assumed spacing, with a bounded, liveness-aware search that prefers a genuinely tradeable nearby strike over a numerically-closer illiquid one.
Falls back to an explicit 'no viable contract' state when nothing nearby is tradeable, so a bad chain is never silently misread as a good one.
On real bank PDFs, reprinted column headers, brought/carried-forward markers and a footer disclaimer's phone numbers were leaking into transactions, and one footer line became a phantom transaction that broke the running-balance chain.
PDF.js returns loosely positioned x/y text fragments, not tables, so rows and columns have to be reconstructed from coordinates, and page-break reprints and footer text sit in the same coordinate space as genuine rows.
Detect and skip header/footer/balance-forward rows, strip leaked ledger markers while preserving genuine leading-digit references, and reconcile each row's amount against the running balance to recover debit/credit direction.
Verified against a real five-page statement: four phantom rows removed and all balance-mismatch warnings cleared.
After a service-worker restart, Panic Mode could invert or screen-share protection could leave tabs permanently blurred.
MV3 service workers are unloaded and restarted at any time, silently resetting in-memory module state like 'is Panic currently on?'.
Move ephemeral cross-restart state into chrome.storage.session, make every disable path DOM-authoritative (always query and clear tracked elements), and add a monotonic generation counter to invalidate superseded async work.
A desynced flag can never leave a page stuck blurred, and racing profile apply/clear operations no longer clobber each other.
The popup could show 'no trackers' on a tab open for a while, even though the badge still showed a stale count.
MV3 service workers terminate after ~30 seconds of inactivity, wiping the in-memory Map that held per-tab detection state.
Serialize the per-tab set of tracker IDs into chrome.storage.session and rehydrate on read; and to make 'Stop' instant on already-running trackers, inject a MAIN-world script that swaps each tracker's live API functions for no-op proxies.
Detection state survives worker restarts within the session, and blocking takes effect immediately without a page reload.
Have a product in mind, something to build, or a question about one of these? Tell me a little and I'll write back.
astalcreates@gmail.com