ttushar.

Full-stack developer · 2026

Jurnii

An AI platform that drives real browser agents through customer journeys to score digital experience, plus a competitive intelligence product tracking promotions across the betting market. I owned the journey execution engine and the Customer 360 module.

TypeScriptLangGraphNext.jsHasuraPostgreSQL
Role
Full-stack developer
Ownership
Journey engine & Customer 360
Contribution
~600 commits on Customer 360 alone
Status
Live in production

The problem

What was broken

Customer experience consultants audit websites by hand: open the site, try to sign up, try to deposit, write down what went wrong, turn it into a slide deck. It takes days, costs a lot, and two consultants auditing the same site will disagree about half of it. Automating it with browser agents introduces a worse problem — a bad run looks exactly like a good one.

Audits that don't scale

Manual journey audits are slow, expensive and inconsistent — the deliverable is a consultant's recollection, not evidence, and it's stale before it's presented.

Agents that can't be trusted

Give an LLM a browser and it will do something: stop early and report success, spend six steps in a cookie banner, or describe a Cloudflare challenge as though it were the signup form. An assessment built on a bad execution renders exactly like one built on a good execution.

Competitive tracking by spreadsheet

Betting operators need to know what competitors are promoting right now. That information is public, changes daily, and was being collected by hand into a spreadsheet that was stale on arrival.

Data that's quietly wrong

The expensive defects never crash anything. Label text stored beside prices, casing splits in group-bys, classifiers structurally unable to return the right category — numbers that are subtly wrong in charts customers pay for.

The product

What I built

Jurnii sends AI agents through real browsers to audit digital experiences the way a customer meets them, and I owned two parts of the platform. The interaction graph is the execution engine: a LangGraph state machine that performs the browser automation, has a QA bot evaluate whether the run can be trusted, measures performance, captures and validates screenshot evidence, evaluates heuristics, and generates recommendations. Evidence capture is engineered down to the economics — which steps deserve a screenshot, and JPEG at 85 quality, because vision-model calls are priced on image size and thousands of journeys make that a real line item.

Customer 360 is a separate product on the same platform for the betting and gaming market: 52 database tables, 36 pipeline repository modules, and around 260 UI components tracking what every operator in the market is promoting, continuously. Scraped output flows through the diff engine into per-vertical detail tables — sports offers carry markets, casino offers carry games and providers, bingo carries rooms — surrounded by the machinery you only discover you need in production: currency conversion, supplier funding attribution, a fixtures knowledge base that ties an odds boost to the real match, and a human review queue.

Capabilities

Key features

Automated journey assessments

An AI agent drives a real browser through the journeys a customer would attempt — sign up, deposit, find help — and scores the experience against a heuristics database.

Evidence-first reporting

Every finding ships with screenshots of the actual failure, captured at the moments that matter. The report is proof, not recollection.

QA-verified executions

A separate evaluator reviews every run before it becomes an assessment, with bounded retries and human escalation — bad runs are caught before they become reports.

Recurring assessments against the delta

Sites change, so recurring runs compare against previous executions and generate recommendations from what actually changed, not the raw state.

Customer 360 market tracking

Continuous scraping of promotions, hero banners and odds boosts across betting brands, with per-vertical detail extraction, currency conversion, and a first-seen/last-seen timeline per offer.

Market intelligence views

Overview, per-brand breakdowns, live and boost feeds, a compare view, market richness trends and AI insights — all obeying one cascading filter from group down to individual sport.

Under the hood

How it's engineered

A QA loop that can go backwards

The LangGraph engine routes every execution through an evaluator that returns confidence, a continue/retry/stop decision, and feedback injected into the retry's prompt. Retries are capped at two and the cap is real — when it runs out, a human is paged rather than bad data proceeding. A confidence override stops the evaluator burning browser minutes on cosmetic complaints.

The diff engine

The heart of Customer 360 is deciding whether today's promotion card is yesterday's promotion. Wrong in one direction and every scrape invents duplicates; wrong in the other and genuinely new offers vanish into existing records. Dedup within a scrape, match against store, maintain the timeline.

Extraction measured, then fixed

Hero banner extraction was benchmarked against frozen captures, then fixed with carousel advancement, pagination-dot fallbacks and a viewport screenshot as a structure hint. Exact-count accuracy went from 21% to 76%, duplicates from 13.1% to 1.0% — and one brand is still wrong, which I'd rather write down than round off.

Five execution modes

The same graph runs full, automation-only, evaluation-only, skip-browser, or screenshot-verification — because debugging a reasoning node should not require driving a browser through a signup flow. It turned the feedback loop from tens of minutes into minutes.

Where it landed

Outcomes

Assessments that took consultant-days now run as automated journeys with screenshot evidence attached — and the QA loop means what ships as a report has been checked, not assumed. On Customer 360, operators see the market's promotions as a live, filterable product instead of a stale spreadsheet.

A large share of the value came from unglamorous correctness work. A data quality audit surfaced defects that never crashed anything: odds columns storing "Was" and "Now" as text, a casing collision silently splitting every group-by, and a classifier whose schema was generated from disabled categories — structurally incapable of returning baseball or MMA, misfiling about 1,800 boosts in a month until a one-line gating change fixed it, after the diagnosis was corrected. A production CPU mystery resolved the same way: not compute demand, but a missing concurrency declaration packing nearly all traffic onto two of three machines. What I'd do differently is written down too — build the execution modes on day one, and put data validation at the write boundary before the dashboards, because every one of those defects had been shipping into customer-facing charts for weeks before anyone questioned a number.