DEV Community

Cover image for Loci: A Walk You Have to Remember
Teo Furlan
Teo Furlan

Posted on

Loci: A Walk You Have to Remember

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

What I Built

I often walk my dog, and too many walks become the same loop: I hesitate over where to go, then choose the familiar route again. I do the same when I head somewhere nearby, like the supermarket. I wanted a reason to explore on foot, and a little more purpose than scrolling through a walk.

Recently I enabled my phone's warning for using it while walking. I was surprised by how often I was reading social media or chatting as I moved. That made me want to try using technology against the pull of technology: a memory game that gives me something to think about, then asks me to put the phone away.

Loci is an Android app that plans a walking loop through real places near you, turns them into one short mnemonic story, and then hides the map. You look at the route once, put the phone in your pocket, and walk it from memory. The screen is the shortest part of the experience: a minute to memorize, then the rest of the walk is outside.

Meet Loci

Loci is also the name of the character you talk to: a small pixel-art companion on a black field. It waits on the home screen, listens while it plans, gives a hint when you ask, and celebrates when you finish a route. Instead of filling in a form, you ask it for a walk, by typing or by voice, and it answers with a route made of places around you.

Ask Loci Loci listens while planning
Home screen: Loci waits and asks where to walk today, with example requests and a text and microphone input. Loci listens while the app finds places near you.

Every landmark is an original 32×32 pixel sprite on a night map, so the places become memory hooks rather than interchangeable pins.

Memorize screen: a night map with numbered pixel-art landmarks and a story fragment in a dialogue box beside Loci.

How to play

  1. Ask Loci for a walk or run ("20 min walk, green areas"), then review the planned course and its story.
  2. Study the landmarks while the map is visible. The story is the cue to remember.
  3. Tap Hide map & start, put the phone in your pocket and follow the story from memory. GPS keeps checking with the screen off, and a vibration marks each checkpoint. Order doesn't matter in the current mode.
  4. Ask for a hint if you need one: it replays that place's story fragment and gives a direction, for half credit. Giving up is always available and reveals the map.
  5. At the end, Loci shows what you remembered, with a badge for each place.
Walk from memory Results
Pocket screen: Loci on a black field, a place counter, a Hint button and a Give up button. Results screen: Loci, the score, a badge for each checkpoint and the route map.

The phone is never locked by the app, so calls and emergency help remain available. Planning requires connectivity; a prepared run works offline. Loci is not turn-by-turn navigation and makes no route-safety guarantee.

Demo

Every screen in the video is the real release build (v1.0.0), recorded on the Android emulator. The only simulated thing is the GPS position (San Telmo, Buenos Aires), moved in small steps to walk the route. The narration is synthetic, generated locally with the open-weight Kokoro voice model.

Code

GitHub logo teofurlan / loci

Loci: a memory walk. Gemma turns a random loop of real OpenStreetMap landmarks into a method-of-loci story; you look once, pocket the phone, and walk it from memory.

Loci

Loci is an Android app that plans a walking loop through real landmarks, turns it into a mnemonic story, and asks you to walk it from memory with the phone in your pocket. It is built for the DEV Hacktoberfest 2026 challenge (hf26, Gemma category).

You ask Loci, a small pixel-art companion, for a route ("20 min walk, green areas") by typing or by voice. Loci finds named places near you in OpenStreetMap and links them into a short story using the method of loci: each place becomes a vivid image, and the images follow one another. You read (or listen to) the story once with the map visible, then hide the map and walk. GPS confirms each checkpoint with a vibration, and at the end Loci shows how many you remembered.

Try it

Download the Android APK from the latest release (loci-1.0.0.apk), open it…

How I Built It

Gemma is the mechanic

Gemma isn't a chat feature added for decoration. Without a story that connects places to memorable images, there is no memory challenge to carry away from the screen.

Gemma has two jobs:

  1. Parse the request. It turns free text ("30 min run, I remember places better than street names") into bounded route parameters: distance or time, pace, preferences, story style. The app validates and clamps every value.
  2. Write the story. It writes one short mnemonic fragment per landmark, using the method of loci: each place becomes a vivid image, and each image leads to the next. The input is only landmark IDs, names and kinds. No coordinates go to the model, and the IDs that come back are checked against the fetched set.

Gemma never gets to invent landmarks or coordinates. The places come from OpenStreetMap; the model only supplies the words. Voice input uses Android speech recognition and feeds the same text path.

Architecture

The route and memory-game logic is plain TypeScript, with external services behind small adapters:

Free-text request ──> intent parser ──> bounded route intent
                                           │
GPS origin ──> loop candidates ──> Overpass landmarks ──> snapped checkpoints
                                           │
                                           └──> story generator ──> Gemma via Vercel proxy
                                                                      │
                         Expo / React Native screens <── route + story┘
                         GPS fixes ──> hit detection ──> score + vibration
Enter fullscreen mode Exit fullscreen mode

The domain handles distance calculations, randomized loop candidates, landmark selection, GPS hit detection, session state, hints and scoring. Application code composes those steps into route planning. Adapters connect the ports to Overpass mirrors, LLM clients, story templates and cache, and local visited-landmark history. Expo and React Native provide the Android app; MapLibre draws the map with OpenFreeMap tiles. I wrote the domain logic, the adapters and the pure view models behind the screens test-first; the suite has 586 Jest tests.

In production, the app calls the open-weight Gemma 4 model through the Gemini API behind a small Vercel proxy. The proxy fixes the model, caps input and output sizes, applies best-effort per-IP rate limiting and keeps the API key server-side instead of inside the APK. If generation fails, Loci falls back to a cached or template story.

The screen-off run is deliberately simple: it checks proximity to the prepared checkpoints, not whether I followed a particular street between them. Hints and giving up are always available, so the score is never the point of the walk. That balance matters to me: I want a small reason to pay attention to where I am, while still being free to keep walking or stop.

Lessons learned

  • Leave room for model thinking. Gemma's reasoning could use up a small token budget and leave an empty visible answer. More headroom fixed the case I saw.
  • A failed request can hide the next one. A transient proxy 502 plus an over-eager, client-wide cooldown meant the story request could silently fall back to a template. Retrying transient proxy failures and limiting the cooldown to Ollama fixed it.
  • Public data services need alternatives. Overpass returned 504s, so the app tries mirrors instead of depending on a single endpoint.
  • Screen-off GPS needs Android foreground work. A foreground service keeps the run's location tracking alive while the screen is off.

Why Does Open Innovation Matter?

Loci is built from open pieces end to end, and each one does a job a closed service would have made harder:

  • Open map data is what keeps the model honest. The places come from OpenStreetMap through Overpass, with names and kinds for parks, monuments, churches, artworks and more (the app draws 18 kinds). Because the real place data is open and queryable, the model never has to "know" a neighborhood: it only writes words about places the app already fetched and verified.
  • An open-weight model can move. The same prompts and validation run against Gemma on my laptop through Ollama during development, at no cost and with no account, and against hosted Gemma in production. Swapping is configuration, not a rewrite, and running Gemma on the phone itself is a realistic next step rather than a dependency on one vendor.
  • No map API keys or quotas. MapLibre with OpenFreeMap tiles means the map costs nothing to show and can't be switched off by a billing change.
  • Small and inspectable. The proxy is a single open function with fixed model, size caps and rate limiting, so anyone can see exactly what leaves the phone: landmark names and kinds, never your coordinates.

Where it worked better than a closed approach: I could develop the whole story pipeline offline against a local model, test failure paths for free, and keep the app's promise ("the model only writes the words") enforceable in code, because both the data and the model are open.

Prize Categories

  • Best Use of Gemma: Gemma parses every request and writes every story; the route and the game are built around what it produces.

What's next

  1. Take Loci on a longer outdoor walk and share where it went, the distance and the score.
  2. Let Loci ask a clarifying question when a request is vague.
  3. An ordered quest mode, where remembering each place unlocks the next clue.
  4. On-device Gemma, so planning can work without a connection too.

Top comments (3)

Collapse
 
alewx profile image
alex •

what's the fallback when the location stream stalls beyond the model's inference window? also, are you persisting walk data client‑side or pushing it to a cloud endpoint, because that adds latency and privacy concerns

Collapse
 
teo_furlan profile image
Teo Furlan •

Hi Alex, good questions! The model is actually never in the loop during the walk, Gemma only runs while planning, before you start, so there’s no inference window for the GPS to outlast. Once you hide the map, checkpoints are confirmed on the device from GPS fixes (fully offline). If the location stream stalls, nothing gets punched until fixes return, with no timeout that fails the run, and hints fall back to the last known position. If the model fails while planning, you still get a cached or template story.

As for data, the walk itself lives only in memory on the phone and is never uploaded; the only thing saved is the list of visited landmark IDs, stored locally. At planning time, the start point goes to OpenStreetMap’s Overpass API to find landmarks, and the request text plus landmark names go through a stateless proxy to Gemma, which never sees coordinates. Hope this answer your questions :)

Collapse
 
alewx profile image
alex • • Edited

thanks for the clarification, love how you keep the run fully offline and avoid timeouts, really clever handling of GP

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