
This is a submission for the Hacktoberfest Open-Source AI Challenge Week 1: Touch Grass
What I Built
OutdoorPulse is an AI-powered outdoor activity recommender that analyzes your local weather, personal preferences, and time of day to suggest the perfect outdoor activity — right now.
It answers the question every screen-addicted person asks: "What should I do outside today?"
Here's how it works:
- Tell it about yourself — your interests (hiking, photography, birding...), fitness level, and how much time you have
- It checks your weather — real-time temperature, humidity, UV index, wind, sunrise/sunset via SerpApi
- AI picks your activities — Gemma 4 (open-weight model) reasons about which of 46 curated outdoor activities match your current conditions
- Listen and go — ElevenLabs narrates each recommendation so you can listen while you lace up your shoes
The core insight: the hardest part of going outside isn't the activity — it's deciding what to do. OutdoorPulse removes that decision friction by giving you a personalized, weather-aware answer in seconds.
Who is it for?
- Remote workers who need a reason to step away from the desk
- Parents looking for family-appropriate outdoor ideas
- Fitness enthusiasts who want weather-adapted suggestions
- Anyone who opens their phone to "check one thing" and loses 2 hours
Demo
🌐 Live App: outdoor-pulse.onrender.com
🔌 API Health: outdoor-pulse-api.onrender.com/api/health
Note: Free tier on Render spins down after 15 min of inactivity. First load may take ~30 seconds to wake up.
Here's what the AI generates for Dhaka, Bangladesh on a warm October evening:
{
"greeting": "Hello Zuhair, the clear skies and 82°F warmth this afternoon are setting the stage for some great outdoor time.",
"recommendations": [
{
"activity_name": "Sunset Photography Walk",
"headline": "Capture the twilight transition as the sky paints itself in golds and purples.",
"match_score": 95,
"why_now": "The soft, diffused light of the evening offers unique photographic opportunities impossible during harsh midday sun.",
"what_to_bring": ["Camera with good low-light performance", "Sturdy tripod", "Insect repellent"]
},
{
"activity_name": "Waterside Walk",
"headline": "Enjoy a calming stroll along a nearby canal as the city lights reflect on the water.",
"match_score": 88
},
{
"activity_name": "Night Walk",
"headline": "Dodge the day's heat and experience the city's quieter side on a cool evening stroll.",
"match_score": 92
}
]
}
Every recommendation is specific: it references the actual temperature (82°F), humidity (75%), wind speed (10 km/h), and time of day (evening). No generic "go for a walk" — it tells you why now and what to bring.
Code
ZuhairHossain
/
outdoor-pulse
🌿 AI-powered outdoor activity recommender — Hacktoberfest 2026
🌿 OutdoorPulse
AI-powered outdoor activity recommender that gets you off the screen and into the world.
OutdoorPulse uses open-weight AI models to analyze real-time weather, your preferences, and time of day to suggest personalized outdoor activities — with voice narration to listen to while you get ready.
Built for Hacktoberfest 2026 — Week 1: Touch Grass
✨ Features
- 🤖 AI Recommendations — Gemma 4 (open-weight) generates personalized activity suggestions based on real conditions
- 🌤️ Live Weather — SerpApi fetches current weather, UV index, humidity, and sunrise/sunset times
- 🔊 Voice Narration — ElevenLabs reads recommendations aloud so you can listen while getting ready
- 📍 Location Aware — GPS auto-detection or manual entry for any city worldwide
- 👤 Personal Profiles — Set your interests, fitness level, and available time
- 🌙 Time-Aware — Suggestions adapt to morning, afternoon, evening, or night
- 🎨 Premium Dark UI — Glassmorphism design with nature-inspired color palette
🏗️
…Project Structure
outdoor-pulse/
├── client/ # Vite + React frontend
│ ├── src/
│ │ ├── App.jsx # Main app with profile, weather, recommendations
│ │ ├── index.css # Premium design system (600+ lines)
│ │ └── components/
│ │ ├── ActivityCard.jsx # Activity cards with audio playback
│ │ ├── WeatherWidget.jsx # Real-time weather display
│ │ ├── ProfileSetup.jsx # Onboarding with interest chips
│ │ ├── LocationBar.jsx # GPS + manual location input
│ │ ├── Header.jsx # Navigation
│ │ └── LoadingState.jsx # Loading animations
│ └── vite.config.js # Dev proxy to backend
├── server/ # Express.js backend
│ └── src/
│ ├── index.js # Express server with CORS
│ ├── routes/
│ │ ├── recommend.js # Main AI recommendation pipeline
│ │ ├── weather.js # Weather endpoint
│ │ ├── audio.js # ElevenLabs TTS endpoint
│ │ ├── activities.js # Activity database queries
│ │ └── user.js # Profile management
│ ├── services/
│ │ ├── gemma.js # Multi-provider AI (OpenRouter → Groq)
│ │ ├── weather.js # SerpApi weather service
│ │ ├── elevenlabs.js # Text-to-speech service
│ │ └── activities.js # Activity filtering + scoring
│ └── data/
│ └── activities.json # 46 curated outdoor activities
└── render.yaml # Render deployment config
How I Built It
The AI Core: Gemma 4 via OpenRouter
The brain of OutdoorPulse is Gemma 4 31B — Google's open-weight model — accessed through OpenRouter's free inference tier. Here's the key architectural decision:
// server/src/services/gemma.js — Multi-provider with automatic fallback
const PROVIDERS = [
{
id: 'openrouter-gemma',
baseURL: 'https://openrouter.ai/api/v1',
model: 'google/gemma-4-31b-it:free',
name: 'Gemma 4 31B (via OpenRouter)',
},
{
id: 'groq',
model: 'qwen/qwen3.8-27b',
name: 'Qwen 3.8 27B (via Groq)',
},
];
I built a multi-provider fallback system: the app tries Gemma 4 on OpenRouter first. If it's rate-limited (the free tier shares capacity), it automatically falls back to Qwen 3.8 on Groq. Both are open-weight models. The user never sees an error — the app just works.
The AI receives a structured prompt with:
- Real weather data from SerpApi (temperature, humidity, UV, wind, sunrise/sunset)
- User profile (interests, fitness level, available time)
- Time context (morning/afternoon/evening/night, current month)
- Activity database (46 activities with metadata)
And it returns structured JSON with personalized recommendations, including match scores, gear suggestions, and specific time windows.
Weather Pipeline: SerpApi
SerpApi provides structured weather data that feeds directly into the AI prompt:
// server/src/services/weather.js
export async function getCurrentWeather(location) {
const response = await axios.get('https://serpapi.com/search', {
params: {
engine: 'google',
q: `weather ${location}`,
api_key: process.env.SERPAPI_API_KEY,
},
});
// Extracts: temp, humidity, wind, UV, sunrise, sunset, condition
}
Weather is the #1 factor in outdoor activity selection. A 95°F humid afternoon needs different recommendations than a 65°F breezy morning. SerpApi makes it possible for the AI to reason about real conditions instead of guessing.
Voice Narration: ElevenLabs
Each activity card has a "🔊 Listen" button that generates natural voice narration via ElevenLabs:
// server/src/services/elevenlabs.js
export async function generateSpeech(text) {
const response = await axios.post(
`https://api.elevenlabs.io/v1/text-to-speech/${VOICE_ID}`,
{ text, model_id: 'eleven_multilingual_v2' },
{ headers: { 'xi-api-key': process.env.ELEVENLABS_API_KEY },
responseType: 'arraybuffer' }
);
return Buffer.from(response.data);
}
The audio feature is intentional for the "Touch Grass" theme: you can listen to your recommendations while getting ready to head outside instead of staring at yet another screen.
Activity Database: 46 Hand-Curated Activities
46 activities across 8 categories (hiking, birding, photography, gardening, wellness, running, scenic, family), each with weather constraints, difficulty levels, equipment lists, and time ranges:
{
"name": "Sunset Photography Walk",
"category": "photography",
"difficulty": "easy",
"duration_minutes": { "min": 30, "max": 60 },
"weather_constraints": {
"min_temp_c": 5, "max_temp_c": 38,
"max_wind_kph": 40,
"excluded_conditions": ["heavy rain", "thunderstorm"]
},
"best_time_of_day": ["afternoon", "evening"],
"equipment": ["camera or smartphone", "comfortable shoes"]
}
The activity service pre-filters based on weather constraints before sending candidates to the AI, reducing hallucination and ensuring every suggestion is actually feasible right now.
Frontend: Premium Dark-Mode UI
The frontend is Vite + React with a custom design system featuring:
- Forest-inspired color palette (
#0A0F0Dbackground,#4ADE80nature accents) - Glassmorphism cards with
backdrop-filter: blur(20px) - Micro-animations on hover and state transitions
- GPS auto-detection via OpenStreetMap Nominatim
- Profile persistence in localStorage
- Responsive design that works on mobile for on-the-go use
Deployment: Render
The entire stack runs on Render's free tier:
-
Backend: Node.js Web Service (
outdoor-pulse-api) - Frontend: Static Site with SPA rewrite rules
- Auto-deploys on every
git push
Why Does Open Innovation Matter?
1. Zero-Cost, Accessible to Everyone
OutdoorPulse runs entirely on free tiers — no credit card required anywhere:
- Gemma 4 via OpenRouter: free inference
- Qwen 3.8 via Groq: free fallback
- Render: free hosting
- SerpApi: 100 free searches/month
- ElevenLabs: free tier (boosted with MLH Hacktoberfest promo)
A closed API like GPT-4 would cost ~$0.01-0.03 per recommendation. At scale, that's a real barrier. Open-weight models on free inference providers make this accessible to developers everywhere — including countries where USD payment methods aren't easy to get.
I literally built this entire app without a credit card. Try that with OpenAI.
2. No Vendor Lock-In — Proven in Production
The multi-provider architecture isn't theoretical. During development, Gemma was rate-limited on OpenRouter, and the app seamlessly fell back to Qwen on Groq:
🤖 Trying Gemma 4 31B (via OpenRouter)...
⚠️ Gemma 4 31B (via OpenRouter) failed: rate limited
🤖 Trying Qwen 3.8 27B (via Groq)...
✅ Qwen 3.8 27B (via Groq) succeeded!
Same code, same prompts, different open-weight model. The user never noticed. With a proprietary API, a rate limit means your app breaks.
3. Privacy by Design
Your location, interests, and fitness data go to an open-weight model — not to a company that may train on your inputs. With open weights, you could self-host Gemma on your own hardware and keep everything entirely local. The architecture supports it; just swap the endpoint URL.
4. Transparent Reasoning
Gemma's weights are public. When the AI recommends a "Night Walk" because it's 82°F and humid in Dhaka, you can inspect exactly how the model reasons about weather conditions. With a closed API, the recommendation is a black box.
My Agent Session
The session captures the full build journey: initial concept, scaffolding the full-stack app, debugging Google AI Studio billing issues (pivoted to OpenRouter for free Gemma access), building the multi-provider fallback system, integrating SerpApi weather and ElevenLabs audio, and deploying to Render.
Prize Categories
Render — Best Use of Render: The full-stack app runs on Render's free tier — Node.js Web Service for the API, Static Site for the React frontend. The
render.yamlBlueprint enables reproducible deployment, and auto-deploy triggers on every git push.ElevenLabs — Best Use of ElevenLabs: Voice narration is a core UX feature, not a gimmick. It lets users listen to activity recommendations while physically getting ready to go outside — reducing screen time at the exact moment it matters most for the "Touch Grass" theme.
SerpApi — Best Use of SerpApi: Real-time weather data is the foundation of every recommendation. SerpApi provides temperature, humidity, UV index, wind speed, sunrise/sunset, and conditions — all fed directly into the AI prompt so recommendations match what's actually happening outside your door.
Entire — Best Agent Session: The complete build session is embedded above, showing the real development process including architectural pivots (Google AI Studio → OpenRouter), debugging, and design decisions made in real-time.
Top comments (0)