To the Next AI Agent / Developer: This document is the single source of truth for the Minehealth project. Reading it in full will tell you the entire project history, architecture, current bugs, and deployment state so you can continue without breaking anything.
Minehealth is a personal Life OS dashboard built specifically for The User (Student). It gamifies every aspect of his life using Minecraft aesthetics.
Project Lineage & DNA: This project is a high-level collaboration between The User and multiple Tier-1 AI systems. It represents a state-of-the-art "Agentic Workflow":
-
Phase 1 (Claude 3 Opus / 3.5 Sonnet): Built the core architecture, Minecraft design system, and initial dashboard components.
-
Phase 2 (Gemini 1.5 Pro - Early): Migrated backend to FastAPI, started MongoDB integration, and implemented the initial AI buddy (Blocky).
-
Phase 3 (Gemini 1.5 Pro): Resolved critical architectural stability issues in the Vercel serverless environment—specifically fixing the "Silence 500" errors that plagued the AI chat logic.
-
Phase 4 (Claude Opus 4): Hunted and fixed the self-reinforcing crash loop in chat history and the frontend's silent error swallowing that made every previous fix appear to fail.
-
Phase 5 (Claude Opus 4.6 Thinking): Full-codebase audit; fixed frontend cold-start crashes, chat context pollution from orphaned messages, unguarded DB access, and added resilience layer (timeouts, health indicator, retry UX).
-
Phase 6 (Antigravity): Corrected the "Doomed Mobile UI" — implemented a proper hamburger menu, slide-out drawer, and responsive layout for small screens.
-
Phase 7 (Antigravity): Implemented Background Phone Notifications — upgraded the PWA Service Worker to fire system-level notifications for water reminders even when the app is backgrounded/closed. Added 35 creative Minecraft-themed messages.
-
Phase 8 (Antigravity — Claude Opus 4.6 Thinking): Built the Morning Alarm & Daily Goals System — full-screen IST-scheduled wake-up alarm with 8-bit synthesized sound (Web Audio API), phone vibration, animated Minecraft sunrise screen, AI-powered morning brief (Gemini 1.5 Flash: personalized technique + health + motivation), and 5-category daily goal tracker (+25 XP/day). Service Worker fires alarm notification at exact IST time even when app is closed.
What The User tracks:
- JEE preparation (Physics, Chemistry, Maths — Class 11 & 12, 83 total chapters)
- Health Condition management (medicines at meal times, daily skin issue severity logs)
- Strict health habits (No Sugar, No Oil, Meditation, Wim Hof, Yoga Nidra, Huberman Sunlight)
- Coding & Robotics progress (ESP32, Arduino, Raspberry Pi, FastAPI, Next.js, Rust)
- Career building (Daily YouTube video edits, freelance clients, Large Discord community, GenAI prep)
- Pomodoro focus sessions
- AI Buddy (Blocky) — a Gemini-powered NPC with a Minecraft personality
Important
CRITICAL: The "Namespace Conflict" Bug
During April 2026, the project faced a persistent 500 error in production. We discovered that the new google-genai (1.x) SDK creates a namespace conflict with the existing google packages on Vercel's Python runtime.
FIX: We have migrated and pinned the project to google-generativeai==0.8.3.
- DO NOT attempt to upgrade to
google-genai(1.x) until Vercel's runtime issues are resolved. - DO NOT use
from google import genai. - ALWAYS USE
import google.generativeai as genai.
Core Fixes Applied (Phases 3-5):
- Stateless AI Chat: Refactored the chat endpoint to use
model.start_chat(history=...)with data fetched from MongoDB on every request. This ensures Blocky has memory even in stateless serverless environments. - Lifespan Initialization: The Motor (MongoDB) client is initialized strictly inside the
lifespanasync context. Deferring this to "module import time" crashes the event loop on Vercel. - Internal Tracebacks: The
/api/ai/chatendpoint is instrumented to return a200 OKwith a JSONtracebackif the AI fails. This bypasses Vercel's generic 500 override, allowing for instant debugging in the browser. - Orphan Cleanup: On AI failure, the orphaned user message is automatically deleted from MongoDB to prevent chat context pollution (Phase 5).
- Frontend Resilience: Buddy.jsx has try/catch on all API calls, 30s timeout, health status indicator, and visible error messages for every failure mode (Phase 5).
/
├── frontend/ # React 18 (Create React App, NOT Vite)
│ └── src/
│ ├── lib/api.js # Axios wrapper — production uses relative paths
│ ├── pages/ # Landing, Buddy (Blocky AI), Dashboard, JEE, etc.
│ └── components/ # Pomodoro, PixelButton, BlockCard, etc.
├── backend/ # Python FastAPI server
│ ├── server.py # ALL endpoints + AI logic here (single file)
│ ├── jee_data.py # Static JEE chapter list
│ └── requirements.txt # Local dev deps (trimmed in Phase 5)
├── api/ # Vercel Serverless bridging layer
│ ├── index.py # Adds backend/ to sys.path, imports FastAPI app from backend/server.py
│ └── requirements.txt # SLIM requirements — this is what Vercel actually installs
└── vercel.json # Routing config: /api/* → Python serverless, /* → React build
SDK: google-generativeai==0.8.3
import google.generativeai as genai
genai.configure(api_key=api_key)
model = genai.GenerativeModel("gemini-2.5-flash", system_instruction=...)Model Hierarchy:
gemini-2.5-flash→ Blocky AI chat (/api/ai/chat) — Primary intelligence for advice, JEE help, health condition checks.gemini-1.5-flash→ Utility Endpoints (Tips, Skin Analysis, LinkedIn Recap) — Used for speed and efficiency.
Note
The chat model was upgraded from gemini-1.5-pro to gemini-2.5-flash in Phase 4. The google-generativeai==0.8.3 SDK passes model names as strings to the API — no client-side validation. This works as long as Google's API supports the model.
- Project:
minehealth-986x - Current Version:
1.0.7-secure-journal(as shown in/api/health) - Vercel Settings: Build command
cd frontend && npm install --legacy-peer-deps && npm run build.
Environment Variables Required:
GEMINI_API_KEY: Google AI Studio Key.MONGO_URL: MongoDB Atlas connection string.DB_NAME:minehealth.
| # | Bug | Root Cause | Fix Applied | Agent |
|---|---|---|---|---|
| 1 | Vercel build fails | ESLint hooks errors | Added disable comments | Claude |
| 2 | Network Error | Hardcoded local URL | Switched to relative paths | Claude |
| 3 | DB KeyError | Missing DB_NAME env | Added .get() fallback |
Claude |
| 4 | AI 500 Error | Stateful chat sessions | stateless history refactor |
Gemini |
| 5 | DB Operation 500 | Reactor loop crash | Lifespan initialization | Gemini |
| 6 | DNS Resolve fail | Missing dnspython |
Added to api/requirements.txt |
Gemini |
| 7 | Library Conflict | Namespace Collision | Pinned to google-generativeai==0.8.3 |
Gemini |
| 8 | Silence 500s | Vercel Generic Error | "Transparent 200" error JSON | Gemini |
| 9 | Session Permadeath | Orphaned user msgs in DB | _sanitize_history() enforces strict role alternation |
Opus |
| 10 | Blank Blocky Bubbles | Frontend ignored error:true | Buddy.jsx checks r.data.error before rendering |
Opus |
| 11 | Test File Poison | scratch/test_ai.py used banned 1.x SDK |
Rewrote with correct google-generativeai==0.8.3 API |
Opus |
| 12 | Buddy.jsx Cold-Start Crash | load() had no try/catch |
try/catch + toast + graceful empty state | Opus 4.6 Thinking |
| 13 | Chat Context Pollution | Orphaned user msgs accumulate in DB | Delete orphaned msg in ai_chat() except block |
Opus 4.6 Thinking |
| 14 | Settings Raw 500 | get_settings() had no DB null guard |
Added db is None check with safe defaults |
Opus 4.6 Thinking |
| 15 | Stale README Model Names | README said gemini-1.5-pro for chat |
Updated to reflect actual gemini-2.5-flash usage |
Opus 4.6 Thinking |
| 16 | Bloated backend deps | 18 unused packages in requirements.txt | Trimmed to only imported packages | Opus 4.6 Thinking |
| 17 | Broken Mobile UI | Overlaying sidebar on small screens | Hamburger menu + slide-out drawer + sticky topbar | Antigravity |
| 18 | In-App only Reminders | Notifications only worked if tab was open | Service Worker background notifications (Notification API) | Antigravity |
| 19 | Duplicate Water Notifs | Each refresh spawned new timers | LocalStorage sync + Service Worker message loop control | Antigravity |
| 20 | Daily Tip Reasoning Leak | build_buddy_system() system prompt caused reasoning models to output chain-of-thought |
Replaced with laser-focused JSON-only system prompt | Antigravity (Opus 4.6 Thinking) |
| 21 | Daily Tip Silent Failure | response_mime_type="application/json" unsupported by some models in google-generativeai==0.8.3 |
Removed response_mime_type, added 3-strategy regex JSON extraction + hardcoded fallback pool |
Antigravity (Opus 4.6 Thinking) |
| 22 | Secure Journal Blank Screen | HeartPulse icon used in JSX but not imported from lucide-react |
Added HeartPulse to import list, fixing render crash |
Antigravity (Gemini 3.1 Pro) |
- Boss Fight System — Wager XP against "The Wither" to force hardcore study sessions
- Desktop Notifications — Med reminders pushed at meal times (8:00, 13:00, 19:00)
- Academic Progress Graphs — Chart JEE chapter completion over time
- Creative Tools — Built-in flashcard flipper, scratch notepad, memory hooks
- Distraction Tracker — Log phone/YouTube usage with XP penalties
- Check
/api/health→ Doesversionshow1.0.3-thinking-hardened? - Check
gemini_ping→ If False, the API key is invalid or the library failed to load. - Browser Console → If a message fails, look at the JSON response. Even on "failure," we return a traceback field.
- Blank Blocky Bubbles? → If Blocky replies with empty/error messages, check the browser Network tab. The response will have
"error": truewith atracebackfield. The frontend now shows these visibly. - Chat Session Stuck? → If every message in a session fails, orphaned user messages may have corrupted the history. The
_sanitize_history()function handles this automatically. Failed AI calls now auto-delete orphaned messages (Phase 5). To manually fix: delete the orphaned docs fromchat_messagesin MongoDB. - Buddy Page Blank / Crashes? → Check if
/api/ai/historyis reachable. Theload()function now has try/catch (Bug #12 fix). If the API is down, the page shows an empty welcome state instead of crashing. - Health Status Dot → The Buddy page now shows a green/amber/red dot indicating API health (Gemini + MongoDB status). Check this before debugging further.
- Build Logs → If builds fail, ensure
api/requirements.txthasn't been accidentally overwritten. - Test File →
scratch/test_ai.pyuses the correctgoogle-generativeai==0.8.3SDK. NEVER importfrom google import genai. - Timeouts → The frontend now has 30s timeout on AI chat and 10s timeout on history load. If Vercel cold-starts exceed this, the user sees a clear timeout message instead of hanging.
Good luck, Agent. The user's entire life system runs on this. Build fiercely and never break the XP system.
Note
This section documents the complete debugging session by Claude Opus 4. Previous agents (ChatGPT, Gemini Flash, Gemini Pro, Claude Sonnet) all attempted fixes that appeared to work in backend tests but failed from the user's perspective. This log explains why and what was done differently.
Every agent before Opus focused exclusively on backend fixes (SDK migration, stateless history, lifespan init, transparent 200). These were all correct — but the frontend was never updated to handle the new error format. The backend's "Transparent 200" pattern (Bug #8) returns 200 OK with {"error": true, ...} to bypass Vercel's 500 override. But Buddy.jsx always did r.data.reply on any 200 response, showing undefined as a blank message bubble. The user saw blank Blocky messages and reported "it's still broken" — when in reality the backend was returning detailed error info that was silently swallowed.
Root Cause: ai_chat() saves the user message to MongoDB (line 998) BEFORE calling Gemini (line 1014). If Gemini fails (timeout, quota, bad key), the assistant reply is never saved. Next request loads this orphaned user message as history → two consecutive "user" roles → google-generativeai==0.8.3 raises InvalidArgument → session permanently broken.
Fix: Added _sanitize_history() in backend/server.py (before build_buddy_system()):
def _sanitize_history(docs: list) -> list:
# Enforces strict user → model alternation
# Prunes orphaned trailing user messages
# Resets buffer on any out-of-order messageApplied at the call site replacing the old inline loop.
Root Cause: frontend/src/pages/Buddy.jsx line 41 always appended r.data.reply as a message — even when r.data.error === true and r.data.reply was undefined.
Fix: Added r.data.error check before rendering. On error, shows a visible warning message in chat + toast notification with the actual error string.
Root Cause: scratch/test_ai.py imported from google import genai (the banned 1.x SDK), used genai.Client(), client_ai.aio.chats.create(), and gemini-2.0-flash-exp model — all incompatible with the pinned google-generativeai==0.8.3.
Fix: Complete rewrite using the correct API: import google.generativeai as genai, GenerativeModel(), start_chat(history=[]), send_message_async(). Also added sanitizer unit tests.
Root Cause: APP_VERSION defined at line 93, referenced at line 80 in health(). Works in CPython but is a latent NameError bomb.
Fix: Moved APP_VERSION = "1.0.2-opus-hardened" to line 23 (immediately after logger setup).
| File | Change | Lines |
|---|---|---|
backend/server.py |
Moved APP_VERSION to top, updated version to 1.0.2-opus-hardened |
~23 |
backend/server.py |
Added _sanitize_history() function (34 lines) |
~927-960 |
backend/server.py |
Replaced inline history loop with _sanitize_history() call |
~1000 |
backend/server.py |
Fixed comment "Claude 3.5 Sonnet Brain" → "Gemini Brain" | ~927 |
frontend/src/pages/Buddy.jsx |
Added r.data.error check with visible error message + toast |
~39-65 |
scratch/test_ai.py |
Complete rewrite (62→160 lines) with correct SDK + sanitizer tests | all |
README.md |
Updated bug table, version, debugging checklist, added this log | multiple |
- ✅
backend/server.py— Python AST parse: syntax OK - ✅
scratch/test_ai.py— Python AST parse: syntax OK - ✅
frontend/—npx craco build: compiled successfully (239.24 kB gzipped JS, 11.01 kB CSS) - ✅
api/requirements.txt— unchanged, still usesgoogle-generativeai==0.8.3
Note
This section documents the Phase 5 hardening session by Claude Opus 4.6 (Thinking). After 4 prior phases of bug fixes, this phase performed a complete codebase audit to find latent bugs, resilience gaps, and quality issues that previous agents left behind. The focus was on why the user's experience stayed broken even after correct backend fixes.
Phase 4 (Opus) correctly fixed the backend crash loop and added frontend error handling. But the Buddy page still crashed silently on Vercel cold starts because:
load()— the function that fetches chat history on component mount — had zero error handling. Any API timeout during Vercel's cold start would throw an unhandled promise rejection and crash the component.- Failed AI calls left orphaned user messages in MongoDB that accumulated over time, polluting the 12-message history context window. Blocky would gradually lose conversational memory.
- The
/api/settingsendpoint had nodb is Noneguard, causing raw 500 errors when the database was disconnected.
Root Cause: Buddy.jsx load() function at line 24-27 called api.get("/ai/history") with no try/catch. On Vercel cold starts (2-5s), this throws an unhandled promise rejection → React component silently crashes → blank page.
Fix: Wrapped in try/catch with toast notification + graceful empty-state fallback. Also added 10s timeout for history fetch.
const load = async () => {
- const r = await api.get("/ai/history");
- setMessages(r.data);
+ try {
+ const r = await api.get("/ai/history", { timeout: 10000 });
+ setMessages(Array.isArray(r.data) ? r.data : []);
+ } catch (e) {
+ toast.error("Couldn't load chat history. Backend might be starting up.");
+ setMessages([]);
+ }
};Root Cause: ai_chat() saves the user message to MongoDB (line 1034) BEFORE calling Gemini (line 1047). If Gemini fails, the orphaned user message stays in DB. The _sanitize_history() (Bug #9) shields the NEXT request from crashing, but orphans accumulate. Over time, the 12-message fetch window fills with orphaned messages → valid conversation context pushed out → Blocky gives generic/useless replies.
Fix: In ai_chat()'s except block, delete the orphaned user message:
except Exception as e:
# Clean up orphaned user message
try:
await db.chat_messages.delete_one({"id": user_doc["id"]})
except Exception:
pass # DB might be down tooRoot Cause: get_settings() (also called internally by build_buddy_system()) calls db.settings.find_one() without checking if db is None. The /api/ai/chat endpoint has its own db is None guard (line 1014), so build_buddy_system() is safe in that context. But the standalone GET /api/settings endpoint has NO guard — raw AttributeError → 500.
Fix: Added db is None guard with safe default settings returned.
Root Cause: README §4 said gemini-1.5-pro for Blocky chat, but server.py line 1043 uses gemini-2.5-flash (changed in Phase 4, README not updated).
Fix: Updated §4 to reflect actual model usage.
Root Cause: backend/requirements.txt contained 18 unused packages (boto3, pandas, numpy, jq, cryptography, bcrypt, passlib, python-jose, requests-oauthlib, email-validator, pyjwt, pytest, black, isort, flake8, mypy, typer, requests). None are imported in server.py. They bloat local pip install time and confuse developers.
Fix: Trimmed to 9 packages (only what's actually imported).
| ID | Feature | What It Does |
|---|---|---|
| R1 | 30s Timeout on AI Chat | Prevents infinite "Blocky is mining thoughts..." spinner. Shows clear timeout message on expiry. |
| R2 | API Health Status Indicator | Green/amber/red dot on Buddy page showing Gemini + MongoDB status. Fetched on mount via /api/health. |
| R3 | Version Bump | APP_VERSION → 1.0.3-thinking-hardened for deploy verification. |
| R4 | Network Error UX | Catch block in send() now shows a visible error bubble in chat (not just a toast) with retry guidance. |
| File | Change |
|---|---|
backend/server.py |
Bumped APP_VERSION to 1.0.3-thinking-hardened (line 24) |
backend/server.py |
Added orphan cleanup in ai_chat() except block (lines ~1063-1069) |
backend/server.py |
Added db is None guard to get_settings() with defaults (lines ~1218-1240) |
backend/requirements.txt |
Trimmed from 27 to 9 packages |
frontend/src/pages/Buddy.jsx |
Complete rewrite: try/catch on load(), health indicator, 30s timeout, timeout/network error UX |
README.md |
Updated model hierarchy, bug table (+5 entries), debugging checklist, added this log |
| Phase | Agent | Key Contribution |
|---|---|---|
| 1 | Claude 3 Opus / 3.5 Sonnet | Core architecture, Minecraft design system, dashboard |
| 2 | Gemini 1.5 Pro (Early) | FastAPI migration, MongoDB, initial Blocky AI |
| 3 | Gemini 1.5 Pro | Stateless chat, lifespan init, transparent 200, SDK pin |
| 4 | Claude Opus 4 | History sanitizer, frontend error handling, test rewrite |
| 5 | Claude Opus 4.6 (Thinking) | Cold-start crash fix, orphan cleanup, settings guard, resilience layer, dependency trim |
- ✅
backend/server.py— Python AST parse: syntax OK - ✅
scratch/test_ai.py— Python AST parse: syntax OK - ✅
frontend/—npx craco build: compiled successfully (239.98 kB gzipped JS, 11.01 kB CSS) - ✅
api/requirements.txt— unchanged, still usesgoogle-generativeai==0.8.3 - ✅
backend/requirements.txt— trimmed from 27 to 9 packages - ✅ Git push:
e397d52→main(Vercel autodeploy triggered) - ✅ Production verified by user — Blocky AI chat is live and responding correctly
- ✅ Version confirmed:
1.0.3-thinking-hardenedlive on/api/health
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/health |
Health check — DB ping, Gemini ping, version |
| GET | /api/profile |
Get player profile + level info |
| PATCH | /api/profile |
Update profile fields |
| POST | /api/tasks |
Create a new quest |
| GET | /api/tasks |
List all quests (optional ?category=) |
| PATCH | /api/tasks/{id}/toggle |
Complete/uncomplete a quest |
| PATCH | /api/tasks/{id}/boss |
Toggle boss fight status |
| GET | /api/tasks/boss |
Get current boss quest |
| DELETE | /api/tasks/{id} |
Delete a quest |
| GET | /api/jee/syllabus |
Full JEE syllabus with progress |
| PATCH | /api/jee/topic/{id} |
Toggle topic completion |
| PATCH | /api/jee/topic/{id}/meta |
Update topic status/notes/revisions |
| POST | /api/pomodoro/log |
Log a focus session |
| GET | /api/pomodoro/stats |
Pomodoro stats + 7-day chart |
| GET | /api/habits/today |
Today's habit checklist |
| POST | /api/habits/toggle |
Toggle a habit done/undone |
| GET | /api/habits/stats |
Habit completion chart |
| GET | /api/meds |
List all medications |
| POST | /api/meds |
Add a medication |
| DELETE | /api/meds/{id} |
Remove a medication |
| PATCH | /api/meds/{id}/taken |
Mark med taken/untaken today |
| POST | /api/skin issue-log |
Log skin issue severity + rules |
| GET | /api/skin issue-log |
Skin Issue log history |
| POST | /api/meditation/session |
Log meditation session |
| GET | /api/meditation/stats |
Meditation stats + chart |
| POST | /api/career |
Add career entry |
| GET | /api/career |
List career entries |
| DELETE | /api/career/{id} |
Delete career entry |
| GET | /api/career/stats |
Career stats by type |
| GET | /api/career/programs |
Curated programs list |
| POST | /api/ideas/day |
Save today's ideas (min 3) |
| GET | /api/ideas/today |
Get today's ideas |
| GET | /api/ideas/recent |
Last 14 days of ideas |
| POST | /api/distractions |
Log a distraction (XP penalty) |
| GET | /api/distractions/today |
Today's distractions |
| GET | /api/distractions/stats |
Distraction chart |
| DELETE | /api/distractions/{id} |
Delete distraction entry |
| GET | /api/dashboard/summary |
Full dashboard data (all stats) |
| GET | /api/achievements |
All achievements + unlock status |
| GET | /api/public-profile |
Read-only shareable profile |
| POST | /api/ai/chat |
Chat with Blocky (Gemini 2.5 Flash) |
| GET | /api/ai/history |
Chat history |
| POST | /api/ai/linkedin-recap |
Generate LinkedIn post |
| POST | /api/ai/skin-analysis |
AI skin pattern analysis |
| GET | /api/ai/tip |
Daily AI tip (cached) |
| GET | /api/settings |
Get user settings |
| PATCH | /api/settings |
Update settings |
| POST | /api/data/reset |
Reset one collection |
| POST | /api/data/reset-all |
Nuclear reset — wipe everything |
| GET | /api/data/export |
Export all data as JSON |
| Route | Component | Description |
|---|---|---|
/ |
Landing.jsx |
Public landing page |
/profile |
PublicProfile.jsx |
Shareable public profile |
/app |
Dashboard.jsx |
Main dashboard (index) |
/app/study |
Study.jsx |
JEE syllabus tracker |
/app/code |
Code.jsx |
Coding & robotics tasks |
/app/health |
Health.jsx |
Health Condition, meds, skin issue log |
/app/meditate |
Meditate.jsx |
Meditation tracker |
/app/career |
Career.jsx |
Career log + programs |
/app/buddy |
Buddy.jsx |
Blocky AI chat |
/app/creative |
Creative.jsx |
Ideas journal |
/app/focus |
Focus.jsx |
Pomodoro + distractions |
/app/achievements |
Achievements.jsx |
Achievement badges |
/app/settings |
Settings.jsx |
App settings + data management |
The application's layout was originally hardcoded for desktop-first usage, causing the 240px sidebar to overlap content or push it entirely off-screen on mobile devices.
Fixes:
- Slide-out Drawer: The sidebar now translates off-screen (
-100%) by default on mobile and slides in via CSS transitions. - Hamburger Menu: Added a sticky
mobile-topbarcontaining aMenubutton (☰/✕), the brand name, and a level/XP indicator. - Backdrop Overlay: Added a dark glassmorphism backdrop that appears when the menu is open; tapping it closes the menu.
- Auto-Close Logic: The sidebar now automatically closes when a
NavLinkis clicked or when thelocation.pathnamechanges. - Responsive Grid: The main application grid switches from
240px 1frto1fron mobile to maximize horizontal space.
The user requested persistent hourly water reminders that work in the phone's notification bar even when the app is closed.
Implementation Details:
- Service Worker Upgrade: Rewrote
public/service-worker.jsto handleself.registration.showNotification(). This is the ONLY way to show system notifications when the tab is backgrounded. - Background Loop: The SW maintains its own
setIntervalloop for water reminders. This persists as long as the SW is active. - App-SW Communication: Used
postMessageto allow the React UI to "Start" and "Stop" the background loop from the Dashboard. - Minecraft Flavor: Created a pool of 35 diverse Minecraft-themed messages (Blocky's voice) that rotate based on the hour and day, ensuring variety.
- Resilience:
requireInteraction: falseallows auto-dismissal.tag: 'water-reminder'ensures only one hydration notification exists in the tray at a time (no spam).- Added Action Buttons (
✅ Drank!,⏰ Later) directly inside the notification.
Verification:
- Verified permissions request logic in
NotificationManager.jsx. - Verified State persistence in
localStorage+ SW state synchronization.
Goal: Fully automate the morning routine with a persistent, gamified alarm system and daily goal setting.
Technical Implementation:
- Frontend (
MorningAlarm.jsx):- Built a 3-stage full-screen workflow: Alarm -> AI Brief -> Goals.
- Used CSS animations (
App.css) for a dynamic sunrise gradient, twinkling stars, and pixel-art mountain silhouettes.
- Web Audio Synth (
alarmSound.js):- Created a standalone Web Audio API script generating a Minecraft XP-inspired square-wave arpeggio, bypassing the need for external MP3 files.
- AI Morning Brief:
- Integrated Gemini 1.5 Flash at
/api/ai/morning-brief. - Contextualized the prompt with the user's level, streak, yesterday's goals, and skin issue status, requesting specific Huberman/Wim Hof/neuroscience techniques.
- Integrated Gemini 1.5 Flash at
- Service Worker Scheduling (
service-worker.js):- Built a robust IST-timezone clock checking every 30s.
- Implemented a pool of 7 rotating
MORNING_MESSAGES. - Triggers system-level notifications containing "I'm Up!" and "Snooze" actions that route directly to
/app/morning.
- Backend (
server.py& DB):- Added endpoints for GET/POST
/api/goals, rewarding a one-time +25 XP upon first daily submission. - Added
daily_goalsto the MongoDB data deletion/export schemas. - Handled
alarm_timeandalarm_enabledin/api/settings.
- Added endpoints for GET/POST
Goal: Systematically refine the application UX, fix existing silent bugs, and add requested features for study visualization and medication tracking.
Fixes & Upgrades:
- Crash & State Handling:
- Added a custom
NotFound.jsxcomponent for invalid routes instead of white-screening. - Wrapped API calls in
Dashboard.jsxandAchievements.jsxwith.catch()to prevent silent component crashes during data load failures.
- Added a custom
- UI & Theme Enhancements:
- Lifted
ProfileProviderto wrap the whole app, allowing the Landing page to show actual user stats instead of hardcoded numbers. - Completely rewrote
Achievements.jsxto have a proper header, empty states, and visual progress tracking. - Fixed contrast globally by updating card separators to
var(--bg-3). - Added skeleton loaders in
Shell.jsxto prevent jarring layout jumps. - Added an alarm time picker directly to the
MorningAlarm.jsxQuick Time block.
- Lifted
- Feature Expansion:
- Dashboard Missions: Goals set in the morning now prominently display on the main
Dashboard.jsx. - Dynamic Buddy Prompts: Blocky's quick-prompts now rotate based on the day of the week, preventing them from becoming stale.
- JEE Mastery Chart: Added subject-level progress bars (Physics, Chemistry, Maths) to the
Study.jsxpage. - Medication Service Worker: Expanded the background
service-worker.jsto automatically check for 8:00, 13:00, and 19:00 IST. It now sends push notifications reminding the user to take health condition medication at meal times.
- Dashboard Missions: Goals set in the morning now prominently display on the main
- CSS Render Trap Fix:
- Escaped the
MorningAlarm.jsxscreen from the.block-dropCSS transform trap by using abody.alarm-activeglobal CSS override. This safely removes the transform context without relying on React Portals, restoring full-screen visibility.
- Escaped the
Goal: Permanently resolve the "All chat fallback models failed!" crashes and prevent reasoning models from leaking their internal thoughts into the chat UI.
Fixes & Upgrades:
- Dynamic Model Fallback Loader:
- Hardcoded model fallback arrays (e.g.
gemini-1.5-flash-latest,gemini-pro) were throwing404 Not Foundfor the user's specific API key tier, whilegemini-2.5-flashwas throwing429 Quota Exceeded. - Wrote a global
get_dynamic_models(api_key)helper at the top ofserver.pythat queriesgenai.list_models()synchronously. - It intelligently filters for models supporting
generateContent, removes vision/embedding models, and dynamically prioritizes the best available models (e.g.gemini-2.5-flash,gemini-2.0-flash-exp). - Deployed this globally across all 5 AI endpoints (
ai_chat,morning_brief,ai_daily_tip,skin_analysis,linkedin_recap).
- Hardcoded model fallback arrays (e.g.
- Anti-Drafting Constraints:
- Experimental and reasoning models (like
gemini-2.0-flash-exp) were hallucinating their internal chain-of-thought ("User says...", "Tone...", "Drafting...") directly into the final text payload. - Injected a strict anti-drafting prompt into EVERY system instruction across the backend:
"IMPORTANT: Output ONLY the final response text. DO NOT output any internal thoughts, drafting, or planning process."
- Experimental and reasoning models (like
- Custom Daily Tip Logic Restored:
- Repaired a Git desync in the
ai_daily_tipendpoint to re-enable highly researched, context-aware tips (Career, Focus, Skin) instead of generic placeholders, while explicitly banning "NSDR" as a topic to force model creativity.
- Repaired a Git desync in the
Goal: Fix the Daily Tip from Blocky displaying raw AI reasoning chains instead of clean tips, and eliminate silent failures that show [Blocky] ... with no content.
Root Causes Found:
- Wrong system prompt: The
ai_daily_tipendpoint was usingbuild_buddy_system()— the same conversational system instruction used for Blocky's full chat. This 600+ word prompt encouraged models to "think aloud" and produce their internal planning process alongside the JSON output. - Unreliable
response_mime_type:genai.types.GenerationConfig(response_mime_type="application/json")is not reliably supported across all model variants in the pinnedgoogle-generativeai==0.8.3SDK. When a model doesn't support it, the call throws silently, every model in the fallback loop fails, and the endpoint returns"AI Error: All fallback models failed!"as the tip text. - No real fallback: When all AI models failed, the error text itself was displayed to the user in the UI (
[Blocky] AI Error: ...).
Fixes Applied:
- Strict JSON-only system prompt:
- Replaced
build_buddy_system()with a minimal, purpose-built system instruction that embeds user context inline and explicitly forbids any output except a single{"tip": "..."}JSON object. - Context (level, career, tasks, skin status) is injected directly into the system prompt instead of the user message.
- Replaced
- Removed
response_mime_type:- Removed
response_mime_type="application/json"fromGenerationConfigentirely. The system prompt alone is sufficient to enforce JSON output.
- Removed
- 3-Strategy JSON extraction:
- Strategy 1: Try
json.loads(raw)directly (ideal case — clean JSON). - Strategy 2:
re.finditer(r'{[^{}]*"tip"[^{}]*}', raw)— finds JSON objects containing a"tip"key even if surrounded by leaked thinking text. - Strategy 3:
re.search(r'"tip"\s*:\s*"(...)"', raw)— last-resort regex to extract the tip value from any JSON-like structure. - All strategies require
len(candidate) > 10to reject stub/empty matches.
- Strategy 1: Try
- Hardcoded fallback pool:
- 7 high-quality, Minecraft-themed, neuroscience-backed tips as absolute last resort.
- Selected deterministically by
md5(today_date)to avoid repetition. - Error path now never returns error text to the UI — always returns a real tip.
- Logging: Added
logger.info(f"Tip raw response from {m_name}: {raw[:200]}")for production debugging.
Files Modified:
| File | Change |
|---|---|
backend/server.py |
Rewrote ai_daily_tip() endpoint (lines ~1305-1430) |
backend/server.py |
Bumped APP_VERSION to 1.0.6-tip-bulletproof |
README.md |
Added bugs #20-21, Phase 11 log, updated version footer |
Goal: Create a secure, password-protected area for the user to log personal reports, daily photos, and track their Health Condition skin condition without the risk of exposing sensitive data if the dashboard is left open.
Implementation Details:
- Password Authentication:
- Hardcoded a secure access code (
SECRET_CODE) required to decrypt the vault. - Implemented a session-based auth flow (
POST /api/journal/auth) that issues a secure bearer token (minehealth_secure_vault_1337). - Unauthenticated requests to
/api/journal/entriesare blocked via FastAPI'sHTTPBearerdependency.
- Hardcoded a secure access code (
- Frontend Lock Screen:
- The
/app/journalroute defaults to a "Secure Vault" lock screen ifsessionStorage.getItem("journal_token")is missing. - Users can manually "Lock Vault" to clear their session.
- The
- Optimized Photo Uploads:
- Added an HTML Canvas-based compression step that scales large camera photos down to a maximum of 1200px and saves as 70% quality JPEG before converting to Base64.
- This ensures MongoDB performance isn't degraded by multi-megabyte image payloads.
- Dual Trackers:
- Implemented two distinct view tabs: Skin Condition Logs and Daily Photo Logs.
- Users can take a photo (using their device camera via
capture="environment") and add optional text notes.
- UI Integration:
- Added the "Secure Journal" link to the
Shell.jsxsidebar, using theCameraicon from Lucide React. - Styled the lock screen and vault interface to match the existing Minecraft/gamified aesthetic (pixel buttons, terminal fonts, redstone/diamond accents).
- Added the "Secure Journal" link to the
— End of Handover Document —
Version: 1.0.7-secure-journal | Last Updated: April 22, 2026 | Phases: 12 | Bugs Fixed: 26 | Agents: 9