the whole city recolours as you drag the pin · RAPTOR written from scratch · checked against brute-force oracles · English / 中文
// ai-built — Planned, written and tested largely by Claude Code agents (Anthropic’s coding agents) working as a team of builders and independent verifiers, directed and reviewed by Jun.
●reach.juncao.devnight · en
Reach shows everywhere you can get to by public transport in Melbourne and Victoria, door to door, for the day and time you choose. Drop or drag the pin and the whole city recolours in ten-minute bands. Underneath is a RAPTOR routing engine written from scratch over Transport Victoria’s full GTFS timetable. Around the map: journeys that explain themselves, arrive-by, the last tram home, a meeting point for up to five people, two homes compared, a whole day played back, and an algorithm theater. The engine is tested against independently written brute-force oracles, and the app is bilingual (English / 中文).
▸RAPTOR from scratch over the full feed: metro trains, trams, buses, V/Line trains and coaches, regional buses and SkyBus. The current timetable compiles to 28,692 stops and 376k trips in one checksummed binary file, which a pool of worker threads reads in place from a SharedArrayBuffer.
▸Fast enough to follow a drag: a one-to-all query (the earliest arrival at every stop) takes about 11 ms at p95 inside a worker on my i9-10900K, and live queries are latest-wins, so the map keeps up while the pin moves.
▸Checked, not assumed: 1,000 queries over the real timetable compare about 205 million labels with brute-force oracles that share no code with the engine (a naive scan of every trip, a time-expanded graph) and with a time-dependent Dijkstra baseline: 0 mismatches. There are also 19 fast-check properties over 12,900 generated cases and 24 golden journeys.
▸Journeys that explain themselves: the fastest option, any slower one that needs fewer rides, and walking, each with its legs, platforms and waits and a plain-language reason it is listed (sixteen kinds, from a tight change to a Night Network service). A “Best time to leave” chart covers every departure minute of the next two hours.
▸The map is a travel-time field drawn per pixel on the GPU: WebGL2 renders a cone for every reached stop into a depth buffer, so the depth test keeps the minimum, then shades ten-minute bands with analytic isolines. A self-test against the CPU runs before the GPU is trusted, and each new answer flows into place instead of jumping.
▸Eight modes in one app (Reach, Journey, Arrive by, Last tram home, Compare, Meet-up, Play the day and an algorithm theater that replays RAPTOR’s rounds beside a Dijkstra), Night and Paper themes, an interactive user guide and a recorded demo.
▸Release gates: Playwright end-to-end tests in Edge and Chrome, a pixel-level layout audit across both themes and languages at desktop, tablet and phone sizes, and a Proof page in the app with the full verification report and benchmarks.
▸Built in about ten days. A lead agent froze the contracts and split the work into tracks that each own their files; builder agents worked in parallel and separate verifier agents checked their work.
multi-model Bedrock rewriting · layout-preserving .docx edits · real page-limit enforcement · live on this domain
A full-stack AI studio that tailors a resume and cover letter to a specific job description — deployed right here at juncao.dev/resume-agent. Upload a .docx, paste the JD, pick a model (Claude or GPT-OSS via Amazon Bedrock), and it either regenerates polished markdown or rewrites your original document paragraph-by-paragraph at the OOXML level, so the layout you designed survives untouched. Entirely serverless — Lambda + DynamoDB + S3 behind this site's CloudFront — with per-user credit billing in AUD and an auth stack built from scratch.
▸Multi-model generation on Amazon Bedrock — Claude Haiku / Sonnet / Opus plus GPT-OSS — through one streaming runner with retries, model fallback, and effort-tiered extended-thinking budgets.
▸Keep-your-layout mode: the original .docx is segmented and edited in place at the OOXML level (runs, numbering, tables, hyperlinks preserved) — the model returns only per-paragraph changes, never a reformatted document.
▸Measured page-limit enforcement: output is rendered to PDF (headless Chromium / LibreOffice in a container Lambda), pages are counted, and the model gets up to two 'cut N lines' repair rounds until the document actually fits the limit your rules asked for.
▸Credit billing in AUD: reserve → settle ledger in DynamoDB with per-model token prices, cache read/write rates, and FX + markup from SSM — every run shows its real cost down to the micro-cent.
▸Auth from first principles: scrypt password hashing, ES256 JWTs, rotating refresh-token families with reuse detection, and lockout with exponential backoff.
▸Poll-based job pipeline built for Lambda's limits — async worker, DynamoDB event log with TTLs, heartbeat stall detection, idempotent billing settlement; inputs autosave and every generation lands in a 180-day S3 history.
▸Bilingual UI (English / 中文), a prompt preset library, and an AI assistant that proposes prompt updates via tool-use.
● architecture · ascii
+------------+ /resume-agent/* +------------+ async +------------+
| CloudFront |------------------>| API fn |---------->| Worker fn |
| juncao.dev | /api/* (strip) | Hono + JWT | | Bedrock |
+-----+------+ +-----+------+ +-----+------+
| | |
v v v
+------------+ +------------------+ +----------------+
| Web S3 | | DynamoDB | | Renderer fn |
| SPA bundle | | jobs · ledger · | | LibreOffice + |
+------------+ | events · history | | Chromium PDF |
+------------------+ +----------------+
the LeetCode 37 question I bombed in an interview, kept on the site as a reminder
Built this because I bombed the Sudoku Solver question (LeetCode 37) in an interview. It's a fully playable 9x9 sudoku game at three difficulties, but the real point is the second tool: an auto-solver that runs the same backtracking algorithm I should have written, animated cell-by-cell so you can watch it try, commit, and backtrack live. Also ships a hint tool that lists every legal digit for the cell you've selected (per row, column, and 3x3 box).
▸Random valid puzzle generation with rotational symmetry on cell removal — easy / medium / hard difficulties.
▸Hint tool: for the selected cell, lists every digit 1-9 that satisfies the row + column + 3x3 box rules right now.
15 built-in sorts · side-by-side compare · run your own algorithm in real CPython
Two-tab algorithm playground. Tab one ships 15 sorting algorithms (popularity-ordered) with bar-chart animation, live op-counters (compares / reads / writes / swaps), per-algorithm complexity badges, a 'how it works' write-up, and source code in Python / JavaScript / Java / C#. Tab two is a real-CPython sandbox where you write your own sort and the runtime tracks every operation.
▸15 sorting algorithms — Quick, Merge, Heap, Insertion, Selection, Bubble, Tim, Shell, Counting, Radix, Bucket, Comb, Cocktail, Gnome, Pancake — each with executable JS that emits a shared op-stream consumed by the visualizer.
▸Side-by-side compare mode: pick any two algorithms, run them on identical input, watch the difference in op counts.
▸User-code tab: real CPython via Pyodide (loaded in a Web Worker, lazy-init'd, ~10 MB first-load).
▸Modern editor (CodeMirror 6) with Python syntax highlighting, line numbers, autocomplete, and live `compile()`-based syntax checking.
▸Custom TrackedList Python class proxies the user's array — every read, write, and comparison drives the same animated bar chart.
▸15 test cases (incl. empty, single, sorted, reversed, all-equal, negatives, dupes, near-sorted, n=200 adversarial). Validates against sorted(input). All run output streams into a console panel.
▸Crude complexity bucketer: re-runs your algo at n = 50/100/200/400/800, fits ratios to log / linear / nlogn / quadratic / cubic models, displays the closest match.
TypeScriptReactCodeMirror 6Web WorkerPyodide (CPython in browser)
Scheduled price-watcher with email alerts and a plugin model
A self-hosted, extensible price monitor I built for myself. Tracks any number of products across multiple sites, runs on a schedule, and emails me the moment a price drops below a target I set. New sites are added by writing a tiny scraper plugin — no code changes elsewhere.
▸Add a watch in one CLI command or via a small web form: URL, target price, optional expiry.
▸Pluggable scraper interface — drop a `sites/<store>.py` file implementing `parse(html) -> price` and the scheduler picks it up.
▸Per-item cooldown so you don't get alert-spammed when a price hovers around the threshold.
▸Time-bound watches (e.g. 'remind me only until Black Friday') with a daily expiry sweeper.
▸Pluggable notifier: SMTP email by default, optional Telegram bot and webhook.
▸Runs anywhere: a single Docker container, or AWS Lambda + EventBridge for a free-tier serverless deploy.
▸DynamoDB / SQLite storage adapter — start local, graduate to cloud without code changes.
Serverless job portal with AI-powered recommendations
A serverless job portal supporting new immigrants in finding employment in Australia. Backend services on AWS Lambda + Python improved scalability, availability, and user experience.
▸Designed scalable backend architecture with AWS Lambda + API Gateway — low-cost and high availability.
▸Implemented an AI-based recommendation engine using vector search to improve job match accuracy.
▸Configured Route 53 + CloudFront to optimise routing and reduce latency.
Backend for the company's production legal AI system: a knowledge vector database with relevance-based document search, query routing, and result re-ranking. Powers the in-app legal Q&A assistant.
End-to-end form-fill, review, and e-lodgement pipeline
Owned and led the backend behind Visa Robot's flagship form-automation flow — collecting client data, automatically populating government PDF/HTML forms, routing through a review pipeline, and e-lodging once approved.
▸Domain-driven service split: intake, mapping, validation, review queue, e-lodgement.
▸Idempotent state machine for each application — survives Lambda timeouts and retries.
▸Audit log of every field mutation and reviewer decision.
▸Recognised internally with the CodeBlack Best Backend Engineer award after delivery.