Inspiration
I fell for networking back in polytechnic. A lot of people found subnetting and VLANs dry, but for me it just clicked, the idea that behind every website and every video call is this invisible chain of devices that all have to agree, and if a single link in that chain is misconfigured, the whole thing silently breaks. It was a puzzle with a right answer, and I loved chasing it. I carried that into university and kept going deeper, routing, firewalls, cloud networking, all of it.
But somewhere along the way I noticed a gap in how we were taught. We learned how to configure things — type the commands, build the lab. What nobody really trained was the part that actually matters on the job: a vague ticket lands, "users can't reach the server," and you have to hunt down the one thing that's wrong in a network that otherwise looks completely fine. That diagnostic instinct is the real skill, and there was no good way to practice it.
So I built the thing I wish I'd had as a student.
What it does
No Route to Host puts you in the on-call seat. You get a trouble ticket and a
broken network, and you investigate through a real vendor CLI — Cisco IOS,
FortiOS, AWS CLI, Linux iptables. You form a hypothesis, find the single
misconfiguration, fix it, and the game grades you on time and efficiency. Eleven
scenarios span switching, routing, VPN, AWS security groups, and OS-level host
firewalls.
The part I'm proudest of: Kiro plays every scenario before you ever see it. As I author each lab, Kiro drives the simulation itself through a self-built MCP server — loading the scenario, confirming the fault is really there, running the reference fix, and proving the ticket resolves. If a scenario is unsolvable, has an unintended shortcut, or its symptom doesn't match the fault, it fails loudly and won't ship. An AI that QA's its own training content.
Where the AI actually lives is worth being precise about: Kiro validates at authoring time, on my machine, through the MCP server. The game that ships to GitHub Pages is pure static files running the same engine — no AI and no backend at play time. The fairness guarantee is proven before anything ships, then re-enforced by a deterministic validator on every commit. AI in the dev loop; a deterministic guarantee in production.
How I built it
It's a TypeScript monorepo (npm workspaces) built around one idea: a single, pure simulation engine that everything else imports.
@nrth/engine— the core. Reachability isn't simulated packet forwarding; it's a deterministic chain of ordered conditions. A ping succeeds only if every condition holds:
$$ \text{reachable}(s, d) = \bigwedge_{i=1}^{7} C_i(s, d) $$
where the conditions are host IP config, access-VLAN path, trunk allowance, L3 routing, firewall policy, AWS security-group/NACL/route-table, and the OS host firewall. Each scenario breaks exactly one $C_i$, and the fix re-satisfies exactly that one. That structure is the whole reason Kiro can prove a scenario is fair — the solution space is finite and deterministic.
- React + Vite + xterm.js front-end — runs that same engine client-side, so the whole game is just static files on GitHub Pages. No backend to babysit.
- MCP server on the official SDK — a local (stdio) interface that lets Kiro drive the simulation while I author, exposing tools, resources, and prompts for loading, playing, and validating scenarios. It's the dev-time bridge between the AI and the engine — not part of the deployed game, and it doesn't need to be.
- One shared validator — the same
validateScenariocode runs in three places: the CI gate, an on-save hook (break a scenario, hit save, get instant feedback), and an in-browser Author Studio. Zero duplicated logic.
I planned the whole thing spec-first in .kiro/ requirements, design, tasks,
and steering rules before writing the real code.
Challenges I ran into
The hardest problem was making "fairness" mean something concrete. It's easy
to say a scenario is solvable; it's much harder to prove it and prove it
isn't accidentally solvable the wrong way. That's what pushed me toward the
constraint-chain model instead of real packet simulation. Because
$\text{reachable}(s,d)$ is a pure boolean function of state, Kiro can exhaustively
check each scenario and return one of four honest verdicts: already-solved,
unsolvable, symptom-mismatch, or unintended-solution.
The other real challenge was resisting duplicated logic. The game, the MCP server, the CI check, and the Author Studio all need the same engine and the moment they drift, the word "validated" stops meaning anything. Collapsing everything onto one shared engine and one shared validator took discipline, but it's what makes the guarantee trustworthy.
Accomplishments that I am proud of
- The AI validates the content, then the code guarantees it forever.
While authoring scenarios, Kiro drives the simulation through the MCP server
(following the rules in
.kiro/steering) to actually play each lab and confirm it's solvable and fair. That same check is codified in a deterministic validator that runs in CI on every push and in the on-save hook — so once a scenario passes, it can never silently break, whether or not the AI is in the loop. The AI proves it once; the code keeps it true. - One engine, four surfaces. The exact same
@nrth/enginepowers the browser game, the MCP server, the CI gate, and the on-save hook. Nothing can drift. - Zero-backend deploy. The whole thing runs client-side and lives on GitHub Pages — no server, no sessions, no runtime dependencies. Anyone can play it in one click.
- Breadth that stays honest. Layer-2 switching all the way up to AWS NACLs and Windows Firewall, and every scenario still reduces to breaking exactly one provable condition.
What I learned
Beyond any single framework, I learned how to turn a subject I love into
something other people can actually learn from. Going from "I understand
networking" to "I can build a tool that teaches the part of networking nobody
teaches" was a completely different kind of hard — and a far more satisfying one.
I also learned that determinism isn't just a nice engineering property here; it's
the entire foundation that lets an AI vouch for the content it ships. And working
spec-first in .kiro/ genuinely changed how I build — deciding what "correct"
means before writing code made the validation layer fall out naturally instead
of being bolted on.
How I Used Kiro
Challenge: Diagnostic networking labs are hard to author correctly. A scenario can be accidentally unsolvable, have an unintended shortcut, or describe a symptom that doesn't match the actual fault. Hand-verifying each one is slow and error-prone.
How Kiro solves it: Kiro is embedded in the authoring loop — not as a code assistant, but as a QA agent that plays the game to prove each scenario is fair.
Kiro features used:
Spec-driven development (
.kiro/specs/) — Requirements, design, and tasks written before code. Every task is checked off; the shipped code matches the spec exactly. This shaped the architecture: the constraint-chain reachability model fell out naturally from defining "what does solvable mean" in the spec.Self-built MCP server — 8 tools + 12 resources + 3 prompts expose the simulation engine to Kiro. The agent loads a scenario, confirms the fault is present, executes the reference solution, and proves the fix works — all through MCP tool calls.
Steering file (
.kiro/steering/networking-trainer.md,inclusion: always) — Encodes CLI grammar rules, fairness definitions (4 verdicts: already-solved, unsolvable, symptom-mismatch, unintended-solution), and agent behaviour boundaries (never edit engine source, never invent commands).On-save hook (
.kiro/hooks/on-save-validate.md) — Fires when a scenario file is saved. Runs the full validation gate instantly. Break a scenario → FAIL. Fix it → PASS. No broken lab ever ships.Validation agent (
.kiro/agents/scenario-validator.md) — Defines the multi-step flow: load → assert broken → execute fix → assert solved → check fairness.
How it shaped the build: The AI proves a scenario is fair once during authoring; then a deterministic validator (same engine, zero duplication) keeps it true forever in CI. AI in the dev loop; a deterministic guarantee in production.
What's next for No Route To Host
- A scenario editor for instructors — let teachers author labs in the browser with Kiro validating each one live, so a broken exercise can never reach a class.
- More domains — BGP, IPv6, DNS resolution, and TLS/certificate faults, each as a new provable condition in the chain.
- Adaptive difficulty — track which fault classes a player struggles with and serve the next ticket accordingly.
- Multiplayer incident mode — a shared outage where a team divides the network and races to find the fault together, the way a real on-call bridge works.
Built With
- docker
- github
- kiro
- mcp
- react
- typescript
- vite
- xterm.js
- yaml
Log in or sign up for Devpost to join the conversation.