This is a submission for the Hacktoberfest Weekend Challenge: Build for a Friend
What I Built
FocusBuddy is a 100% offline, privacy-first task decomposer designed to help individuals dealing with ADHD or executive dysfunction. When facing overwhelming projects—such as "make notes on certain topics of DBMS"—FocusBuddy uses local open-source AI to break the goal into bite-sized, 5-minute micro-steps. It presents these steps strictly one at a time to eliminate overthinking and cognitive overload.
I built this for a friend who frequently experiences task paralysis when starting large academic projects. What they said after testing it:
"Seeing only one step at a time stopped me from overthinking and helped me actually start studying without feeling overwhelmed!"
Demo

(Run index.html in any browser while Ollama is running locally).
Code
Here is the complete source code (index.html) used to build the local frontend:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>FocusBuddy</title>
<style>
body { font-family: Arial, sans-serif; max-width: 600px; margin: 50px auto; padding: 20px; background: #0f172a; color: #f8fafc; }
input, button { padding: 12px; font-size: 16px; margin-top: 10px; width: 100%; border-radius: 8px; box-sizing: border-box; border: none; }
input { background: #1e293b; color: #fff; border: 1px solid #334155; }
button { background: #2563eb; color: white; cursor: pointer; font-weight: bold; }
button:hover { background: #1d4ed8; }
.step-box { background: #1e293b; padding: 20px; border-radius: 8px; margin-top: 20px; border-left: 5px solid #3b82f6; }
.hidden { display: none; }
.btn-group { display: flex; gap: 10px; margin-top: 15px; }
</style>
</head>
<body>
<h1>⚡ FocusBuddy</h1>
<p>Your offline, low-pressure task chunker.</p>
<div id="input-section">
<input type="text" id="taskInput" placeholder="What task feels overwhelming? (e.g., Clean my desk)">
<button onclick="breakDownTask()">Break It Down 🚀</button>
</div>
<div id="loading" class="hidden" style="margin-top:20px;">⏳ Breaking task into micro-steps...</div>
<div id="step-section" class="hidden">
<div class="step-box">
<h3 id="stepHeader">Step 1</h3>
<p id="stepText" style="font-size: 18px; line-height: 1.5;"></p>
</div>
<div class="btn-group">
<button onclick="prevStep()">⬅️ Previous</button>
<button onclick="nextStep()">Next ➡️</button>
</div>
</div>
<script>
let steps = [];
let currentStep = 0;
async function breakDownTask() {
const task = document.getElementById('taskInput').value;
if (!task.trim()) return;
document.getElementById('loading').classList.remove('hidden');
document.getElementById('step-section').classList.add('hidden');
const prompt = `Break down the task "${task}" into 4 to 6 bite-sized, 5-minute micro-steps. Return ONLY a valid JSON array of strings, like ["Step 1 text", "Step 2 text"]. Do not include markdown or commentary.`;
try {
const response = await fetch('http://localhost:11434/api/generate', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'llama3.2',
prompt: prompt,
stream: false
})
});
const data = await response.json();
let text = data.response.trim();
if (text.includes('```
')) {
text = text.replace(/
{% raw %}
```json|```
{% endraw %}
/g, '').trim();
}
steps = JSON.parse(text);
currentStep = 0;
showStep();
} catch (err) {
alert('Error connecting to Ollama. Make sure Ollama is running in the background!');
} finally {
document.getElementById('loading').classList.add('hidden');
}
}
function showStep() {
if (steps.length === 0) return;
document.getElementById('step-section').classList.remove('hidden');
document.getElementById('stepHeader').innerText = {% raw %}`Step ${currentStep + 1} of ${steps.length}`{% endraw %};
document.getElementById('stepText').innerText = steps[currentStep];
}
function nextStep() {
if (currentStep < steps.length - 1) {
currentStep++;
showStep();
} else {
alert('🎉 Amazing work! You completed all the steps.');
}
}
function prevStep() {
if (currentStep > 0) {
currentStep--;
showStep();
}
}
</script>
</body>
</html>
Top comments (0)