This is a submission for Weekend Challenge: Dog Days Edition
What I Built
Every dog owner has had this moment: you get home late, or you eat something without sharing, and your dog gives you that look. Is My Dog Judging Me? exists to answer the question that look raises, with actual data.
Upload a photo of your dog, and Gemini Vision reads the expression and hands back a verdict: a judgment level from 0 to 100%, the dog's current emotional state, a sarcastic inner monologue in the dog's own "voice," a piece of advice for the owner, and a best-guess breed. It's a dumb premise on purpose — but I didn't want it to feel like a dumb build. The goal was a project I could point to as a working, deployed, genuinely usable app, not a local-only proof of concept.
Demo
🔗 Live: is-my-dog-judging-me.netlify.app
Code
bodikinf
/
is-my-dog-judging-me
Playful weekend project: upload a dog photo, Gemini Vision judges the look and delivers a sarcastic verdict. Built for Dev.to Weekend Challenge: Dog Days Edition.
Is My Dog Judging Me? 🐶
A playful weekend project: upload a photo of your dog, and Gemini Vision reveals exactly how disappointed they are in you.
Built for the Dev.to Weekend Challenge: Dog Days Edition.
🔗 Live demo: is-my-dog-judging-me.netlify.app
Screenshots
How it works
- You upload a photo of your dog.
- The photo is resized and re-encoded in your browser (this also strips EXIF/GPS metadata before it ever leaves your device).
- The photo is sent to a SvelteKit API route, which calls the Gemini Vision API with a structured JSON schema.
- Gemini returns a judgment level, an emotion, a sarcastic inner monologue, some advice, and a breed guess.
- The verdict is displayed with a bit of confetti and a sound effect.
Tech stack
- SvelteKit 5 (runes) + Tailwind CSS 4
-
Google Gemini API (
gemini-2.5-flash) for vision analysis, withresponseSchemafor reliable structured output - Upstash Redis…
How I Built It
The stack is SvelteKit 5 (using the new runes API) with Tailwind CSS 4, deployed to Netlify through @sveltejs/adapter-netlify.
The upload pipeline. When you pick a photo, it's drawn onto a canvas in the browser and re-exported as a compressed JPEG before it ever touches my server. This does two things at once: it keeps upload sizes small (faster response, lower bandwidth), and it strips EXIF metadata in the process — including GPS coordinates a phone might have embedded in the original file. I didn't want to be the guy who casually leaks someone's home address through a joke app.
The Gemini call. The compressed image is sent to a SvelteKit API route (/api/judge), which calls gemini-2.5-flash with a responseSchema attached to the request. Instead of asking the model for JSON and hoping the output parses cleanly, the schema guarantees a structured response every time — no regex, no "strip the markdown fences," no silent parsing failures. That one decision saved me a lot of defensive code.
Making it something people can actually hit. Since I want this app to keep running after the weekend, I didn't reach for an in-memory rate limiter that resets on every cold start. I used Upstash Redis with a sliding-window limiter (5 requests/hour per IP) instead — cheap, serverless-friendly, and it survives redeploys. There's also file-size/type validation, a request timeout on the Gemini call, and a proper error state on the frontend if the AI service hiccups.
Being upfront about the data. Because this app touches photos and sends them to a third-party AI, I wrote an actual Privacy Policy page explaining what happens: no accounts, no photo storage, no tracking, and a plain explanation of what Gemini and Upstash each see. It felt like the right thing to ship, not an afterthought.
The fun part. The verdict card triggers canvas-confetti (intensity scales with how harsh the judgment is), plays a short sound effect, and sits over a subtle paw-print background pattern — small touches, but they make the moment of "reveal" feel finished rather than abrupt.
Prize Categories
Submitting to Best use of Google AI — Gemini Vision's image analysis, paired with responseSchema for reliable structured output, is the actual core of the app, not a bolt-on feature.
What's Next
Right now the UI is English-only, but the verdict text can already be generated in the user's browser language (navigator.language gets passed straight into the prompt) — wiring that up fully is the next small step.
Longer-term, this project is a stepping stone toward something more ambitious I'm working on: an app that matches people with real adoptable shelter dogs based on their actual lifestyle — apartment or house, activity level, kids — pulling from open shelter databases. This weekend was a good excuse to get comfortable with Gemini's vision capabilities before building that.


Top comments (0)