Skip to content
This repository was archived by the owner on Aug 5, 2026. It is now read-only.

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Steady - Recovery Companion & Caregiver Buddy System

A GenAI-powered check-in, personal emergency script, and real-time caregiver-linked support system for people navigating substance use recovery in India. Built for the PromptWars (hack2skill) "Build with AI" challenge - this repo covers both the warm-up Step 1 and the main challenge build (same persona, extended into a two-role product).

Persona

Primary persona: the person in recovery, with a caregiver as a linked, real second role - not a generic multi-persona app. Every crisis-moment interaction is designed around the person in recovery; the caregiver side exists specifically to support them in real time, not as a standalone feature.

Approach and logic

Core loop (person in recovery)

  1. Sign up, choosing "In recovery" - one-click Google sign-in or email/password (with a forgot-password flow). Google sign-in is the lower-friction default; email/password is the fallback for anyone who doesn't have or want a Google account. Gets a real 6-character pairing code to share with a caregiver.
  2. Check-in - 3 real screening questions adapted from the WHO ASSIST instrument, plus an open field for their own words about their trigger and their reason to stay clear (lib/data/assist-lite.ts).
  3. Script generation (/api/generate-script) - Gemini (gemini-2.5-flash) drafts a short, personal, WRAP-style emergency script from that context. A real national helpline number is appended programmatically (never generated by the model, to guarantee accuracy) and persisted to Firestore under the user's own uid.
  4. Daily check-in: "I stayed clear today" / "I used today" drives a non-punitive streak (lib/streak.ts) - a lapse resets the current streak but never the longest streak or history, reflecting that relapse is a normal stage-of-change transition, not a failure (see project research docs, §1a).
  5. "I need help right now" (/api/crisis-response) - the saved script is sent back to Gemini with a "this is happening right now" framing for a calming, personalized read-back, and writes a real-time alert to any linked caregiver via Firestore. Shown alongside a guided box-breathing grounding exercise, not an alarm sound - a loud alert raises panic in someone already in distress rather than lowering it.
  6. Opt-in distress-phrase detection (lib/voice.ts) - the person can turn on continuous listening for phrases like "I need help" or "I want to use" (off by default - always-on mic is a real privacy tradeoff, not silently enabled). A match triggers the same crisis flow automatically, after a 3-second cancelable countdown so a single stray phrase doesn't fire an unwanted caregiver alert. Click-to-speak dictation for the check-in trigger note is a separate, unrelated feature and unaffected.
  7. Rewards catalog - streak milestones map to badges and illustrative reward categories (lib/data/rewards.ts). This is explicitly NOT a live commerce/payment integration - real partner deals for coupons/cashback are a business-development step outside a hackathon timebox, and the UI says so rather than pretending otherwise.

Caregiver loop

  1. Sign up, choosing "A caregiver." Enters the recovering person's pairing code to link (links/{recoveringUid}_{caregiverUid} in Firestore, enforced by security rules - see below).
  2. Live dashboard: linked person's current/longest streak and daily buddy-check-in status, via a Firestore onSnapshot listener - no polling, no refresh needed.
  3. Real-time crisis/lapse alerts: the moment the linked person hits "I need help right now" or logs a lapse, a banner appears live on the caregiver's screen.

This is a real, non-mocked, cue → routine → reward loop end to end: the crisis trigger is the cue, the Gemini-generated grounding action is the routine, streak milestones are the reward - and the caregiver is wired into the same loop, not bolted on separately.

How it works (running locally)

npm install
cp .env.example .env   # fill in GEMINI_API_KEY and the Firebase config (see below)
npm run dev

Firebase config values (NEXT_PUBLIC_FIREBASE_*) come from Firebase Console → Project settings → General → Your apps → Web app. These are not secret and are safe to expose client-side. GEMINI_API_KEY is the one real secret and stays server-side only (never sent to the client).

For Google sign-in to work, enable it under Authentication → Sign-in method → Google in the Firebase Console (Email/Password must also be enabled for the fallback path). Also publish firestore.rules via Firestore Database → Rules in the console, or firebase deploy --only firestore:rules with the CLI - a fresh project defaults to denying all access until this is done.

Testing

See TESTING.md for the full breakdown. Summary:

  • npm run test - unit tests (streak logic, ASSIST scoring), no network.
  • npm run test:integration - real Gemini API calls, no mocking.
  • npm run test:rules - Firestore security rules against the real local emulator (firebase emulators:start --only firestore first).
  • E2E - headless Playwright critical path (signup → crisis trigger → caregiver sees the live alert).

Assumptions and known limitations

  • Two dedicated portals, no shared role picker. /user is the entry point for the person in recovery (signup, login, Google sign-in, forgot password, all in one page); /caregiver is the same for caregivers. Each is self-contained specifically so the recovering person's path stays as fast as possible, and so this route tree could be split into two fully separate deployments later without touching the other side. The old shared /signup, /login, /checkin, /script routes still work as redirects to their new locations, for backward compatibility.
  • Logged-in users landing back on /user or /caregiver see the form again rather than an automatic redirect to their dashboard - a known minor UX gap, not a functional bug (the Header still reflects their actual session).
  • Simplified ASSIST scoring, not the official multi-branch WHO algorithm (documented in lib/data/assist-lite.ts).
  • Typed check-in, not voice-first. The problem statement's "zero-typing intervention" ideal is proven out at the AI/decision-logic layer end to end; the Gemini Live API voice layer is a documented next step, not built here due to the timebox.
  • Rewards catalog is illustrative, not a live redemption/commerce system (see above).
  • One helpline surfaced (1800-11-0031) in generated scripts; Tele-MANAS is in lib/data/helplines.ts, ready to surface as a second option.
  • Pairing codes use a 6-character alphanumeric space (no 0/O/1/I ambiguity) with no explicit collision check - acceptable risk at hackathon scale, would need a uniqueness guarantee at real scale.

Known upstream issue

npm audit reports advisories inside two places, neither exploitable via this app's actual runtime/user-facing surface:

  • Next.js 16.2.11's own bundled build-time dependencies (postcss, sharp, the eslint/minimatch chain). Next has not shipped a patched release yet; npm audit fix --force would downgrade to a very old Next version, which is not a real fix.
  • @google/genai's optional MCP-server sub-dependency chain (@modelcontextprotocol/sdk@hono/node-server), unused by this app - we only call ai.models.generateContent, never the SDK's optional local MCP server.

Tracking upstream for patched releases rather than downgrading either.

Tech stack

Next.js 16 (App Router, TypeScript, Tailwind) · @google/genai (server-side only) · Firebase Auth (email/password) + Firestore (client SDK, secured by firestore.rules) · Netlify (hosting).

About

Steady - a GenAI recovery-companion app, built for Google AI Hackathon.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages