DEV Community

Cover image for 🌿 TouchGrass β€” Go Outside. Take a Shot. Let Local AI Judge It.
Diwakar Arya
Diwakar Arya

Posted on Fully Autonomous

🌿 TouchGrass β€” Go Outside. Take a Shot. Let Local AI Judge It.

Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass Submission 🌿


This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass

🌿 TouchGrass β€” Go Outside. Take a Shot. Let Local AI Judge It.

What I Built

Most modern apps are designed around a single metric: maximizing screen time. They want your eyes glued to a feed, scrolling endlessly through algorithms engineered to keep you indoors.

TouchGrass does the exact opposite.

"The physical activity is the product. The web application is simply the game master."

TouchGrass is a timed, competitive outdoor photography challenge for groups of people (2–20 players). It encourages participants to:

  1. Set the stage: Choose a duration (e.g., 30 minutes) and pick a creative theme (or let local AI invent one).
  2. Put the phone in your pocket: Once the server-authoritative countdown begins, the screen goes into an ultra-minimal standby mode with one instruction: GO OUTSIDE. LOOK AROUND. TAKE YOUR SHOT.
  3. Explore the real world: Participants venture outside into parks, alleys, woods, or streets to find an authentic real-world scene fitting the challenge.
  4. Take exactly one shot: No infinite retakes or filtering sessions.
  5. Return and submit: When time expires, players return and upload their single capture.
  6. Anonymous AI Judging: A locally running multimodal AI model (llama.cpp + Gemma 3 Vision / LLaVA) scores each photograph blindly against a rigorous 100-point rubric.
  7. Interactive Reveal: Scores and rankings remain cryptographically locked server-side until the host triggers the celebratory reveal with podium rankings, animated confetti, and in-depth rubric breakdowns!

Demo

  • GitHub Repository: https://github.com/Diwakar38/TouchGrass
  • Instant Local Demo: Clone and run ./start.sh to launch both backend and frontend locally in seconds using the built-in deterministic Mock AI mode (0 model downloads required).
  • Docker Compose: docker compose up --build launches the full stack with persistent volume storage.

Code

🌿 TouchGrass β€” AI-Powered Real-World Photography Challenge

Go outside. Take a shot. Let local AI judge it.
A timed physical photography competition for Hacktoberfest 2026.

Java Spring Boot Next.js Database Inference License


🎯 What is TouchGrass?

TouchGrass is a timed photography competition for groups of people. A host creates a challenge, participants go outside to find and photograph something matching a physical theme, and a local multimodal AI model evaluates the photographs after everyone returns.

The entire product philosophy centers on one core principle:

The real-world activity is the product. The web application is simply the game master.

Most digital apps maximize screen time. TouchGrass does the opposite: it starts the timer, instructs everyone to put their phones in their pockets, and pushes them into the physical world.


πŸ”„ The Challenge Lifecycle

TouchGrass operates via a strict, server-authoritative state machine:

  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
  β”‚   SETUP   β”‚  Host picks 2–20 players & duration
  β””β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”˜
        β”‚
  β”Œβ”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”
  β”‚   READY
…

Tech Stack:

  • Frontend: Next.js 14, React 18, TypeScript, Tailwind CSS (Mobile-first, high outdoor contrast, prefers-reduced-motion compliance).
  • Backend: Java 21, Spring Boot 3.3, Spring Data JPA, Bean Validation.
  • Database: Single local SQLite database (jdbc:sqlite:./data/touchgrass.db) β€” zero bloated cloud databases or message brokers.
  • AI Runtime: llama.cpp OpenAI-compatible HTTP inference server.
  • Storage: Clean filesystem abstraction (LocalFileStorage) storing submissions under ./data/challenges/<id>/submissions/.

How I Built It

1. Open-Source AI & Local Inference

TouchGrass is built around local, open-weight multimodal vision models running on llama.cpp (such as Gemma 3 Vision or LLaVA 1.6).

Rather than hardcoding proprietary vendor SDKs, we designed an extensible Java abstraction:

public interface AiService {
    ChallengeTheme generateChallenge();
    ImageEvaluation evaluateImage(ChallengeTheme theme, String submissionId, ImageData image);
}
Enter fullscreen mode Exit fullscreen mode
  • LlamaCppAiService: Connects over HTTP to http://localhost:8081/v1/chat/completions, transmits photographs as base64 data URLs, and parses structured JSON responses. It includes retry policies, connection timeouts, and score bound sanitization.
  • MockAiService: A zero-download fallback that simulates realistic judging criteria, critiques, and themes. This enables developers and CI pipelines to test the entire application lifecycle instantly.

2. Externalized Prompt Templates & Structured Rubric

Instead of embedding prompts in code, templates live in backend/src/main/resources/prompts/:

  • theme-generation.txt: Generates evocative outdoor prompts (e.g., "Unexpected Geometry", "Something That Doesn't Belong") with field hints and difficulty ratings.
  • image-evaluation.txt: Instructs the vision model to score photos blindly out of 100 points across 7 weighted criteria:
    • Theme Relevance (25 pts)
    • Creativity / Interpretation (20 pts)
    • Composition (15 pts)
    • Visual Quality (15 pts)
    • Uniqueness (10 pts)
    • Story / Communication (10 pts)
    • Observation (5 pts)

Important Judging Philosophy: The AI judge does not evaluate whether a photo was taken on an expensive camera. A smartphone shot capturing an ingenious real-world moment will beat an uninspired shot from a $5,000 DSLR.

3. Server-Authoritative State Machine & Hidden Results

To guarantee competitive integrity:

  • Server Clock: startedAt and endsAt are computed on the backend. Client devices cannot cheat by spoofing their system clocks.
  • Server-Enforced Secrecy: GET /api/challenges/{id}/results returns 403 Forbidden until the host officially triggers POST /api/challenges/{id}/reveal. Scores and rankings cannot be inspected via browser developer tools or network tabs beforehand.

Why Does Open Innovation Matter?

  1. Complete Privacy for Real-World Photos: In a game that asks participants to photograph their immediate surroundings, neighborhoods, or friends, sending personal photos to closed corporate cloud APIs creates privacy concerns. With open-weight models running on local inference via llama.cpp, not a single byte leaves the host machine.
  2. Offline & Remote Capability: Physical photography challenges often happen in state parks, campsites, or remote trails where cell service is non-existent. Open-source local AI means TouchGrass can run entirely offline on a laptop or edge device with zero internet connection.
  3. Reproducibility & Customization: Closed proprietary APIs frequently change models, degrade reproducibility, and impose opaque rate limits or price tiers. With open-source models, the judging rubric, system prompts, and model weights remain completely under the host's control.

My Agent Session

This project was developed through pair-programming with Antigravity, Google DeepMind's advanced coding assistant. The agent helped architect the challenge state machine, build the Spring Boot SQLite JPA persistence layer, generate the Next.js mobile-first UI components, and create automated integration tests.


Prize Categories

  • Primary: Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
  • Best Use of Local Inference / Open-Weight Models (llama.cpp + Gemma multimodal)
  • Most Innovative Real-World Application (Screen-minimizing outdoor gameplay)

Top comments (1)

Collapse
 
koda2026 profile image
Harun - solo dev •

"the physical activity is the product. the web application is simply the game master."

bro, this philosophy is incredible. i’m 12, sitting in kunnathur for a family holiday, and i’ve been glued to my $150 phone shipping code all morning. your app is literally the reality check i needed to go outside today. πŸ˜‚

from an architecture side, running open-weight multimodal models locally via llama.cpp is a massive flex. sending personal photos of people's neighborhoods to closed cloud apis is a huge privacy risk, and you solved it with local inference.

also, building a MockAiService so devs can test the whole lifecycle without downloading massive model weights? genius for ci/cd.

huge respect for this hacktoberfest build. i'm putting my phone in my pocket and going to touch some actual grass now. 🌿🐯