Building Strayling
Take a photo of an animal you meet on the street, and the phone cuts out just that animal and turns it into a photo sticker. It goes into your sticker book and onto the neighborhood map. I wrote this from the repository's code, docs and git history (main, as of November 2, 2026).


What it does
- Snap: take a photo and pick a filter (original, film, pastel, black and white). Check the suggested species and give it a name.
- Map: you can browse without signing in. Taking photos, saving and logging meetings need a Google sign-in.
- Meetings: you can log one once a day, and only when you are in the same cell or the cell right next to it.
- Pets: one person can register up to 10, and can download their own records as a ZIP once a day.
- Just now: shows up to 5 updates from the last 30 minutes in the same country, without the name of the person who found the animal.
- Daily limits: 20 animal photos on the map and 20 comments.
How the cut-out works
Android uses ML Kit Subject Segmentation, and iOS 17 and later uses Vision. Both run on the phone. The photo goes in as a 1024px JPEG with EXIF removed, and only the largest subject and its largest connected region are kept. Then the filter, a white border and a shadow are applied, and it is saved as 512px and 160px WebP. Quality steps down through 0.86, 0.75 and 0.6 until the files fit the 300KB and 48KB caps.
On Android the processing limit is 15 seconds. If the cut-out area is under 2% or the cut-out fails, the middle 80% becomes a square photo card. Since this card includes the background, it is locked as private and only you can see it.
Map and location
The phone turns coordinates into an H3 resolution 8 cell ID before sending them. The map groups cells at resolution 8 at zoom 13 or higher, 6 at 10 or higher, 4 at 6 or higher, and 2 when zoomed out further. Up to 400 cells at a time, with 3 thumbnails per cell.
On November 2, 2026, I narrowed what other people can see. That date is from the repository commits. Owners still see everything.
Structure
- One arm64 container on EC2 serves both the API and the web.
- The phone map uses the Google Maps SDK. The web and keyless builds use MapLibre and OpenFreeMap.
- Deploys run from a script on the Mac in this order: checks, web build, image, ECR, SSM run, verification.
- CI on GitHub Actions was removed on October 27, 2026. Type checks and tests run locally.
- For app updates (OTA), the script stops if the native runtime differs.
Where AI is used
The server uses only Claude, and the default model is from the Haiku line. It is used for name and species suggestions, finding the same animal, speech bubbles, comment translation, diary drafts, opinions on reports, summarizing reviews and so on. Only the sticker and text are sent. Camera photos, exact locations and accounts are not. If a call fails, only that feature is skipped. Opinions on reports are for reference, and a person makes the decision.
How it was built
- October 4, 2026: first commit. At first it was an app that turned the animal you photographed into a 3D character.
- October 5: removed 3D and the field guide, and switched to photo stickers.
- October 13: removed the publish delay so saved stickers show on the map right away.
- October 27: removed external CI and dropped the backup AI provider.
- October 29: the day with the most commits, 135 including merges.
- November 2: shipped a batch of fixes from a security review.
Problems I ran into
- Map cards went blank after returning to the app: markers are redrawn now (October 6).
- Requests went out before the saved sign-in was read, so the first screen froze (October 14).
- The 0,0 the map sends first put pins in the ocean (October 28).
- On Android Google Maps, cards stayed after zooming out: the zoom level is now part of the marker key (October 29).
- Importing a map module that does not exist on the web crashed the web app: added a web-only file (October 30).
- An RN 0.86 issue where a button that started disabled could not be pressed after it was enabled: it is remounted now (October 31).
- Images where a small file uses a lot of memory: the size is checked and rejected before decoding (November 2).
- Fixed 8 server tests that had fallen behind the code while there was no CI (November 2).
Tools and numbers
I used Claude Code for development. This is based on the Co-Authored-By lines in commits and does not mean a share of the work. The docs say Aside was used for making and checking images.
| Item | Value |
|---|---|
| Commits | 713 (2026-10-04 to 11-02) |
| PR numbers | Up to #354 |
| Claude co-author lines | 419 lines |
| Server test files | 94 |
| App version | 0.1.5 |
| App | Expo 57, React Native 0.86 |
| Server | Next.js 16, Drizzle, PostgreSQL |
The test file count is a count of files. I did not run the tests while writing this.
Next
The items in the docs are push notifications and the next native build, real-time chat in the neighborhood lounge, removing compatibility code for old app versions, and iOS universal links. No dates are given.