Elsewhere — Don't Remind Me. Give Me a Reason.
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass.
🚀 Try It and Explore the Code
- Live demo: https://sidequest-touchgrass.onrender.com/
- GitHub repository: https://github.com/YuvrajSHAD/touchgrass-ai
- Hugging Face Space: https://huggingface.co/spaces/zoroxR/elsewhere-qwen
The web app is deployed on Render. Although the Hugging Face Space and local inference integrations have been tested separately, the active AI provider in the public deployment has not yet been verified.
Less time deciding what to do. More time actually doing it.
🌱 The Idea
We don't need another app telling us to go outside. Most of us already know we should.
The harder part is deciding what to do with the free time we have.
You're sitting at your laptop, scrolling on your phone, and a simple question comes up:
Okay, what should I actually do?
I built Elsewhere around a different idea:
Don't just remind people to go outside. Give them a reason to.
Imagine you're into photography, have 30 minutes free, and a friend happens to be nearby. Instead of throwing fifty activities at you, Elsewhere uses that context to suggest one small, actionable outdoor quest.
The AI isn't the destination. The outside world is.
⚡ How It Works
flowchart TD
A["Your interests"] --> D["Elsewhere"]
B["Time available"] --> D
C["Nearby friend context"] --> D
D --> E["Generate one outdoor quest"]
E --> F["Close the app"]
F --> G["Go do something"]
style D fill:#d9f99d,stroke:#3f6212,color:#1a2e05
style G fill:#bbf7d0,stroke:#166534,color:#14532d
Three inputs. One suggestion. No endless feed.
For example:
Your friend is nearby, and you both have 20 minutes. Meet up and explore somewhere you wouldn't normally go.
The intended experience is simple:
- Open Elsewhere.
- Get a reason.
- Close the app.
- Go outside.
🛠️ The Technical Architecture
Elsewhere is a Progressive Web App (PWA) backed by Node.js and Express. Its suggestion pipeline supports hosted Hugging Face inference, optional local inference through llama.cpp, and a deterministic fallback.
flowchart TD
U["Browser / PWA"] --> API["Node.js + Express"]
API --> CTX["Build suggestion prompt<br/>Interests · Duration · Friend context"]
CTX --> HF{"Hugging Face<br/>Space configured?"}
HF -->|Yes| HFI["Qwen3 1.7B<br/>ZeroGPU inference"]
HFI -->|Usable response| OUT["Clean suggestion"]
HFI -->|Failure / no usable text| LOCAL{"Local LLM configured?"}
HF -->|No| LOCAL
LOCAL -->|Yes| LLAMA["llama.cpp<br/>OpenAI-compatible API"]
LLAMA -->|Usable response| OUT
LLAMA -->|Failure / no usable text| FALLBACK["Deterministic fallback"]
LOCAL -->|No| FALLBACK
OUT --> RESP["Return suggestion"]
FALLBACK --> RESP
RESP --> U
The diagram describes the backend's intended provider-selection and fallback logic. It does not establish that every path works in the deployed Render environment.
The stack
| Layer | Technology | Purpose |
|---|---|---|
| Frontend | HTML, CSS, JavaScript, PWA | User experience |
| Backend | Node.js, Express | API and suggestion orchestration |
| Hosted AI | Hugging Face Space | Qwen3 inference |
| Local AI | llama.cpp | Local OpenAI-compatible inference |
| Model | Qwen3 1.7B | Generates short outdoor suggestions |
| Deployment | Render | Hosts the web app and backend |
🧠 Following a Suggestion Through the System
Here's the request lifecycle in a little more detail.
sequenceDiagram
participant U as User
participant W as Web App
participant S as Express Server
participant H as Hugging Face
participant L as Local llama.cpp
U->>W: Select interests and available time
W->>S: POST /api/suggestion
S->>S: Build contextual prompt
alt Hugging Face configured
S->>H: Request Qwen3 suggestion
H-->>S: Inference result
else Hosted provider unavailable or unusable
S->>L: Try local inference if configured
L-->>S: Model response or failure
end
S->>S: Clean result or use fallback
S-->>W: Return suggestion
W-->>U: Display one outdoor quest
The server owns provider selection and response handling. The browser doesn't need to know which model generated the suggestion.
That separation also makes it possible to test inference independently of the public deployment.
🔬 What I Actually Tested
I wanted to distinguish a working integration from an architecture that merely looks good on paper.
| Test | Result |
|---|---|
| Local llama.cpp health endpoint | Passed |
| Local app → llama.cpp suggestion request | Passed during testing |
| Local app → Hugging Face Space inference | Successful response observed |
| Hugging Face Space direct demo | Tested successfully |
| Full browser and geolocation flow | Not fully verified |
| AI inference through the public Render deployment | Not verified |
One successful hosted-inference test returned:
Find a quiet spot to do calisthenics and enjoy the breeze.
The local integration also returned a model-generated response through the app's suggestion endpoint.
These checks confirmed that both inference paths could produce responses during their respective tests. They don't prove continuous availability or successful inference on every request.
🔌 Why Open-Weight AI?
I wanted to explore what a small, focused application could do with open-weight AI without making every interaction dependent on a closed, hosted API.
Using Qwen3 with a Hugging Face Space gives the project a hosted inference path. Supporting llama.cpp also gives me a way to run inference locally through an OpenAI-compatible API.
The trade-offs are different:
- Hosted inference: Easier to access without running a model on your own machine, but dependent on service availability and usage limits.
- Local inference: More control over where the model runs, but requires a compatible server and sufficient local resources.
- Deterministic fallback: Keeps the suggestion flow useful when a model isn't configured or returns no usable response.
flowchart LR
A["Suggestion request"] --> B{"Inference available?"}
B -->|Hosted| C["Hugging Face + Qwen3"]
B -->|Local| D["llama.cpp + Qwen3"]
B -->|Neither| E["Fallback template"]
C --> F["One suggestion"]
D --> F
E --> F
For this project, AI is a means to an end. It should make the suggestion more relevant, not turn a five-minute decision into a twenty-minute conversation.
🔒 Privacy and Product Decisions
Elsewhere is deliberately designed to resist becoming another attention-consuming product.
- No endless feeds.
- No streaks or gamification loops.
- No notification loops.
- No endless AI conversations.
- Nearby-friend context is intended to help people make plans, not encourage constant checking.
The current backend uses in-memory state for group and presence data, rounds location information, and expires presence after a limited period. The exact privacy properties still depend on the implemented flows and deployment configuration.
The guiding principle is simple: help people spend less time on the screen, not more.
🧪 My Agent Session
I used DevRelay to document the repository architecture, trace the suggestion-generation flow, and test the local LLM integration.
The session separates source-code findings from results verified through live local checks, while identifying behavior that remains untested.
🏆 Prize Categories
- Render — Best Use of Render: Hosting the Elsewhere web app and backend on Render.
- ElevenLabs — Best Use of ElevenLabs: Generating AI narration for the Elsewhere product demo.
- Entire — Best Use of Entire: Sharing the DevRelay session documenting Elsewhere's architecture and local LLM integration.
- GitHub — Best Use of GitHub Copilot: Using Copilot to inspect the codebase, trace suggestion generation, and test the local LLM integration.
🌍 What's Next?
The next step is to verify the full deployed inference path and browser experience, then continue refining how the app turns a person's interests and available time into a genuinely useful suggestion.
The goal isn't to build the biggest AI application.
It's to build one that gives someone a good reason to close it.
Less scrolling. More elsewhere.
If you try it, I'd love to hear: Would one personalized outdoor suggestion actually get you off your screen?

Top comments (0)