Project archive

Full-stack and browser-native case studies

Detailed write-ups sourced from audited repositories — frontend architecture, API design, local runtimes, and deployment choices.

Full-stack PWALive

A production-oriented PWA demonstrating real-world product engineering: auth, RBAC, offline sync, reminders, testing, deployment, and observability.

Mobile-first PWA for logging newborn care events with multi-caregiver sync, offline outbox, and a FastAPI + MongoDB backend.

  • React
  • TypeScript
  • TanStack Router
  • FastAPI
  • +3 more
Problem

Caregivers need a fast phone-first way to log feeds, diapers, sleep, and health events—and share that timeline with partners without losing data when connectivity drops.

Frontend work
  • React 19 SPA with TanStack Router and 20+ file-based routes
  • IndexedDB offline outbox with sync-on-reconnect and client ID remapping
  • HttpOnly cookie auth client with CSRF headers and silent refresh
  • PWA install manifest, shortcuts, and service worker reminders
  • English/Hebrew i18n with RTL and voice log via Web Speech API
Backend & system work
  • FastAPI REST API with 25+ v1 route modules and OpenAPI docs
  • MongoDB repository layer with JWT cookie auth and owner/caregiver/viewer RBAC
  • Web Push reminders (VAPID) with secured external cron job endpoint
  • Production on AWS Lightsail: Docker Compose stack with Caddy reverse proxy/TLS, backend API, and Redis
  • Observability on the VPS: Prometheus, Loki/Promtail, Grafana, Node Exporter, and cAdvisor
  • GitHub Actions CI: pytest (70% coverage gate), Vitest, and Playwright E2E
Key decisions
  • HttpOnly cookie sessions instead of localStorage JWT storage
  • IndexedDB offline outbox for mutation queueing and ID remap after sync
  • Cloudflare Pages frontend with API on AWS Lightsail behind Caddy (ports 80/443 only)
  • External HTTP cron for reminder push dispatch in production
Challenges
  • Offline-first mutation queue with ordered flush and temporary ID remapping
  • Cross-origin cookie auth between Cloudflare Pages frontend and Lightsail-hosted API
  • Multi-caregiver invite flows with viewer read-only enforcement
Tech stack
Frontend
  • React 19
  • TypeScript
  • Vite
  • TanStack Router
  • TanStack Query
  • Tailwind CSS
  • Radix UI
  • i18next
  • vite-plugin-pwa
Backend
  • FastAPI
  • Motor
  • PyMongo
  • Celery
  • Redis
  • pywebpush
  • Resend
Data
  • MongoDB
  • IndexedDB
Infrastructure
  • Docker Compose
  • Cloudflare Pages
  • AWS Lightsail
  • Caddy
  • MongoDB Atlas
  • Prometheus
  • Grafana
  • Loki
  • GitHub Actions
Testing
  • Vitest
  • pytest
  • Playwright
Tooling
  • Bun
  • ESLint
  • Prettier
  • Ruff
Browser APIs
  • Web Speech API
  • Web Push
  • Service Worker
Local ML workspaceIn progress

Local image-generation lab combining a React studio UI, FastAPI GPU orchestration, canvas preprocessing, and typed multipart API flows.

Local Stable Diffusion workspace with a React dashboard, FastAPI orchestration, and a dedicated GPU subprocess for text-to-image and image-to-image generation.

  • React
  • TypeScript
  • FastAPI
  • Stable Diffusion
  • +3 more
Problem

Running image models locally means juggling checkpoints, Python environments, GPU diagnostics, and a usable UI. This project wraps that into one coordinated app.

Frontend work
  • React dashboard for generation, gallery, runtime diagnostics, and image-to-image editor
  • Canvas-based crop/color preprocessing plus server-side Pillow tool endpoints
  • Typed API client for JSON and multipart flows with Vitest component coverage
Backend & system work
  • FastAPI routes with subprocess `diffusers` runner in a dedicated model venv
  • Generation lock and CUDA OOM retry with smaller preset sizes
  • Optional API key, CORS origin checks, and upload validation for local-but-exposed use
  • Filesystem output storage under `outputs/generated`
Key decisions
  • Isolate GPU inference in a subprocess/venv so the API stays fast and testable
  • Allowlisted model IDs instead of arbitrary filesystem paths from the client
  • Split instant browser edits from heavier Pillow tools before image-to-image runs
Challenges
  • Orchestrating reliable local GPU pipelines across two Python environments and a web UI
  • Canvas mask retouch workflow with backend blur/median fill
  • Keeping frontend types aligned with Pydantic schemas across JSON and multipart routes
Tech stack
Frontend
  • React 19
  • TypeScript
  • Vite
  • Vitest
  • Testing Library
Backend
  • FastAPI
  • Uvicorn
  • Pydantic Settings
  • Pillow
Data
  • Local filesystem
Infrastructure
  • PowerShell dev scripts
Testing
  • Vitest
  • pytest
AI / ML
  • Stable Diffusion 1.5
  • diffusers
  • Realistic Vision checkpoint
Browser APIs
  • Canvas
  • Fetch
  • FormData
Links
Browser utilityLive

Browser hardware-control experiment using Web Bluetooth, serialized GATT commands, and accessible UI states.

Single-file browser app that pairs with generic BLE LED strips over Web Bluetooth—color, brightness, power, and multi-protocol debugging with no native app or backend.

  • Web Bluetooth
  • Petite-Vue
  • Tailwind CSS
  • iro.js
  • +2 more
Problem

Generic BLE LED strips often ship with closed or mobile-only vendor apps. This utility talks to compatible strips from Chromium on HTTPS with runtime protocol tuning.

Frontend work
  • Petite-Vue reactive UI with iro.js color wheel and responsive glassmorphism layout
  • Web Bluetooth pairing, GATT discovery, throttled writes, and serialized command chain
  • Pluggable protocol profiles, channel order, and debug panel with storage CRUD
  • Accessibility hooks: aria-live, aria-label, labeled inputs
Backend & system work
  • No backend — GitHub Actions CI with zero npm install static tests
  • GitHub Pages deploy publishes `src/` directly with no build step
Key decisions
  • Single HTML file with no build step for trivial static hosting and direct device control
  • Throttled and serialized BLE writes to avoid overlapping GATT operations
Challenges
  • Web Bluetooth requires HTTPS, user gesture, and Chromium — with clear unsupported-context warnings
  • Protocol fragmentation across command families, channel orders, and write modes
  • Characteristic discovery across many known service/characteristic pairs
Tech stack
Frontend
  • HTML5
  • Petite-Vue
  • Tailwind CSS (CDN)
  • iro.js
  • Font Awesome
Infrastructure
  • GitHub Pages
  • GitHub Actions
Testing
  • Node.js built-in test runner
Browser APIs
  • Web Bluetooth
  • localStorage
  • Clipboard API
Full-stack prediction markets UIIn progress

A Polymarket-style markets browser built on Next.js 16, wiring real Gamma/CLOB/Data API feeds through server caches into a Jotai + React Query frontend with WebSocket live prices and Recharts history.

Bolymarket is a Next.js 16 Polymarket-style prediction markets UI that proxies Polymarket’s Gamma, CLOB, and Data APIs through cached BFF routes, streams live outcome prices over WebSocket with simulation fallback, and splits structural data (React Query) from tick-level prices (Jotai).

  • Next.js
  • React
  • TypeScript
  • Tailwind CSS
  • +5 more

Bolymarket recreates Polymarket’s homepage and event-detail experience as a read-only Next.js app. Structural market data flows through TanStack Query (persisted to IndexedDB); live outcome probabilities update via Polymarket’s activity WebSocket into per-outcome Jotai atoms, with client-side simulation when the socket is unavailable.

Problem

Polymarket’s product surface is complex (category navigation, live odds, charts, sports, mobile chrome), and building a faithful read-only experience requires careful separation of static event data from high-frequency price updates without melting the React tree.

Frontend work
  • Built 7 App Router pages: /, /crypto, /sports, /sports/live, /politics, /event/[slug], /api-docs
  • Implemented Polymarket-faithful app chrome: TopBar, CategoryNav, Footer, MobileBottomNav, search toolbar
  • Split state: Jotai for filters/bookmarks/theme/live prices; TanStack React Query for events and chart history
  • Rendered BinaryCard, MultiOutcomeCard, SportsMatchCard, featured carousel, and category page layouts
  • Built event detail with Recharts PriceChart, timeframe toggles, related news, share/embed, visual OrderTicket
  • Wired live prices via shared livePriceEngineManager with leaf-only subscriptions and reduced-motion support
  • Styled with Tailwind CSS v4 semantic tokens, dark mode, and Motion for modal transitions
  • Added debounced client search, localStorage bookmarks, and URL-synced category navigation
Backend & system work
  • Implemented 7 Next.js BFF routes proxying Gamma, CLOB, Data API, sports live, and related news
  • Normalized all upstream responses with Zod schemas; thin route handlers delegate to lib/api modules
  • Added server-side caching with optional Redis (REDIS_URL) and in-memory fallback
  • Built GDELT news fetch with OkSurf fallback and 5-minute server cache
  • Published OpenAPI 3.0 spec at /api/openapi with Swagger UI at /api-docs
  • Configured Next.js image remotePatterns for Polymarket CDN assets
  • Deployed on Vercel (bun install --frozen-lockfile, bun run build); no CI workflow in repo
  • Env vars: REDIS_URL (optional), NEXT_PUBLIC_LIVE_PRICE_MODE (auto | websocket | simulation)
Key decisions
  • React Query for structural event data, Jotai atom families for live prices — prevents tick-driven query invalidation
  • BFF API routes instead of direct browser calls — centralizes validation, caching, and upstream shape handling
  • Polymarket activity WebSocket with 2s simulation fallback in auto mode — UX without full CLOB order book
  • Per-outcome outcomePriceAtomFamily with RAF coalescing — minimizes re-render scope on price ticks
  • Recharts fed by CLOB history with generateChartData simulated fallback when upstream is sparse
  • IndexedDB persistence for React Query via @tanstack/react-query-persist-client and idb-keyval
Challenges
  • High-frequency price updates without grid re-renders — Jotai leaf subscriptions, React.memo, documented profiler targets
  • WebSocket reliability — reconnect, ping, subscription index by event_slug, simulation engine fallback
  • Sports live complexity — separate sportsWebSocketEngine, game state atoms, league aggregation (phase in progress)
  • CLOB chart sparsity — merge logic plus simulated series; latest point synced to live atoms
  • Chrome fidelity vs. scope — many nav/footer links are visual-only placeholders
Tech stack
Frontend
  • Next.js 16.2.9
  • React 19.2.4
  • Tailwind CSS v4
  • Jotai ^2.20.1
  • TanStack React Query ^5.101.0
  • Recharts ^3.8.1
  • Motion ^12.40.0
  • Lucide React ^1.18.0
Backend
  • Next.js Route Handlers (BFF)
  • redis ^6.0.0 (optional)
Data
  • Polymarket Gamma REST API
  • Polymarket CLOB /prices-history
  • Polymarket Data API /trades
  • @polymarket/real-time-data-client ^1.4.0
  • Polymarket sports WebSocket
  • GDELT + OkSurf news
  • Zod ^4.4.3
  • idb-keyval ^6.2.5
Infrastructure
  • Vercel
  • Bun (recommended runtime)
  • Optional Redis (REDIS_URL)
Testing
  • Vitest ^4.1.9
  • React Testing Library ^16.3.2
  • jsdom ^29.1.1
  • 119 Vitest test files
Tooling
  • TypeScript ^5 (strict)
  • ESLint ^9 + eslint-config-next 16.2.9
  • Prettier ^3.8.4
Browser APIs
  • WebSocket
  • IndexedDB
  • localStorage
  • Web Share API
  • prefers-reduced-motion
  • requestAnimationFrame
Full-stack puzzle PWAIn progress

Water-sort gameplay combining animated liquid interactions and resilient local play with server-verified connected competition.

Mobile-first water-sort puzzle PWA combining animated gameplay and offline progression with a FastAPI backend for cloud sync, leaderboards, and realtime multiplayer.

  • React
  • TypeScript
  • TanStack Start
  • FastAPI
  • +6 more

Tubes separates deterministic puzzle mechanics from responsive SVG/CSS pouring animations and keeps its campaign playable offline. A separate FastAPI backend adds identity, cloud progression, daily challenges, leaderboards, social features, and WebSocket matches. Match settlement, progression consumers, and season rollover are implemented, but their production launchers are absent from the checked-in deployment configuration.

Problem

A touch-friendly water-sort game needs precise move rules, responsive liquid animations, and reliable progress even without connectivity. Connected competition also needs server-verified results and synchronized multiplayer state.

Frontend work
  • Deterministic pouring, undo, hints, fog-of-war, and win rules on a TanStack Store game model
  • Responsive SVG/CSS liquid animations with staged tilt, stream, fill, settle, and celebration effects
  • Local-first campaign progression with unlock rules, personal bests, resume state, and authenticated cloud merging
  • Typed REST client with Zod runtime validation, bearer authentication, token refresh, and WebSocket match state
  • Installable PWA with offline notices, reduced-motion interactions, Web Audio cues, haptic fallbacks, and Capacitor native-shell support
Backend & system work
  • Versioned FastAPI APIs for progress, daily challenges, leaderboards, profiles, social features, clubs, custom puzzles, and competitions
  • Server-authoritative puzzle and move-replay validation for campaign results and competitive matches
  • Redis-backed WebSocket rooms with reconnect tickets, presence, distributed locks, ordered commands, and duplicate-command protection
  • MongoDB repositories and indexes for identity, progression, ratings, match history, seasons, and shared content
  • Passwordless email, Google, and Apple authentication with signed access tokens and rotating opaque refresh tokens
  • Implemented Redis Stream consumers for match settlement and progression, plus season rollover; checked-in deployment configuration does not launch these workers
Key decisions
  • Keep campaign gameplay functional offline through a local catalog and locally persisted progression
  • Separate deterministic game mechanics from animated presentation, committing pours after animation completion
  • Use TanStack Start in static SPA mode for PWA delivery and Capacitor native-shell integration
  • Validate external data with Zod and verify competitive move sequences on the server
  • Use MongoDB for durable records and Redis for realtime coordination, locks, caching, and event streams
Challenges
  • Synchronizing liquid geometry, animation phases, input, audio, and authoritative move commits
  • Keeping the mobile board stable as browser chrome changes the visible viewport
  • Reconciling local and remote progression across level IDs, slugs, and independent move/time personal bests
  • Maintaining ordered, idempotent multiplayer commands across reconnects and coordinating MongoDB records with Redis Stream processing
Tech stack
Frontend
  • React 19
  • TypeScript 6
  • TanStack Start
  • TanStack Router
  • TanStack Query
  • TanStack Store
  • Vite 8
  • CSS custom properties
  • SVG animations
  • Zod
Backend
  • Python 3.14
  • FastAPI
  • Uvicorn
  • Pydantic Settings
  • PyJWT
  • HTTPX
  • Structlog
Data
  • MongoDB
  • PyMongo
  • Redis
  • Redis Streams
  • Redis Pub/Sub
  • localStorage
  • sessionStorage
Infrastructure
  • Cloudflare Pages
  • vite-plugin-pwa
  • Workbox
  • Capacitor 7
  • Docker
  • Docker Compose
  • Render Blueprint
  • Mailpit
  • SMTP
  • Resend
Testing
  • Vitest
  • Playwright
  • axe-core
  • pytest
  • pytest-asyncio
Tooling
  • ESLint
  • Prettier
  • Husky
  • Ruff
  • Mypy
Browser APIs
  • WebSocket
  • Web Audio
  • Vibration API
  • Visual Viewport API
  • Service Worker
  • Web App Manifest
  • matchMedia
Previous portfolioLive

Content-first portfolio SPA demonstrating schema-validated JSON pipelines, searchable case studies, visualization galleries, and static deployment with minimal serverless routing.

A React/TypeScript portfolio SPA for data analysis case studies, using Zod-validated JSON content, searchable project pages, visualization galleries, and a minimal Vercel serverless geo-block route.

  • React
  • TypeScript
  • Vite
  • Bun
  • +10 more

An earlier personal portfolio built to present data analysis case studies as structured, searchable content — static frontend, validated data pipeline, and one serverless route for geo IP checks.

Problem

I needed a portfolio for presenting data analysis work and project visualizations without running a CMS or database. Content stays in validated JSON, deploys as a static SPA, and only uses backend code where a server-side secret is required.

Frontend work
  • React 19 + TypeScript + Vite SPA with lazy-loaded routes
  • Theme UI design system with light/dark mode
  • Searchable and filterable project grid
  • Project detail pages with case-study structure and plot carousel
  • Static content pipeline using JSON, Zod schemas, and Vite asset resolution
  • Contact page with React Hook Form, Getform submission, clipboard copy, and resume download
  • SEO metadata with react-helmet-async, sitemap, robots, and Vercel Speed Insights
  • Accessibility details including skip link, reduced-motion styles, and ARIA feedback states
Backend & system work
  • Minimal Vercel serverless handler for GET /api/geo-block
  • Abstract API IP geolocation used server-side so the API key stays private
  • Vercel routing that sends /api/* to the serverless handler and the rest to the static frontend
  • Client-side Getform submission for contact messages
Key decisions
  • Used JSON + Zod instead of a CMS/database to keep content git-reviewable and statically deployable
  • Kept backend scope intentionally minimal — only serverless code where secrets must remain server-side
  • Used Zustand as a lightweight access layer over validated static content
  • Lazy-loaded routes and heavier UI pieces to keep the SPA structure cleaner
  • Used Vercel to deploy a static frontend and one serverless route from the same repo
Challenges
  • Keeping content integrity without a CMS
  • Resolving local asset references into Vite build output
  • Coordinating static frontend routing with a minimal serverless backend
  • Keeping Theme UI and React Bootstrap components visually consistent
  • Making geo-blocking fail open so the site still renders when the external API is unavailable
Tech stack
Frontend
  • React 19
  • TypeScript
  • Vite
  • React Router
  • Theme UI
  • React Bootstrap
  • Framer Motion
  • Zustand
  • Zod
  • React Hook Form
  • react-helmet-async
Backend
  • Vercel serverless Node handler
Data
  • Local JSON content files
Infrastructure
  • Vercel
  • Vercel Speed Insights
Tooling
  • Bun
  • TypeScript
  • Vite
Browser APIs
  • Clipboard API
  • fetch

Command palette

↑↓ navigate · Enter select · Esc close