Antonio Queiroz — AI Solutions Architect · Lisbon

Complex systems that just work.

I design and ship AI-powered products end to end — model, data, infrastructure and interface — with a bias for boring technology, measured costs, and details people never have to think about.

01 — Selected work

Bolão Copa 2026

Live — archived after the final

A prediction league for the 2026 World Cup. Friends and family called the score of all 104 matches; a scoring engine settled the arguments.

Built as a single Cloudflare Worker: the React SPA ships as static assets, a Hono API handles auth, predictions and rankings, D1 holds the state and KV absorbs the traffic. During the tournament, scheduled jobs synced live results and news — retired now that the cup is over, the site stays up as a freeze-frame of the final table.

System — one worker serves the SPA, the API and the sync pipelines

BROWSER React 18 SPA predictions · rankings CLOUDFLARE WORKER STATIC ASSETS · SPA HONO API — /api/* sessions · scoring · rate limits 104 matches settled D1 — SQLITE users · matches · predictions KV cache · rate limiting SCHEDULED SYNC retired — july 2026 EXTERNAL FEEDS football-data.org · news RSS 01 app shell 02 /api json 03 sql 04 cache
104 matches scored 1 worker · 0 servers React 18 · Hono · TypeScript D1 + KV $0/month infra

Murdoku

Live — new cases published regularly

A competitive murder-mystery logic game, adapted from the puzzle book genre: read the clues, place every suspect on the floor plan, accuse the killer — faster than everyone else.

The heart of it is a constraint solver that proves every published case has exactly one solution before players ever see it. An admin builder composes rooms, furniture and structured clues that render as natural Portuguese sentences; players race a server-side clock with a single accusation each, solo or in teams, over an F1-style season leaderboard. Same calm architecture as the bolão: one Cloudflare Worker, D1, KV.

System — the solver gates publishing; the API guards the clock and the secret

BROWSER solving grid · builder one accusation, ever CLOUDFLARE WORKER STATIC ASSETS · SPA HONO API — /api/* server-side clock · one-shot accuse the killer never leaves the server D1 — SQLITE puzzles · plays · teams KV rate limiting CONSTRAINT SOLVER unique-solution proof at publish 01 app shell 02 gameplay 03 sql 04 limits 05 publish only if exactly one solution
13 clue types 1 accusation per case React 18 · Hono · TypeScript D1 + KV $0/month infra

Totoliga

Live — season 2026/27

A Totobola-style prediction game for the Portuguese league. Call 1X2 on every matchday; correct calls earn points and half a star — stars buy doubles and triples, just like the real coupon.

Matchdays in the Liga sprawl unpredictably across Friday-to-Monday, so there is no single deadline: every match locks server-side at its own kickoff. Hourly jobs rebuild the calendar from football-data.org — new rounds appear on their own, rescheduled games move themselves — and a 15-minute results pass only spends API calls when matches are actually hot. Same calm architecture: one Cloudflare Worker, D1, and an idempotent scoring engine an admin can always override by hand.

System — every match locks at its own kickoff; the sync loop keeps the calendar honest

BROWSER 1X2 coupon · standings doubles/triples · stars CLOUDFLARE WORKER STATIC ASSETS · SPA HONO API — /api/* per-match kickoff locks star ledger · idempotent scoring D1 — SQLITE players · rounds · matches predictions · stars no KV — friends-scale on purpose SCHEDULED SYNC hourly calendar · 15-min results FOOTBALL-DATA.ORG Primeira Liga feed — free tier 01 app shell 02 1X2 picks 03 sql 04 rebuild calendar · settle rounds 05 only when hot
34 matchdays · 1X2 3 pts + ½★ per hit doubles 1★ · triples 2★ React 18 · Hono · D1 $0/month infra

Kabum

Live — open a room, bring three friends

A four-player arena game in the spirit of the bomb-laying classics: blast crates, grab power-ups, trap your friends. Room codes, online multiplayer, bots that hold their own.

The whole simulation is one deterministic Rust crate — integer-only math, seeded RNG — compiled to WebAssembly and run twice. In the browser it powers offline practice; on Cloudflare it lives inside a Durable Object, one per room, ticking 20 times a second as the sole authority on every match: the sim itself validates each move, so a modified client can't cheat physics. State streams to players as compact binary snapshots over WebSockets; the canvas just interpolates and draws the neon.

System — one Rust sim, two runtimes: practice in the browser, authority in a Durable Object

04 input — [0x01, bits], only on change BROWSER canvas 2d · 60 fps lerp between snapshots input bitmask · bomb latch PRACTICE — offline local wasm sim vs bots CLOUDFLARE WORKER STATIC ASSETS · CLIENT MATCHMAKING — /api/* room code = durable object id DURABLE OBJECT KabumMatch — one per room authoritative wasm · 20 Hz validates every input · bots lobby · rematch · reconnection in-memory only — empty rooms simply evaporate KABUM-CORE — RUST → WASM deterministic · fixed-point · seeded RNG pure C ABI, no bindgen — 39 KB 01 app + wasm 02 room code 03 ws upgrade 05 snapshot — [0x02, ~500 B] · 20 Hz + lobby json one binary — practice mode and the server share the same physics
2–4 players · room codes Rust → wasm · one sim, two runtimes 20 ticks/s server authority 1 Durable Object per match $0/month infra

Letra a Letra

Live — one word, ten gallows

Hangman for a crowd: rooms of up to ten, one secret word, and a personal gallows per guesser. Wrong letters are yours alone — the word belongs to everyone.

After Kabum's Rust-and-wasm adventure, this one is deliberately boring tech doing a social job. The entire rulebook — turns, per-player gallows, the word-setter role the room's owner can assign and the setter can pass on, hint reveals, full-word risks, sit-outs, the persistent room scoreboard — is a single pure TypeScript state machine, shared verbatim by client and server and pinned down by thirty unit tests. A Durable Object per room wraps it with WebSockets and a 45-second turn clock, broadcasting personalized views: only the word's creator ever sees the secret, and accented letters match their plain keys, so CORAÇÃO yields to a C.

System — one pure state machine, wrapped by a Durable Object per room, one personalized view per player

04 actions — letter · word risk · hint · roles, json BROWSERS ×10 vanilla ts · no framework svg gallows · touch keys reconnect by player id one view per player — the setter sees the word CLOUDFLARE WORKER STATIC ASSETS · CLIENT ROOMS — /api/* room code = durable object id DURABLE OBJECT LetraRoom — one per room turn machine · 45 s clock roles: owner · word-setter a gallows each · scoreboard in-memory only — empty rooms simply evaporate SHARED CORE — PURE TS the whole rulebook · 30 unit tests accent-aware — Ç falls to C 01 app shell 02 room code 03 ws upgrade 05 state — personalized json, per player, on every move one module — the client and the room authority share the same rules, typed end to end
2–10 players · room codes a gallows each · one shared word 45 s turns · hints · word risks 1 Durable Object per room $0/month infra
02 — Next
006

In design — this page gets a new card when it ships.

007

In research.

03 — About

Good architecture is invisible — it's the part nobody has to think about.

I work across the stack: LLM systems and agents, APIs, data models and serverless infrastructure. I favor small, legible designs over fashionable complexity — pick pieces that won't wake anyone at 3 a.m., measure what they cost, and make the whole thing feel effortless. Currently exploring what production-grade AI products look like when they're built calm.

04 — Contact

Let's build something that just works.