Jun 2026 – Current · Product, engineering, design
Live
KeepWinning — Global Stock Trend Screener
A Finviz-style chart-grid screener for ~5,700 global tickers at keepwinning.ai, with an agentic AI assistant that screens in plain language. Python data pipeline, Angular frontend, Supabase, Stripe billing, and zero-dependency Web Push.
- Angular 17
- TypeScript
- Python
- Claude API
- Supabase
- Stripe
- Vercel Functions
- PWA / Web Push
Last updated
Context
KeepWinning answers one workflow: market → stock trend → fundamentals, across global markets, in a single view. The whole exchange renders as a grid of candlestick charts — you filter for the trend shape you want instead of opening companies one by one, then an AI assistant does the screening for you in plain language.
Live: keepwinning.ai

Architecture
The system is deliberately split into a batch backend and a static frontend — there is no live price server to keep up:
- A Python pipeline runs after market close behind a swappable
DataSourceabstraction (yfinance, Börsdata), computes indicators, and emits static JSON — one market file, one screener file, per-ticker daily series. - The Angular 17 frontend (standalone components, signals,
OnPush) consumes those files from the CDN. Rendering ~5,700 SVG candlestick charts in one scrollable grid works because a single sharedIntersectionObservermounts and unmounts charts as cards enter the viewport, combined withcontent-visibility: auto.
The AI assistant
The assistant is agentic, not a chat wrapper: a serverless relay on Vercel streams Claude's responses over SSE, while tool execution happens client-side against the app's own services — the model asks to filter, compare, save a screen or set an alert, and the running Angular app performs it. Durable memory and an investor profile persist to Supabase, so the assistant remembers context across sessions. Quota and rate-limit middleware sit in front of the relay.
SaaS plumbing
- Supabase (Postgres + row-level security) for accounts, watchlists, saved screens, and alerts.
- Stripe for subscription billing with webhook-driven entitlements.
- A hand-rolled PWA push stack: Web Push implemented from RFC 8291/8292 directly on
node:crypto— zero dependencies, validated against the RFC test vectors — for trend-crossing alerts.

Takeaways
Pushing all market data to build-time JSON removed the hardest ops problem (a live quote service) and made the frontend's performance problem solvable with browser primitives instead of virtual-scroll libraries. The same static-first choice made the AI assistant tractable: with data on the client, tools run locally and the serverless layer only has to relay tokens and enforce quotas.