This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
You find the perfect spot. Flat ground, a stream nearby, no one around. You also have zero bars and there is a grey papery lump hanging from the branch above where you wanted to put your tent.
That moment is why I built SafeCamp.
What I Built
SafeCamp is a campsite safety inspector that works with no signal. Point your phone at a plant, an insect, a nest or a patch of ground. It tells you how worried to be and what to do next, in four levels: Favorable, Caution, Danger, Critical.
Example advice: “Move your tent pitch at least 30 m away.”
The whole check runs on the phone. You open the app once on Wi-Fi, the vision model is cached and from then on it works in airplane mode. The photo never leaves the device.
How it fits “Touch Grass”
Most apps compete for your attention. This one is built to give it back. It is only useful when you are standing outside, in the place you are about to sleep and it is meant to take seconds: scan, read the card, move the tent, put the phone away.
It is for anyone who camps, hikes or picnics somewhere unfamiliar. It removes one reason to stay home: “what if I run into something I cannot identify and cannot look up?”
Demo
Live app: safecamp.onrender.com
(Open it once on Wi-Fi, then try airplane mode.)
Four real scans from the app
RISK: DANGER Snake - 83% |
RISK: DANGER Wasp or hornet nest - 95% |
NO KNOWN HAZARD Looks like: Pet dog - 97% |
NOT SURE, BE CAREFUL Possible: Risky campfire - 38% |
Code
SafeCamp
An offline campsite safety inspector. Take a photo of a plant, insect or piece of ground,
and get a color-coded risk level and what to do about it, with no signal and no upload
Built for the Hacktoberfest Open-Source AI Challenge, Week 1: Touch Grass.
The repository was started on October 8, 2026, inside the challenge window.
- Live demo: safecamp.onrender.com
- Demo video: Watch on YouTube
- DEV post: SafeCamp: an offline campsite safety check that runs on your phone
Why this exists
Good camping spots tend to have bad phone signal. That is exactly where you meet an unfamiliar insect, a plant you do not want to touch, or a dry gully you should not sleep in. Searching the web is not an option there, and a photo of your campsite is not something everyone wants to upload anyway.
SafeCamp runs the whole check on the phone. The photo…
MIT licensed. The README covers running it locally and adding your own hazards.
How I Built It
The model
SafeCamp uses CLIP (Xenova/clip-vit-base-patch32, int8 ONNX) through Transformers.js. It runs on WebAssembly inside a Web Worker so the UI never freezes.
There is no training. CLIP compares the photo with text prompts like:
“a photo of a paper wasp nest with hexagonal honeycomb cells”
The closest prompts win. Adding a hazard means writing a few sentences, not collecting a dataset.
The hazard list
41 entries live in one TypeScript file:
- 37 hazards (poisonous plants, stinging insects, snakes and large animals, unsafe terrain and water, fire and weather risks)
- 4 favorable signs (e.g. a flat, dry tent site)
Each entry has prompts, a short summary and action steps.
Making it fast
The first version re-encoded every text prompt on every scan.
With 5 hazards it was fine (~1.4 s). At 41 entries it grew to 3.6–5 s on my laptop.
The text side never changes, so I encode it once at dev time into text-embeddings.json. The phone only runs the image encoder. A scan is now back under 1.5 s. A script regenerates the file whenever prompts change.
Making it honest
This is where I spent the most time - a wrong “you’re fine” is worse than no answer.
- Early on, a photo of an empty bird nest came back as “wasp nest, 97%”. The app had no bird nest class, so the nearest hazard won. I added 25 everyday labels (grass, bark, bird nests, rocks) so ordinary things stop being forced into a hazard.
- A real hazard always outranks a favorable sign.
- Related hazards pool their scores (a wasp-or-bee split still counts as “stinging insects”).
- Low confidence gives a “possible, be careful” warning that names the runner-up - never reassurance.
- “No known hazard matched” is never shown as “safe”.
- Mushrooms, berries and snakes always say “treat as dangerous”, because a general vision model cannot reliably tell harmless ones from deadly ones.
- Dark or blurry photos are flagged instead of judged.
- A Why? panel shows the top scores. The score is a relative share between the app’s own labels, not a probability and the app says so.
Working offline
The app is a PWA cached by Serwist. One thing that bit me: by default the ONNX runtime loads its WebAssembly files from a CDN, which fails with no signal. I copy them into public/ort at build time and serve them myself.
On phones
Taking a photo on some phones reloaded the page and lost the result. I added an in-app camera and a gallery button on the result screen.
Stack
Next.js 16, React 19, Bun, Tailwind CSS 4, Serwist, Transformers.js, TypeScript.
AI assistance
I built SafeCamp with Claude as a pair programmer for design discussion and code review. I ran, tested and debugged everything myself. I deliberately avoided cloud APIs (hosted LLMs, databases, text-to-speech inside the app) because they would break the offline and privacy promises.
Limits
SafeCamp is a first-pass aid, not an authority. CLIP is a general model and will be wrong sometimes, especially on blurry, dark, distant or unusual photos. It has not been tested on a wide range of phones. Hazards differ by region and the advice is general. Follow local rangers, signs and emergency services.
Why Does Open Innovation Matter?
SafeCamp only makes sense because the model is open.
- Privacy - An open-weight model can run on the device, so photos of someone’s campsite and kids are never uploaded.
- No signal - A hosted vision API cannot work in the places this app is for. A model that is just a file on the phone can.
- No cost per scan - No API key, no usage bill, nothing to rate-limit. A free tool for campers should stay free.
- Changeable - The hazard list is plain text. Someone in Sri Lanka, Norway or Arizona can swap in their own hazards and thresholds without asking anyone.
- Inspectable - Because the scoring is ours, I could build a Why? panel that shows exactly how a result came out. A black-box API would not let me do that.
Prize Categories
-
Best Use of Render - SafeCamp is deployed on Render as a free Web Service (
bun install && bun run build, thenbun run start) and it auto-deploys on push. -
Best Use of GitHub - GitHub Actions runs lint and build on every push and pull request (
.github/workflows/ci.yml). - Best Use of ElevenLabs - I used ElevenLabs to generate the narration for the demo video. The app itself does not call ElevenLabs, so the offline and privacy promises stay true.
Contact: dev.sasmitha@gmail.com
Top comments (0)