Skip to content

Repository files navigation

mh-tool

A supportive mental-health check-in chatbot. This app is not a substitute for professional mental health care — it's a conversational companion, with a deterministic safety check for crisis language that runs independently of the model on every message.

This app is bring-your-own-key: it has no shared OpenAI key of its own. Each visitor pastes their own OpenAI API key into the app (via the control in the top banner) before the assistant will respond to normal messages — the crisis safety check works with no key at all, for anyone.

Setup

npm install
npm run dev

Open http://localhost:3000, then paste your own OpenAI API key into the banner at the top of the page.

Conversations are ephemeral: chat history is never stored server-side or in localStorage, so refreshing the page clears it. The one exception is your OpenAI API key itself, which is saved in your browser's localStorage so you don't have to re-enter it every visit — see components/ApiKeyProvider.tsx for the tradeoffs of that choice.

How it's built

Next.js (App Router, TypeScript) frontend with one backend API route that proxies to OpenAI server-side — each visitor's own API key is relayed through this route per-request (never stored server-side, never logged) so the deterministic crisis pre-check can keep running in front of every message regardless of whether a key is present. Chat history lives only in React state, no database; the API key itself lives in the browser's localStorage (see components/ApiKeyProvider.tsx).

Browser (ChatContainer + your API key) → POST /api/chat → safety pre-check → OpenAI API (your key) → response → Browser
File Role
components/ChatContainer.tsx Owns chat state (messages, isLoading, error), sends the full history plus your API key to /api/chat on each send
components/MessageList.tsx / MessageBubble.tsx / MessageInput.tsx Rendering: message list with auto-scroll, individual bubbles (styled differently for safety responses), the text input
components/DisclaimerBanner.tsx Always-visible banner with crisis hotline numbers and the language/API-key controls, mounted in app/layout.tsx so it's on every screen
components/ApiKeyProvider.tsx / ApiKeySettings.tsx Where your OpenAI API key is entered, stored (localStorage), and read from
app/api/chat/route.ts The only backend logic: validates the request, runs the safety check, calls OpenAI with the visitor-supplied key, maps errors to friendly messages
lib/safety.ts Regex-based crisis-language detector (English and Spanish) — runs before any OpenAI call, independent of whether an API key is present. If it matches, returns a hardcoded response with 988/741741 and skips the API entirely
lib/systemPrompt.ts The instructions given to the model: no diagnosing, encourage professional help for serious concerns, stay conversational, respond in whichever language the user writes in, optionally offer grounding techniques if someone describes rumination
lib/openai.ts Builds an OpenAI client from the per-request visitor-supplied key; OPENAI_MODEL (optional) still comes from env
lib/i18n.ts English/Spanish UI string dictionary
lib/rateLimit.ts Best-effort per-IP rate limiting on /api/chat
lib/types.ts Shared TypeScript types for the request/response shape

Design notes

  • Two independent safety layers — the regex check and the system prompt don't hand off to each other; both run on every turn, so a gap in one doesn't leave the user unprotected.
  • Stateless API route — the client sends the whole conversation each time, so the server holds nothing between requests; "refresh clears everything" follows directly from that rather than needing separate cleanup logic.
  • Synchronous (non-streaming) responses for v1 — simpler client code and an easier-to-reason-about safety-critical path, at the cost of replies appearing all at once rather than typed out.

Scripts

scripts/ contains an unrelated standalone research tool (nature_mh_scraper.py) for finding recent Nature Mental Health publications — not part of the chatbot app.

About

A supportive mental-health check-in chatbot. This app is not a substitute for professional mental health care — it's a conversational companion, with a deterministic safety check for crisis language that runs independently of the model on every message.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages