DEV Community

Cover image for Walk Cue: one card, one walk, then close the tab
Joshua Warren
Joshua Warren

Posted on

Walk Cue: one card, one walk, then close the tab

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

Most apps that want to get you outside still want you to stay in the app first. Sign up, set goals, grant location, pick a route, check your streak. By the time you've finished setting up the walk, the light's gone.

I wanted the opposite. Type where you are, get one answer, put the phone down. That's Walk Cue.

What I Built

Walk Cue is a single card. You type a city or a ZIP code. It looks at the current weather and the time of day and gives you one cue:

  • How long to go, from 8 to 40 minutes
  • What kind of walk, in a few words like "brisk out-and-back" or "short lit loop"
  • Why now, in one sentence tied to the conditions you're actually in

Under that, it lists up to three named parks, gardens, or nature reserves nearby, with distances in miles, when a map search turns any up.

There's no account and no feed. It doesn't track your walks. The server doesn't save the area you typed. The browser remembers your last one on that machine so the next open goes straight to a cue. It's for anyone who knows they should step outside and doesn't want to plan it. The page is meant to be the shortest part of going outside.

Demo

Here's a card written by a local open-weight model for Austin at midday, 86°F and clear:

Walk Cue live mode: Austin, 86°F, cue written by a local Qwen model

It picked 15 minutes, called it a "quick shady stroll," and pointed at the pocket park with tree cover a mile away. That's the job: read the heat, keep it short, name somewhere real.

Same app, different model. This one is Gemma 3 (the 4B build) through Ollama, for Sydney late in the afternoon, 68°F with a light breeze:

Walk Cue live mode: Sydney, 68°F, cue written by Gemma 3 through Ollama

Gemma went longer, 25 minutes, and kept the line short. The parks underneath come from the map search, not the model, so all three are real places under a mile and a quarter away.

The same card in mock mode, using the Anytown placeholder:

Walk Cue card, Anytown mock mode

Lisbon, with live weather and real parks:

Walk Cue card, Lisbon live weather and parks

And what you see when the model doesn't answer:

Walk Cue fallback when the local model does not answer

Code

GitHub logo joshuaswarren / walk-cue

Local open-weight walk cue: weather + time → short outdoor walk. Hacktoberfest DEV Week 1 Touch Grass.

Walk Cue

Sponsor

One card. A short walk. Then you leave.

Anytown walk cue card

Type a city or ZIP code. Walk Cue reads the weather and the hour, then gives you a single cue: how long, what kind of walk, and why this moment is the one. A few nearby parks show up when a map search answers. Temperatures are in °F. Distances are in miles, or feet when a spot is under a tenth of a mile. The page is supposed to be the short part of going outside.

Run

Python 3.11 or newer. No API keys.

python3 -m pip install -r requirements.txt && python3 -m walkcue
Enter fullscreen mode Exit fullscreen mode

Open http://127.0.0.1:8000.

A virtualenv is the cleaner version of the same thing:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python -m walkcue
Enter fullscreen mode Exit fullscreen mode

Mock mode is the default. Type a real city, or type Anytown for a fictional placeholder that skips…

MIT licensed. Python 3.11 or newer, no API keys:

python3 -m pip install -r requirements.txt && python3 -m walkcue
Enter fullscreen mode Exit fullscreen mode

Open http://127.0.0.1:8000. Mock mode is the default. Type a real city, or type Anytown, a fictional placeholder that skips geocoding and map search. It uses your clock, a fixed mild forecast, and three sample spots so you can try the card with nothing else configured.

To have a local model write the cue with Ollama and Gemma:

ollama pull gemma3
ollama serve
Enter fullscreen mode Exit fullscreen mode

Then in .env:

WALK_CUE_LLM_MODE=live
WALK_CUE_LLM_BASE_URL=http://127.0.0.1:11434/v1
WALK_CUE_LLM_MODEL=gemma3
Enter fullscreen mode Exit fullscreen mode

Restart python3 -m walkcue. Live mode is opt-in on purpose: a base URL alone does nothing while the mode is mock, so a fresh clone never sits waiting on a model that isn't running.

If you set WALK_CUE_HOST=0.0.0.0, a phone on the same network can open the card. That's where it works best: on the phone by the door, not on a laptop.

How I Built It

The cue is small on purpose

You don't need a lot of advice to take a walk. What helps is a reasonable plan you can start right now. So the cue changes with conditions, not with how much you've used the app:

  • Thunderstorm: 8 minutes, close by, turn back if it opens up.
  • Rain: 12 minutes near cover.
  • After dark: about 15 minutes on lit streets. Night wins even when it's also cold or windy, because lighting matters more after dark.
  • Clear sky in the early morning or evening: 30 minutes. That's the "golden" case, when the light is low and it's worth staying out longer.
  • Hot, cold, windy, and gray days each get their own length and tone.

Here's a real line from the offline writer for a rainy hour: "Rain is falling, so make it twelve minutes and stay near cover." That's about all the reading I want the card to ask for.

A request, start to finish

  1. Open-Meteo turns the city or ZIP code into coordinates, then its forecast API returns current conditions. No keys.
  2. Overpass searches about two miles out for named parks, gardens, and nature reserves. If Overpass fails, Nominatim gets one bounded search. If that fails too, you still get a walk with no park list.
  3. The local model or the offline writer writes the cue.

The card shows temperatures in °F and distances in miles, or feet when a spot is under a tenth of a mile.

The offline writer is the default, and it's deterministic: same weather and same hour give the same text. It sorts conditions into a small set of buckets (storm, rain, snow, hot, cold, wind, night, golden, gray, fair). Each bucket has a set duration and a few phrasings. There's no randomness, which makes it easy to test, and the app is useful before you install anything else.

Live mode

Live mode sends the model a short prompt with the area, local time, weather summary, and nearby spots. The system prompt asks for JSON only (duration_minutes, vibe, why_now) and sets a few rules: don't invent places it wasn't given, no emoji, no hashtags, no pep talk. Then the reply gets checked before it reaches the card:

  • Code fences get stripped. The first JSON object gets pulled out.
  • Duration gets clamped to 8 to 40 minutes.
  • The vibe gets trimmed and lowercased. The "why" gets capped in length and has to be a real sentence.
  • If anything's missing or unparseable, the reply is thrown out.

It talks to anything that serves POST /v1/chat/completions: Ollama, LM Studio, llama-server. The Sydney card above came from Gemma 3 4B on Ollama, which is the setup in the README. The Austin card came from Qwen 3.8 27B on llama-server. Qwen3 chat templates think first by default, and on llama-server that left content empty with the whole reply sitting in reasoning_content. Walk Cue now sends chat_template_kwargs: {"enable_thinking": false} with every request, and reads reasoning_content if content still comes back blank.

If the server is down, times out, or returns something unusable, the card shows the offline cue with a plain notice: "The model didn't answer, so this is the offline cue." You never get a spinner that ends in nothing. A local model is a nice upgrade, but it should never be the reason someone doesn't go outside.

The stack is small: FastAPI, Uvicorn, and httpx on the backend, plain HTML/CSS/JS on the front, and pytest for the phrasing and API behavior, including the fallback path.

Why Does Open Innovation Matter?

A walk prompt doesn't need a frontier model behind a paid API. It needs to read three facts (place, time, weather) plus a short list of parks and write one good sentence. A small open-weight model on your own machine is enough for that.

Running it locally also fits what the app is for:

  • Your location stays with you for the writing step. In live mode the prompt goes to a model on your own computer, not a third-party API. The area, the hour, and the parks nearby don't leave your machine to get the sentence written.
  • There's no key and no meter. Nobody gets a bill because they took a walk. Open-Meteo doesn't need a key for weather or geocoding either, so the whole thing runs with zero credentials.
  • You can swap the model whenever you want. Because it speaks the OpenAI-compatible chat API, switching between Gemma and Qwen is a config change. Qwen needed one extra request flag for its thinking template. Gemma needed nothing.
  • It still works when the model doesn't, and that one matters most to me. The offline writer is always there.

What I'd improve next

  • Daylight awareness. Right now "night" comes from the forecast's day/night flag and the clock. I'd like a cue that knows sunset is in 25 minutes and says so.
  • Better park ranking. Distance is a blunt way to sort. A pocket park 1,000 feet away isn't always better than a real trail three-quarters of a mile out when you have 30 minutes.
  • Accessibility-aware cues: an option for flat routes, benches, or shorter loops, without turning the card into a settings page.
  • A home-screen shortcut. I'd make it a lightweight installable page so it's one tap from the lock screen.
  • Smaller models. I want to see how small a model can go and still write a "why now" line worth reading, so it can run on modest hardware.

What I don't plan to add: streaks, badges, accounts, or anything else that gives you a reason to keep looking at the screen.

Prize Categories

Best Use of Gemma. Gemma 3 runs locally through Ollama and writes the cue in live mode. It's the default model in the README setup, and the Sydney card above is its output. When it doesn't answer, the offline writer takes over.

Go outside

The whole idea fits in one sentence: the app should take less time than putting your shoes on. If you try it, the best feedback is a closed tab and a walk.

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments.