This is a submission for Weekend Challenge: Passion Edition 2026
What I Built
Passion Pilot is an intelligent, interactive roadmap generator and contextual AI mentor designed to help you master any new hobby or obsession.
When you type in a passion (e.g., "Gaming", "Photography", or "Woodworking") and your current skill level, Passion Pilot uses the Groq API to instantly generate a highly structured learning syllabus. Instead of a boring text list, it dynamically renders your roadmap as a beautiful, interactive Skill Tree where you can track your progress. It also generates a tiered Gear List outlining exactly what equipment you need to buy and how much it will cost.
The coolest feature? The Contextual AI Mentor. The floating chat bubble is deeply integrated with the global UI state. It knows exactly which task node you currently have marked as "Active" and provides hyper-focused, personalized advice based on exactly where you are stuck in your journey!
Demo
Live Project URL: https://passion-pilot-three.vercel.app/
Code
Passion Pilot
Passion Pilot is an AI-powered roadmap generator and contextual mentor designed to help you master any new hobby or obsession.
Built for the DEV.to Hackathon.
Features
- Instant Syllabus Generation: Enter any passion and skill level to receive a highly-structured JSON syllabus outlining phases and tasks.
- Dynamic Gear List: Generates a tiered gear list required to pursue the hobby, complete with estimated costs.
- Interactive Skill Tree: Visualize your learning roadmap dynamically with interactive nodes and progress tracking.
- Contextual AI Mentor: The built-in AI chat bubble is deeply integrated with the UI state. It knows exactly which task you are currently working on and gives hyper-focused, contextual advice.
Tech Stack
- React & Vite
- Zustand (Global State Management)
- Tailwind & Vanilla CSS (Dark Mode / Glassmorphism)
- Groq API (Llama 3.3 for lightning-fast structured JSON output)
Getting Started
- Clone the repository:
git clone https://github.com/rahulagarwal18/passion-pilot.git
cd passion-pilot
- Install dependencies:
npm install
-
Configure your…
How I Built It
I built this application using a modern, lightning-fast frontend stack:
- React & Vite: For a rapid, component-driven frontend architecture.
- Tailwind & Vanilla CSS: To design a premium, dark-mode dashboard with glassmorphism elements.
- Zustand: For complex global state management.
- Groq API & Llama-3.3-70b-versatile: For blazing fast AI inference.
1. Global State Management (Zustand)
To make the AI Mentor truly "context-aware", I needed the chat component to know exactly what the user was looking at. I used Zustand to create a global store that tracks the user's active task anywhere in the app:
import { create } from 'zustand'
const usePassionStore = create((set) => ({
passion: '',
skillLevel: '',
roadmap: null,
activeTask: null, // Tracks the node the user is currently working on!
isGenerating: false,
setPassion: (passion) => set({ passion }),
setSkillLevel: (skillLevel) => set({ skillLevel }),
setRoadmap: (roadmap) => set({ roadmap }),
setActiveTask: (task) => set({ activeTask: task }),
setIsGenerating: (isGenerating) => set({ isGenerating }),
}))
export default usePassionStore
2. The Contextual AI Mentor
By subscribing to the activeTask state, the Chatbot component automatically injects the exact task the user is struggling with into the AI prompt. This means you don't have to explain your problem to the AI—it already knows!
import React, { useState } from 'react';
import usePassionStore from '../store/usePassionStore';
import { askMentor } from '../services/gemini';
import { Send, Bot, Sparkles } from 'lucide-react';
export default function ContextualChat() {
const { activeTask, passion } = usePassionStore();
const [messages, setMessages] = useState([]);
const [input, setInput] = useState('');
const handleSend = async () => {
if (!input.trim()) return;
// Injecting the global UI state context directly into the chat!
const contextStr = activeTask
? `The user is currently working on this specific task: "${activeTask.title}".`
: `The user is learning about ${passion}.`;
const userMsg = { role: 'user', content: input };
setMessages(prev => [...prev, userMsg]);
setInput('');
try {
const response = await askMentor(passion, activeTask, input);
setMessages(prev => [...prev, { role: 'assistant', content: response }]);
} catch (e) {
console.error(e);
}
};
// ... rendering logic ...
}
3. Forcing Strict JSON with Llama 3
One of the biggest challenges was parsing the AI's response into a predictable UI. I engineered a highly specific prompt to force the Llama model to return nothing but strict JSON, bypassing markdown formatting:
export async function generateSyllabus(passion, skillLevel) {
const apiKey = import.meta.env.VITE_GROQ_API_KEY;
if (!apiKey) throw new Error("Missing Groq API Key");
const prompt = `You are a master mentor for the topic: "${passion}".
The user is at a "${skillLevel}" skill level.
Generate a structured learning roadmap and a gear list.
You MUST respond ONLY with a raw, valid JSON object. Do not include markdown formatting like \`\`\`json.
...`;
const response = await fetch("https://api.groq.com/openai/v1/chat/completions", {
method: "POST",
headers: {
"Authorization": `Bearer ${apiKey}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
model: "llama-3.3-70b-versatile",
messages: [{ role: "user", content: prompt }],
temperature: 0.7,
response_format: { type: "json_object" }
})
});
const data = await response.json();
return JSON.parse(data.choices[0].message.content);
}
The Engineering Pivot:
Originally, I intended to build this using Google's experimental Gemini models. However, halfway through the hackathon, I ran into unexpected account restrictions with my Google Cloud preview keys, which completely blocked the API. With the clock ticking, I engineered a rapid pivot to the Groq API. Because Groq's Llama 3.3 model is incredibly fast and supports strict JSON schema generation, the transition was incredibly seamless. Pivoting mid-hackathon to a completely different AI provider while keeping the UI parsing logic intact was a fantastic exercise in building resilient, loosely-coupled architectures!




Top comments (0)