<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sasmitha Ashinsana</title>
    <description>The latest articles on DEV Community by Sasmitha Ashinsana (@sasmeee).</description>
    <link>https://dev.to/sasmeee</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2882032%2F42828ca9-e9f3-40d7-956b-bed257bcee90.png</url>
      <title>DEV Community: Sasmitha Ashinsana</title>
      <link>https://dev.to/sasmeee</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sasmeee"/>
    <language>en</language>
    <item>
      <title>SafeCamp: an offline campsite safety check that runs on your phone</title>
      <dc:creator>Sasmitha Ashinsana</dc:creator>
      <pubDate>Sun, 11 Oct 2026 10:40:54 +0000</pubDate>
      <link>https://dev.to/sasmeee/safecamp-an-offline-campsite-safety-check-that-runs-on-your-phone-1af</link>
      <guid>https://dev.to/sasmeee/safecamp-an-offline-campsite-safety-check-that-runs-on-your-phone-1af</guid>
      <description>&lt;p&gt;&lt;em&gt;This is a submission for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05"&gt;Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;That moment is why I built SafeCamp.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;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: &lt;strong&gt;Favorable&lt;/strong&gt;, &lt;strong&gt;Caution&lt;/strong&gt;, &lt;strong&gt;Danger&lt;/strong&gt;, &lt;strong&gt;Critical&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Example advice: “Move your tent pitch at least 30 m away.”&lt;/p&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it fits “Touch Grass”&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
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.&lt;/p&gt;

&lt;p&gt;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?”&lt;/p&gt;
&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/T_eaoRa1YOM" width="710" height="399"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Live app: &lt;a href="https://safecamp.onrender.com" rel="noopener noreferrer"&gt;safecamp.onrender.com&lt;/a&gt;&lt;br&gt;&lt;br&gt;
(Open it once on Wi-Fi, then try airplane mode.)&lt;/p&gt;
&lt;h3&gt;
  
  
  Four real scans from the app
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
  &lt;tbody&gt;
&lt;tr&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4nzt76e8er0na7pz862j.webp" alt="Snake result" width="800" height="1422"&gt;
      &lt;br&gt;&lt;strong&gt;RISK: DANGER&lt;/strong&gt;&lt;br&gt;Snake - 83%
    &lt;/td&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7dykn56sipbrmadcefbx.webp" alt="Wasp nest result" width="800" height="1422"&gt;
      &lt;br&gt;&lt;strong&gt;RISK: DANGER&lt;/strong&gt;&lt;br&gt;Wasp or hornet nest - 95%
    &lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fuee9sbhltl1d1cnpxfae.webp" alt="Pet dog result" width="800" height="1422"&gt;
      &lt;br&gt;&lt;strong&gt;NO KNOWN HAZARD&lt;/strong&gt;&lt;br&gt;Looks like: Pet dog - 97%
    &lt;/td&gt;
    &lt;td&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F4t7dmk1s3sq1kis11a1n.webp" alt="Tent campsite result" width="800" height="1422"&gt;
      &lt;br&gt;&lt;strong&gt;NOT SURE, BE CAREFUL&lt;/strong&gt;&lt;br&gt;Possible: Risky campfire - 38%
    &lt;/td&gt;
  &lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Code
&lt;/h2&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/sasmeee" rel="noopener noreferrer"&gt;
        sasmeee
      &lt;/a&gt; / &lt;a href="https://github.com/sasmeee/safe-camp" rel="noopener noreferrer"&gt;
        safe-camp
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;p&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://raw.githubusercontent.com/sasmeee/safe-camp/main/public/safecamp-logo-light.svg"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsasmeee%2Fsafe-camp%2Fmain%2Fpublic%2Fsafecamp-logo-light.svg" alt="SafeCamp logo" width="120"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;SafeCamp&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;
  An offline campsite safety inspector. Take a photo of a plant, insect or piece of ground,&lt;br&gt;
  and get a color-coded risk level and what to do about it, with no signal and no upload
&lt;/p&gt;

&lt;p&gt;
  &lt;a href="https://safecamp.onrender.com" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/66513384fa00e5e4cddfaf2e6da99a96d0162510d619fec7413fb5793b616873/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6976655f64656d6f2d7361666563616d702e6f6e72656e6465722e636f6d2d316233383262" alt="Live demo"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/a2b318140d58f56862ecd5581d006b961f44164e891dbd5fd6834b93f824756f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4861636b746f626572666573742d323032362d626c756576696f6c6574"&gt;&lt;img src="https://camo.githubusercontent.com/a2b318140d58f56862ecd5581d006b961f44164e891dbd5fd6834b93f824756f/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4861636b746f626572666573742d323032362d626c756576696f6c6574" alt="Hacktoberfest 2026"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/0a68507d8e6e74effd7d97aaea03bcbdfd32168d60bc2f8e29a493e74d64c7e7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5057412d6f66666c696e655f66697273742d326637643466"&gt;&lt;img src="https://camo.githubusercontent.com/0a68507d8e6e74effd7d97aaea03bcbdfd32168d60bc2f8e29a493e74d64c7e7/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5057412d6f66666c696e655f66697273742d326637643466" alt="Offline first"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/db64d3df3fad18238b0c92642b83b47a207d406bf1b29775139f97c20163fe71/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41492d6f6e2d2d6465766963652d326637643466"&gt;&lt;img src="https://camo.githubusercontent.com/db64d3df3fad18238b0c92642b83b47a207d406bf1b29775139f97c20163fe71/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f41492d6f6e2d2d6465766963652d326637643466" alt="On-device AI"&gt;&lt;/a&gt;
  &lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e"&gt;&lt;img src="https://camo.githubusercontent.com/5caa455d8debc46fb23abbadb45a733a937f3910a73fc875c2f7820468e1bb54/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d677265656e" alt="MIT"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Built for the &lt;a href="https://dev.to/challenges/hacktoberfest-week1-2026-10-05" rel="nofollow"&gt;Hacktoberfest Open-Source AI Challenge, Week 1: Touch Grass&lt;/a&gt;.&lt;br&gt;
The repository was started on October 8, 2026, inside the challenge window.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live demo:&lt;/strong&gt; &lt;a href="https://safecamp.onrender.com" rel="nofollow noopener noreferrer"&gt;safecamp.onrender.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Demo video:&lt;/strong&gt; &lt;a href="https://youtu.be/T_eaoRa1YOM" rel="nofollow noopener noreferrer"&gt;Watch on YouTube&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;DEV post:&lt;/strong&gt; &lt;a href="https://dev.to/sasmeee/safecamp-an-offline-campsite-safety-check-that-runs-on-your-phone-1af" rel="nofollow"&gt;SafeCamp: an offline campsite safety check that runs on your phone&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why this exists&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;SafeCamp runs the whole check on the phone. The photo…&lt;/p&gt;&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/sasmeee/safe-camp" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


&lt;p&gt;MIT licensed. The README covers running it locally and adding your own hazards.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I Built It
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The model
&lt;/h3&gt;

&lt;p&gt;SafeCamp uses CLIP (&lt;code&gt;Xenova/clip-vit-base-patch32&lt;/code&gt;, int8 ONNX) through Transformers.js. It runs on WebAssembly inside a Web Worker so the UI never freezes.&lt;/p&gt;

&lt;p&gt;There is no training. CLIP compares the photo with text prompts like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“a photo of a paper wasp nest with hexagonal honeycomb cells”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The closest prompts win. Adding a hazard means writing a few sentences, not collecting a dataset.&lt;/p&gt;

&lt;h3&gt;
  
  
  The hazard list
&lt;/h3&gt;

&lt;p&gt;41 entries live in one TypeScript file:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;37 hazards (poisonous plants, stinging insects, snakes and large animals, unsafe terrain and water, fire and weather risks)&lt;/li&gt;
&lt;li&gt;4 favorable signs (e.g. a flat, dry tent site)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each entry has prompts, a short summary and action steps.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it fast
&lt;/h3&gt;

&lt;p&gt;The first version re-encoded every text prompt on every scan.&lt;br&gt;&lt;br&gt;
With 5 hazards it was fine (~1.4 s). At 41 entries it grew to 3.6–5 s on my laptop.&lt;/p&gt;

&lt;p&gt;The text side never changes, so I encode it once at dev time into &lt;code&gt;text-embeddings.json&lt;/code&gt;. The phone only runs the image encoder. A scan is now back under 1.5 s. A script regenerates the file whenever prompts change.&lt;/p&gt;

&lt;h3&gt;
  
  
  Making it honest
&lt;/h3&gt;

&lt;p&gt;This is where I spent the most time - a wrong “you’re fine” is worse than no answer.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;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.&lt;/li&gt;
&lt;li&gt;A real hazard always outranks a favorable sign.&lt;/li&gt;
&lt;li&gt;Related hazards pool their scores (a wasp-or-bee split still counts as “stinging insects”).&lt;/li&gt;
&lt;li&gt;Low confidence gives a “possible, be careful” warning that names the runner-up - never reassurance.&lt;/li&gt;
&lt;li&gt;“No known hazard matched” is never shown as “safe”.&lt;/li&gt;
&lt;li&gt;Mushrooms, berries and snakes always say “treat as dangerous”, because a general vision model cannot reliably tell harmless ones from deadly ones.&lt;/li&gt;
&lt;li&gt;Dark or blurry photos are flagged instead of judged.&lt;/li&gt;
&lt;li&gt;A &lt;strong&gt;Why?&lt;/strong&gt; 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Working offline
&lt;/h3&gt;

&lt;p&gt;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 &lt;code&gt;public/ort&lt;/code&gt; at build time and serve them myself.&lt;/p&gt;

&lt;h3&gt;
  
  
  On phones
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Stack
&lt;/h3&gt;

&lt;p&gt;Next.js 16, React 19, Bun, Tailwind CSS 4, Serwist, Transformers.js, TypeScript.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI assistance
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Limits
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Does Open Innovation Matter?
&lt;/h2&gt;

&lt;p&gt;SafeCamp only makes sense because the model is open.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Privacy&lt;/strong&gt; - An open-weight model can run on the device, so photos of someone’s campsite and kids are never uploaded.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No signal&lt;/strong&gt; - A hosted vision API cannot work in the places this app is for. A model that is just a file on the phone can.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;No cost per scan&lt;/strong&gt; - No API key, no usage bill, nothing to rate-limit. A free tool for campers should stay free.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Changeable&lt;/strong&gt; - The hazard list is plain text. Someone in Sri Lanka, Norway or Arizona can swap in their own hazards and thresholds without asking anyone.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Inspectable&lt;/strong&gt; - 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prize Categories
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of Render&lt;/strong&gt; - SafeCamp is deployed on Render as a free Web Service (&lt;code&gt;bun install &amp;amp;&amp;amp; bun run build&lt;/code&gt;, then &lt;code&gt;bun run start&lt;/code&gt;) and it auto-deploys on push.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of GitHub&lt;/strong&gt; - GitHub Actions runs lint and build on every push and pull request (&lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Best Use of ElevenLabs&lt;/strong&gt; - 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.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Contact: &lt;a href="mailto:dev.sasmitha@gmail.com"&gt;dev.sasmitha@gmail.com&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>devchallenge</category>
      <category>hf26challenge</category>
      <category>opensource</category>
      <category>pwa</category>
    </item>
  </channel>
</rss>
