DEV Community

Cover image for I Built an AI App That Wants You to Close It
Noorin S
Noorin S

Posted on

I Built an AI App That Wants You to Close It

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

Most AI apps are built to keep you talking. I wanted to build one whose success condition is the opposite: the best interaction with it is closing it.

OFFLINE is an expedition-map-style web app. You tell it how much time you have and what you need. A local Gemma model then writes you a short outdoor mission made of small, strange, sensory steps, and the app gets out of your way. Its last message is always the same:

You're done. Close OFFLINE.

What I Built

OFFLINE is an AI adventure guide designed to become unnecessary.

The flow takes about thirty seconds of screen time:

  1. Check in. Pick how long you have (15, 30, 60 or 90+ minutes) and what you need: clear my head, explore, move, be alone, or surprise me. Optionally say roughly where you are (city, park, village). There's no GPS and nothing is requested from your browser.
  2. Get a mission. Gemma writes the whole thing: a title like "The Quiet Corner", a one-line premise, 4 to 7 steps, a reflection question, and the closing line.
  3. Walk it. Your mission is drawn like a route on an old map, with a red X marking where you are. Each step asks for one concrete thing: "Turn toward the most interesting sound you can hear and walk a little way toward it."
  4. Put the phone down. Press the button and the screen turns into a bare night chart: one calm ring timer, the instruction, and nothing else. You come back for the next step only when you're ready.
  5. Close it. A one-line reflection, an ink stamp ("EXPEDITION COMPLETE"), and a button that says CLOSE OFFLINE.

Who it's for: anyone who opens their phone "for a second" and loses an hour, and anyone who wants a reason to walk somewhere familiar and notice it differently. It's for people who don't want a hiking app, a fitness tracker or another feed.

What it deliberately does not have: streaks, badges, points, accounts, history, notifications or a chat box. Every one of those would pull people back to the screen, which is the opposite of the point.

Code

OFFLINE

An AI adventure guide designed to become unnecessary.

Created by Noorin Sakhi.

Built for Hacktoberfest 2026, Challenge 2: Open-Source AI ("Touch Grass").

What OFFLINE is

You open the app, say how much time you have and what you need, and a local Gemma model writes you a short outdoor mission: a few sensory, non-optimized steps like "turn toward the most interesting sound you can hear." Then the app tells you to put your phone down. It reveals the next step only when you come back for it, and its last message is: "You're done. Close OFFLINE."

It is deliberately not a chatbot, a hiking planner, or a map app.

Why it exists

Most AI products are built to keep you talking to them. OFFLINE's success condition is the opposite: the best interaction with OFFLINE is closing OFFLINE. No feeds, streaks, badges, or accounts. The screen should be…

Run it in about five minutes (you need Python 3.10+, Node 20.19+ or 22.12+, and Ollama):

# 1. a Gemma model (any Gemma tag works)
ollama pull gemma3:1b            # small and fast; or a larger one if your machine can take it

# 2. backend
cd backend
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
OFFLINE_MODEL=gemma3:1b python3 -m uvicorn app.main:app --reload

# 3. frontend (new terminal)
cd frontend
npm install && npm run dev       # open http://localhost:5173
Enter fullscreen mode Exit fullscreen mode

No API keys, no accounts, no cloud. python3 -m app.cli --time 30 --need surprise generates a mission straight in the terminal if you want to test Gemma before the UI.

How I Built It

The stack

React + TypeScript + Vite  ->  FastAPI  ->  Ollama  ->  Gemma (open weights)
                                  |
              validate -> safety screen -> retry once -> hand-written fallback
Enter fullscreen mode Exit fullscreen mode

Gemma writes every mission. The app contains no mission templates for the main path. It sends Gemma a short check-in and asks for JSON that matches a schema, using Ollama's structured outputs. The hand-written missions exist only as a fallback, and the app tells you when you're seeing one.

Making Gemma interesting, not just correct

My first missions were safe and samey. "Take a deep breath and notice your surroundings" is not a quest. Three changes fixed most of it:

  • A voice. The system prompt casts Gemma as a quiet, slightly mysterious game master and bans clichés outright ("be present", "connect with nature", "embrace the moment").
  • A twist per step. Every step must ask for one concrete thing with a small rule that makes it feel like a game: "Follow the quietest direction for ten steps," not "Take a walk."
  • A random lens. Each request carries one of twelve lenses (sound, colour, age, edges, light and shadow, small things, texture, direction, stillness, signs of people, weather and air, looking up) that Gemma threads through the mission, so two requests rarely come out alike.
LENSES = [
    "sound: what you hear, where it comes from, what is just out of earshot",
    "age: things that were here long before you, and things that will outlast today",
    "edges: borders, corners, thresholds, where one place turns into another",
    # ...nine more
]
Enter fullscreen mode Exit fullscreen mode

Never trust a model you can't audit

A small local model will sometimes ignore instructions, and this app tells people to walk around outdoors, so I treat everything Gemma returns as untrusted input. Safety is three layers:

Layer What it does
Prompt Tells Gemma the rules: ordinary public places only; no trespassing, climbing, unsafe road crossings, approaching strangers, ignoring signs, being lost on purpose, special equipment, purchases, or after-dark activity.
Safety screen A deliberately blunt filter over every sentence. It blocks "Climb the fence" and "Open Google Maps," but lets "Do not search your phone for it" through.
Validator Enforces the design rules: 4 to 7 steps, at least two phone-down steps, durations that fit your time, and a final line that tells you to close the app.

If a mission fails, the backend retries once and tells Gemma exactly what was wrong ("step 3 has no instruction; durations add up to 41 minutes, more than the 30 available"). If it fails again, or Ollama is down, slow or missing the model, you get a hand-written mission that passes the same validator, with an honest notice explaining why. The app never pretends Gemma wrote something it didn't.

Things the tests caught

I wrote 30 backend tests and 15 browser tests. The backend tests run against a pretend Ollama server I can make misbehave on command: bad JSON, an unsafe mission, a slow reply, a missing model, or no server at all. That earned its keep:

  • My safety filter blocked my own fallback. It flagged "keep your phone in your pocket" as phone use. I narrowed the rule and added a regression test.
  • Screen-reader users had no heading on step 2 onward. My accessibility check caught it, and it's fixed.
  • A "pop-in" animation shrank buttons to 41px mid-animation and failed my 44px tap-target check. I dropped the scaling.

An honest note on what I did not measure: the automated tests use a stand-in model, so they prove the pipeline, not how good Gemma's missions are. That part I judged by running real missions myself (see the field test above).

The design journey

I redesigned the interface three times, and it's the part I learned the most from:

  1. A calm forest-green theme. It looked fine and felt like every other app, a slideshow of words you tap through.
  2. A bright, quirky sticker style. Too childish, and it still looked like an app.
  3. An expedition map. Parchment, contour lines, a compass whose needle swings and settles, a dotted route with a red X, and a night-chart "phone down" screen. The goal was a page that doesn't feel like it's on a device at all.

Accessibility and privacy by construction

Choices are real radio buttons (arrow keys work), headings take focus on every screen, tap targets are at least 44px, and all motion switches off under prefers-reduced-motion. Phone-down timers compare against the clock, so they stay correct when your screen sleeps. There are no cookies, no localStorage and no third-party requests, and a test asserts that the browser only ever talks to localhost.

Built with an AI pair-programmer

In the spirit of transparency: I built OFFLINE from a written build spec, using Claude as my coding partner in a long back-and-forth. I made the product calls, ran everything on my own machine, hit the real errors (a failed ollama pull, a model-name mismatch), and redirected the design when it wasn't right. The runtime has no closed dependency at all. The only AI inside the app is open-weight Gemma running locally.

Why Does Open Innovation Matter?

I built OFFLINE for people who are trying to spend less time with technology. A cloud API would quietly undercut that, and an open model fixes it in four ways:

  • Privacy is a fact, not a promise. The mission is written on your machine. There's no server to trust, no key to leak, and no log of when and why you wanted to get outside. The only context Gemma ever sees is "30 minutes, clear my head, a park."
  • No signal needed once you leave. The mission is generated before you go. After that, every step and timer lives in the page, and the app makes no network request again. You can walk out of Wi-Fi range with your mission in your pocket.
  • I could swap the model by changing one word. The model is a single environment variable (OFFLINE_MODEL). I could trade a tiny, fast Gemma for a larger, more creative one on the same laptop without touching code, and see the difference in the missions right away. A closed API would have chosen that trade-off for me.
  • It costs nothing to run. No per-mission fee, no rate limit, no billing page. An app meant to be opened for thirty seconds shouldn't come with a meter.

There's also a quieter reason. An app that treats model output as untrusted input is much easier to build when you control the model, the prompt, the sampling and the schema. I could tune the temperature, constrain the output shape and reproduce failures locally. For a project that sends people out the door, that control is a safety feature.

Prize Categories

  • Best Use of Gemma. Gemma runs locally via Ollama and writes every mission end to end: title, premise, steps, reflection and closing line. It's constrained with a JSON schema, steered by a voice and a rotating creative lens, validated and safety-screened, and swappable across Gemma sizes with one setting.

What's Next

OFFLINE is deliberately small, and I'd like to keep it that way. If I keep building, it would be:

  • Gentle context, kept ephemeral: optional daylight and weather so missions fit the hour, never stored.
  • A "found it" step type: missions that ask for something to spot, and read it back in the reflection.
  • Sound for the end of a timer: a soft chime, for people who put the phone in a pocket.
  • A real phone field test on cellular, away from the laptop.

Known limits: the safety screen is a keyword filter, not a guarantee. OFFLINE doesn't know your surroundings, so it can't verify any place exists. Small models vary from run to run, and it can't buzz you while your screen is locked.

Made by Noorin Sakhi, MIT licensed. If you try it, I'd love to hear what your mission was and what you noticed.

Top comments (0)