DEV Community

Iyad
Iyad

Posted on

FetchQuest: Spec-Driven Dog Battling on Solana Devnet

DEV Weekend Challenge: Dog Days Edition Submission 🐕

This is a submission for Weekend Challenge: Dog Days Edition

What I Built

FetchQuest — a tiny dog-vs-raccoon battler. You generate a dog with random stats (Speed, Bark, Chomp) and a personality tag, watch it come to life with an AI-drawn portrait and a bio/taunt line, mint it as a real NFT on Solana devnet, send it into a single fight against a fixed raccoon opponent, and hear the outcome narrated out loud.

The scope was intentionally narrow: one dog, one fight, one result — no roster, no PvP, no multi-round battles. The goal wasn't to cram in as many integrations as possible, it was to make each step of that short loop feel good: satisfying reveals, real animation, sound that lands at the right moment. Polish over breadth.

Demo

https://github.com/user-attachments/assets/21b6a8a7-e470-4e16-8623-4ead4e7a6236

Code

https://github.com/iyadalkentar/fetch-quest

How I Built It

I used spec-driven development for this one instead of just diving into code — before writing anything I wrote out a mission spec, a tech-stack spec, and a phased roadmap, and worked from those throughout the weekend rather than improvising as I went.

The mission spec set one non-negotiable rule: if a trade-off ever came up between "add another feature" and "make the existing steps feel better," the existing steps won. That shaped almost every decision below.

The roadmap was sequenced as vertical slices — each phase took one step of the core loop fully end-to-end (UI + API route + its own polish pass) before moving to the next, rather than building all the plumbing first and polishing at the end:

  • Phase 0 — Scaffold: Next.js (App Router) + TypeScript + Tailwind, single-page flow with generate → mint → fight → result as views/steps rather than separate routes.
  • Phase 1 — Generate a dog: stat/personality roll logic, then /api/generate-dog calling Google AI (Gemini) for a portrait and a bio/taunt line based on the rolled stats and personality, with an animated reveal on the frontend.
  • Phase 2 — Mint it: wallet connect via @solana/wallet-adapter-react (Phantom/Solflare) on devnet, /api/mint using Metaplex to mint the generated portrait plus stats/personality as on-chain metadata attributes, with pending/confirming/minted states and a link out to Solana Explorer.
  • Phase 3 — Fight: deterministic battle resolution against a fixed raccoon opponent, built as an actual animated fight beat rather than an instant win/lose flash.
  • Phase 4 — Hear the result: Google AI generates a result line describing the outcome, ElevenLabs turns it into narration audio played on the result screen alongside the portrait and outcome badge.
  • Phase 5 — Polish pass: walked the entire flow start to finish, tightened transitions between phases, and covered edge/error states (no wallet connected, insufficient devnet SOL, API failures).

All third-party API keys (Google AI, ElevenLabs, the Solana minting authority) stay server-side in Next.js API routes — the client never sees them and only ever calls /api/generate-dog, /api/mint, and /api/battle.

Prize Categories

  • Best Use of Solana — every generated dog is minted as a real NFT on Solana devnet, with its portrait and stats/personality stored as on-chain metadata attributes via Metaplex.
  • Best Use of Google AI — Gemini generates each dog's portrait image and its bio/taunt line from its stats and personality, and later generates the battle result line.
  • Best Use of ElevenLabs — the battle result line is converted to speech and played on the result screen, so you hear the outcome, not just read it.

Top comments (0)