This is an official submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
What I Built
NatureQuest is a local-first outdoor adventure companion that turns a few free minutes into an offline nature mission.
Most applications aim to maximize screen retention. NatureQuest does the exact opposite: it functions as anti-retention software. It uses a local open-weight AI model to generate structured, safety-conscious outdoor micro-adventures, then prompts the user to put down their screen and step outside.
Key Features
- Local AI Engine: Powered locally by Ollama running the
qwen2.5-coder:7bmodel onlocalhost:11434. - Custom Mission Planner: Generates personalized mission checklists based on time available, weather conditions, and surroundings.
- Leave-No-Trace Guardrails: System prompts actively enforce safety rules—no foraging unknown plants, disturbing wildlife, or trespassing.
- In-Browser Nature Journal: A private space where users record observations, saved directly to browser
localStorage.
Demo and Code
- GitHub Repository: https://github.com/mohit-saini-dev/naturequest
- Local Application: Runs on
http://localhost:3000using Next.js, React, and Tailwind CSS.
Generated Mission Preview
How NatureQuest Works
- The user selects available time (e.g., 20 mins) and surroundings in the UI.
- The Next.js API route (
/api/plan/route.js) constructs a prompt enforcing structure and safety rules, sending it to Ollama onlocalhost:11434. -
qwen2.5-coder:7bprocesses the request locally and returns structured JSON with mission tasks and safety reminders. - The client renders an interactive Field Guide checklist.
- The user completes the activity offline and logs a brief reflection in their private journal upon returning.
javascript // Local prompt execution via Ollama daemon const response = await fetch('[http://127.0.0.1:11434/api/generate](http://127.0.0.1:11434/api/generate)', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'qwen2.5-coder:7b', prompt: `<|im_start|>system\n${systemPrompt}<|im_end|>\n<|im_start|>user\n${userPrompt}<|im_end|>\n<|im_start|>assistant\n`, stream: false, format: 'json', }), }); 
![Why Object.keys(user) Returns string[], Not (keyof User)[]: TypeScript Means It](https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2q4w48b9bzs43tynyhsf.png)
