<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Iyad</title>
    <description>The latest articles on DEV Community by Iyad (@ikdev103).</description>
    <link>https://dev.to/ikdev103</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4080158%2Fdbc9b729-e1e9-434f-b4d9-dabe4408e1c8.png</url>
      <title>DEV Community: Iyad</title>
      <link>https://dev.to/ikdev103</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ikdev103"/>
    <language>en</language>
    <item>
      <title>FetchQuest: Spec-Driven Dog Battling on Solana Devnet</title>
      <dc:creator>Iyad</dc:creator>
      <pubDate>Sun, 16 Aug 2026 18:51:51 +0000</pubDate>
      <link>https://dev.to/ikdev103/fetchquest-spec-driven-dog-battling-on-solana-devnet-4b4f</link>
      <guid>https://dev.to/ikdev103/fetchquest-spec-driven-dog-battling-on-solana-devnet-4b4f</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for &lt;a href="https://dev.to/challenges/weekend-2026-08-13"&gt;Weekend Challenge: Dog Days Edition&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FetchQuest&lt;/strong&gt; — 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.&lt;/p&gt;

&lt;p&gt;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 &lt;em&gt;good&lt;/em&gt;: satisfying reveals, real animation, sound that lands at the right moment. Polish over breadth.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/user-attachments/assets/21b6a8a7-e470-4e16-8623-4ead4e7a6236" rel="noopener noreferrer"&gt;https://github.com/user-attachments/assets/21b6a8a7-e470-4e16-8623-4ead4e7a6236&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/iyadalkentar/fetch-quest" rel="noopener noreferrer"&gt;https://github.com/iyadalkentar/fetch-quest&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;p&gt;I used &lt;strong&gt;spec-driven development&lt;/strong&gt; 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.&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Phase 0 — Scaffold:&lt;/strong&gt; Next.js (App Router) + TypeScript + Tailwind, single-page flow with generate → mint → fight → result as views/steps rather than separate routes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 1 — Generate a dog:&lt;/strong&gt; stat/personality roll logic, then &lt;code&gt;/api/generate-dog&lt;/code&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 2 — Mint it:&lt;/strong&gt; wallet connect via &lt;code&gt;@solana/wallet-adapter-react&lt;/code&gt; (Phantom/Solflare) on devnet, &lt;code&gt;/api/mint&lt;/code&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 3 — Fight:&lt;/strong&gt; deterministic battle resolution against a fixed raccoon opponent, built as an actual animated fight beat rather than an instant win/lose flash.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 4 — Hear the result:&lt;/strong&gt; 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Phase 5 — Polish pass:&lt;/strong&gt; walked the entire flow start to finish, tightened transitions between phases, and covered edge/error states (no wallet connected, insufficient devnet SOL, API failures).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;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 &lt;code&gt;/api/generate-dog&lt;/code&gt;, &lt;code&gt;/api/mint&lt;/code&gt;, and &lt;code&gt;/api/battle&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Solana&lt;/strong&gt; — 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.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Google AI&lt;/strong&gt; — Gemini generates each dog's portrait image and its bio/taunt line from its stats and personality, and later generates the battle result line.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs&lt;/strong&gt; — the battle result line is converted to speech and played on the result screen, so you &lt;em&gt;hear&lt;/em&gt; the outcome, not just read it.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devchallenge</category>
      <category>weekendchallenge</category>
    </item>
  </channel>
</rss>
