This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
For the Hacktoberfest Touch Grass challenge, I wanted to give people a reason to head outside, notice what is around them, and spend a little longer there. A photo can start that experience. Waiting for an AI response should not have to interrupt it.
Wildmon turns those photos into a nature discovery game. You can collect your own findings, take on an ecosystem checklist, or challenge a friend to find the same targets before time runs out. Gemma handles identification in the background. When you come back, there are discoveries to open, progress to review, and rewards for what you found.
Keeping the walk uninterrupted shaped both the interface and the architecture. The camera needs to be quick. The processing needs to survive a closed tab. The game needs to keep its own time.
Wildmon: take a fresh photo, look closer, and explore with friends.
There are two main ways to explore: Discovery mode starts with something you noticed; Ecosystem mode starts with something you want to find. Both feed into your collection and total XP.
A discovery can happen in the middle of an ordinary walk. Open quick capture, photograph one clear plant, bird, or insect, and submit it. There is no timer to start or checklist to commit to.
Take a picture, submit your finding, and carry on exploring.
Capture comes first. The screen asks for one clear organism and keeps the interaction short.
Once the upload is accepted, identification continues in the background. A valid, supported result earns discovery XP. An ambiguous image shows Uncertain identification, while a processing failure offers a retry. Those states give the user a clearer answer than leaving every unsuccessful photo at βprocessing.β
Every discovery has a detail page in the collection, where you can revisit the photo, identification, category, and awarded XP. This papaya was one of my real test results:
A papaya discovery worth 10 XP, alongside the focus bonus available during timed hunts.
Put your phone away and earn a focus bonus. During a timed hunt, take a photo, let Wildmon identify it, and spend time exploring with your phone tucked away. After at least one verified discovery, eligible time away from the app can earn 25 XP for 5 minutes, 60 XP for 10 minutes, or 100 XP for 20 minutes. This is an estimate of time away from Wildmon; the website cannot verify that the physical screen was off. The bonus belongs to timed hunts, while quick discoveries earn their usual discovery XP.
A retry works on the same discovery, with protection against duplicate XP.
An ecosystem is a timed solo challenge. Choose from Backyard Biodiversity, Urban Wildlife, Garden Life, Pollinator Path, or Birdwatch Trail, set a duration from one hour to seven days, and start your attempt.
For example, Urban Wildlife asks you to look for a tree, bird, plant, insect, and flowering plant. The checklist turns βgo for a walkβ into a set of things to notice.
Urban Wildlife before starting. The duration and checklist belong to a new timed attempt; earlier pack history stays separate.
Only new discoveries submitted through that ecosystem's capture flow count toward the attempt. Old photos from your collection cannot fill the checklist, and each verified photo fills at most one spot. Ecosystem discoveries also appear in the collection with an ecosystem tag.
You can finish early, or let the server deadline end the challenge automatically. Already accepted photos get a short verification grace period before the result becomes Completed, Partially completed, or Couldn't complete.
Completion adds a milestone bonus to total XP, once per attempt:
| Progress when the attempt settles | Ecosystem bonus |
|---|---|
| No matched targets | 0 XP |
| Some progress, below half | 50 XP |
| At least half, below full completion | 150 XP |
| Every checklist spot | 300 XP |
This gives ecosystems a beginning and an ending. You choose the outing, make progress with new observations, and receive a result based on what you actually submitted.
Add a friend, send a challenge invitation, and choose a shared target list. Targets can be supported species, broader categories such as a bird or plant, or visual traits such as a yellow flower.
Once the invitation is accepted, both players mark themselves Ready before the clock starts. The backend creates one shared start time and deadline, so neither player gets a head start from opening the page first.
Invite a friend β Accept β Both tap Ready
β
Shared clock starts
β
Each player photographs targets
β
Both finish, or the deadline arrives
β
Worker verifies β Winner or draw
A real two-account challenge after both players marked Ready. The recorded accounts had matching server start and deadline timestamps.
Each participant photographs their own targets and taps Done for now when finished. The worker settles the result after both finish or the deadline arrives, allowing identification to complete in the background. The shared clock gives the competition a clear boundary without requiring either player to keep watching it.
For competition beyond a single walk, the leaderboard has Global and Friends views, with weekly and all-time rankings. Global participation is opt-in, and the friends view uses accepted friendships.
The global weekly view. These are development accounts.
The same ranking system scoped to a friend circle.
Badges mark the smaller achievements along the way: your first discovery, category collections, challenge wins, and ecosystem progress. They give a new explorer something achievable to work toward before a leaderboard position matters.
First Discovery is earned here; the remaining badges show goals to work toward.
The walkthrough follows the discovery flow, ecosystem setup, friend challenge, leaderboards, and badges.
Wildmon is live at: wildmon.vercel.app
To try it, create an account and take one clear photo of a plant, bird, or insect. Start with a discovery; choose an ecosystem when you want a checklist for your next outing.
Repository: github.com/pradeept/wildmon
The project contains the Next.js frontend, FastAPI backend, independent worker, seed/index scripts, and an identification evaluation harness. The latest recorded checks include 38 passing API tests and a passing frontend production build. The README covers local setup and deployment; credentials stay in environment variables.
The backend had to support the promise in the interface: submit the photo and carry on. I separated accepting a discovery from identifying it, with a durable MongoDB job between the API and the worker.
Phone browser Β· Next.js on Vercel
β
βββ Request signed upload ββββββββββββΊ FastAPI on Render
βββ Upload photo βββββββββββββββββββββΊ Private object storage
βββ Submit discovery βββββββββββββββββΊ FastAPI
β
MongoDB Atlas
Discovery + queued job
β
Python worker on Render
β
Prepare the image
β
Gemma 4 Β· Google AI Studio
β β
Success Request failure
β βΌ
β Backboard Β· same Gemma model
β β
ββββββββββ¬βββββββββ
βΌ
Pydantic output validation
β
Supported-target matching
β
Save result + once-only XP
β
User returns to their discovery
Next.js, Tailwind CSS, and Radix UI handle the interface, with Geist typography, deep greens, and warm coral accents. The camera is easy to reach, and the navigation follows the main activities: explore, take an ecosystem challenge, revisit the collection, or meet friends. Leaderboards and badges sit together under Rewards.
FastAPI and Pydantic handle authentication, input validation, discovery state, and game rules. MongoDB Atlas stores the records, friendships, attempts, leased jobs, and XP ledger. The images live in private object storage, with signed uploads from the browser.
The Python worker on Render claims jobs, fetches and prepares images, calls Gemma, and saves results. It also finalizes expired activities and reconciles rewards independently of the browser. LangChain composes the prompt and inference call; Pydantic checks the structured answer before it reaches the game rules.
Running the API and worker as separate services matters here. The API can acknowledge a discovery while inference takes its time, and a challenge can expire even after both players have closed their tabs.
Large phone photos get special attention. Browser uploads target 2 MB, and the worker independently bounds the image sent to the model. That reduces payload and processing overhead. I have not established image size as the cause of the Google errors described below.
A frustrating blocker was right in the middle of Wildmon's core experience: identifying the photo someone had gone outside to take.
Google AI Studio accepted my key. The configured Gemma 4 31B model appeared in the model list, and a text-generation test worked. But image requests repeatedly failed with:
Gemma HTTP 500 INTERNAL: Internal error encountered.
A discovery could make it through capture and upload, only to fail at the step that gave it meaning. That affected the collection, ecosystem progress, and friend challengesβall of them depend on getting an identification back.
I checked the stages separately: credentials, model access, text generation, and image generation. I allowed more time for slow responses and added retries. The key worked, but image requests still hit server errors. The response did not tell me whether a quota was involved, and another retry could end in the same place.
Backboard came to the rescue. I added it as a fallback after a failed Google request, keeping the same Gemma model, image, and prompt. The worker could now try another route and receive a response instead of repeatedly stopping at Google's 500 error.
Once users could retry failed discoveries, βaward XP after identificationβ needed a precise boundary. The same job can run again, and two worker attempts can overlap around a lease expiry.
The reward ledger uses a unique discovery source key, and retrying transitions the existing job instead of creating another discovery. Ecosystem milestone rewards also have a once-only key. These safeguards matter because the collection, badges, and leaderboard all depend on the integrity of that score.
The same principle applies to matching: a model proposes an identification, then ordinary server code checks eligibility and assigns each photo to at most one target. The model does not set XP, start a timer, or choose a challenge winner.
While building, I tried to make testing convenient: drawings, then pictures displayed on my laptop screen. Gemma identified I'm not clicking real living organisms and complained! Eventually, I went outside and took actual photos.
The papaya and Golden Pothos findings made it through identification, into the collection, and into the XP total. Testing had made me do the thing I was building the app to encourage.
Open innovation made it possible for me to build Wildmon around an idea I cared about: helping people spend more time outside and notice the life around them. Having access to Gemma meant I could explore that idea without having to build an image-identification model myself.
Nature also makes this a project worth opening up. The plants and birds around my home will be different from those around someone else's. Other people could contribute local knowledge, suggest ecosystem challenges for their region, or point out a finding Wildmon got wrong. Those contributions could make the experience more useful in places I have never visited.
By sharing Wildmon's source, I hope to give others a starting point for their own outdoor experiencesβa nature activity for a classroom, a challenge for a walking group, or a way to explore a neighbourhood with friends. Someone should be able to take what I built, improve it, and make it meaningful where they live.
Wildmon uses Gemma for image interpretation, Backboard for fallback inference, MongoDB Atlas for durable records and jobs, and Render for the deployed API and worker.