Inspiration

In a world where social media often rewards passive scrolling over real interaction, we wanted to build something that nudges people offline and into genuine, face-to-face connection. The SYNCS Hack 2026 theme — "how can technology help us find genuine connection in a world where tech isolates us?" — pushed us to ask: can an app use gamification to encourage real-world activities without turning people into content farms?

That's how Touch Grass was born: a mobile social activity challenge app that rewards scenery photos and mutual meetups, but with a strict consent-first design.

What it does

Touch Grass lets users join activity-based "challenge packs" (e.g. Hiking "Trail Blazer", Basketball "Game Day", Cultural Connect "Culture Crawl") and complete tasks for points:

  • Scenery photos: Capture a summit, plant, court, or public art piece.
  • Mutual connect meetups: Meet another user in person and complete a task together.

Critically, no flow can award points from a one-sided photo of a non-consenting person. All mutual-connect points require mutual opt-in: both users must actively confirm via QR code generate + scan + both-side confirmation before any points or photo are recorded.

How we built it

We built Touch Grass as a native Android app in Java, leveraging our team's existing Java fluency while learning Android-specific APIs over a 24-hour hackathon window.

Tech stack

  • Frontend: Native Android (Java), Android Studio, XML layouts
  • Camera: CameraX for photo capture
  • QR codes: ZXing for QR generation, ML Kit Barcode Scanning for QR scanning
  • Backend: Firebase (Auth, Firestore, Storage) via native Android SDKs
  • AI feature: Text-only icebreaker/caption generation via HTTP call (OkHttp/Retrofit) to a text-generation API, stored in Firestore

Data model (Firestore)

  • users: {displayName, points, activePacks[], pointsHidden}
  • challengePacks: {name, activityType, description}
  • tasks: {packId, type ('scenery_photo' | 'mutual_connect'), pointValue, name}
  • submissions: {userId, taskId, photoUrl, aiVerified, status, timestamp}
  • connections: {userA, userB, userAConfirmed, userBConfirmed, bothConfirmed, pointsAwarded}

We seeded three challenge packs (Hiking, Basketball, Cultural Connect) and focused our live demo on the Hiking pack.

Build order

Following a tight 24-hour plan, we prioritized:

  1. Firebase Auth working end-to-end
  2. Firestore data model + manually seeded packs
  3. Home screen reading real data
  4. Scenery photo submission flow (CameraX → Storage upload → Firestore doc)
  5. Mutual connect flow (QR generate/scan → both-confirm → points)
  6. AI text feature (icebreaker/caption)
  7. AI photo verification (lowest priority, cut if short on time)

Challenges we ran into

Learning Android-specific APIs

While fluent in Java, our team was new to Android-specific libraries like CameraX, Firebase Android SDKs, and ML Kit. Key hurdles included:

  • Understanding that everything Firebase is async (Task<T> callbacks) and ensuring UI updates happened on the main thread.
  • Binding CameraX correctly with lifecycle-aware bindToLifecycle() and handling runtime camera permissions.
  • Choosing between ZXing and ML Kit for QR scanning — we ultimately split responsibilities: ZXing for QR generation (simple bitmap creation) and ML Kit + CameraX for scanning (more reliable, offline, and lifecycle-friendly).

Mutual-connect flow complexity

The mutual opt-in design was our riskiest feature. We had to:

  • Generate a QR encoding a connections document ID.
  • Let the other user scan, confirm, and update the same document.
  • Use Firestore snapshot listeners on both devices to detect when bothConfirmed became true and award points.
  • Avoid race conditions where both users might scan simultaneously or listeners fire twice.

We manually tested this flow with two physical devices before building anything downstream.

Time management

With only 24 hours, we had to ruthlessly prioritize. Our original plan included AI photo verification and a Flybuys-style rewards conversion, but we cut both to ensure the core flows (auth, photo submission, mutual connect) were solid and demo-ready.

What we learned

  • Firebase as a full backend: We learned how Auth, Firestore, and Storage work together to replace a custom server for a prototype.
  • Android camera integration: CameraX is far more approachable than raw Camera2, but still requires careful lifecycle and permission handling.
  • Designing for consent: Building a gamified app that cannot exploit non-consenting people forced us to think deeply about privacy and ethics in social features.
  • Hackathon scoping: We learned to identify the minimum lovable product, cut features early, and focus on a polished end-to-end demo rather than half-built advanced features.

What's next for Touch Grass

If we had more time, we'd:

  • Move points-awarding logic into Cloud Functions for production security (currently client-writable for demo purposes).
  • Add AI photo verification to ensure submissions match task requirements.
  • Implement a points-hiding toggle and Flybuys-style rewards conversion.
  • Expand to iOS and add more challenge packs.

For now, Touch Grass proves that technology can be used not to isolate us, but to gently push us outside, into nature, into culture, and into real conversation — one mutual QR scan at a time.

Built With

Share this project:

Updates