ワンクリックで
mental-health-dashboard
Practitioner dashboard — patient list, assessment library, Create With AI dialog, navigation bar.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Practitioner dashboard — patient list, assessment library, Create With AI dialog, navigation bar.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Create narrated walkthrough videos and screencasts for the Hermes Mental Health practitioner tutorial. Record, narrate, and publish to GitHub Pages.
Patient profile area — clinical summaries, markdown rendering, demographics editing, consent, assessments, results, invites, and file-based persistence. Synthesize assessment history, severity trends, and progress notes into narrative summaries in English.
Manage assessment invite lifecycle — generate 32-char tokens, create invite links to /a/<token>, track pending/completed status, and manage the invite table.
Review and interpret DSM-5-TR assessment results — score submissions, map severity bands, select and render result charts, detect data-quality issues, and produce clinical interpretations in English.
Draft, audit, and manage patient care plans — synthesize assessment results into structured treatment plans, and evaluate existing plans for clinical gaps, safety concerns, and grounding issues.
Practitioner slash-command workflows for Hermes Mental Health — /assess, /intake, /progress, /safety-check, /privacy-audit.
| name | mental-health-dashboard |
| description | Practitioner dashboard — patient list, assessment library, Create With AI dialog, navigation bar. |
| version | 0.1.0 |
| author | hermes-mental-health |
| license | MIT |
| metadata | {"hermes":{"tags":["mental-health","dashboard","ui"],"category":"mental-health","related_skills":["mental-health-core","mental-health-patient-summary","nextjs-patterns"]}} |
Use when working with the practitioner dashboard UI or when the practitioner asks about:
/patients/[id]data/patients/<id>/profile.json files (see below)useMemo to slice the patients array. Page resets to 1 when page size changes.A "+" button on the dashboard opens a dialog to add new patients. Implementation:
Server action — lib/actions/create-patient.ts (marked "use server"):
FormData with name, ageRange, gender, clinicalBackgroundsanitized-name-<timestamp36>patientSchema via Zoddata/patients/<id>/profile.json (creates directory if needed){ success, patient } or { success: false, error }Dialog component — app/(dashboard)/_components/create-patient-dialog.tsx:
useActionState or plain useState + createPatient() callFilesystem scan — listAllPatients() in lib/data/patients-server.ts (server-only):\n - Reads data/patients/ directory for */profile.json files\n - Parses and validates each, merges with SEED_PATIENTS\n - Deduplicates by id (seed patients win on collision)\n - Marked with \"server-only\" import to prevent fs leaking to client bundle\n - Client-safe patients.ts contains seed data only, no fs
Dashboard page — app/(dashboard)/page.tsx:
listPatients() (now includes filesystem patients)PatientTable/patients/[id])After clicking a patient row, the profile page renders with tabs, clinical summary, and
result detail navigation. Full documentation is in mental-health-patient-summary.
Key entry points from the dashboard:
PatientProfile at app/patients/[id]/_components/patient-profile.tsx — uses
useHydrateAtoms([[activePatientIdAtom, patientId]]) to set active patient synchronously
before first render (avoids 0-count flash on badges)suppressHydrationWarning — localStorage may differ from server seed data?tab= is deferred to useEffect to avoid hydration mismatchThe dashboard shows two assessment sections, in this order:
data/shared/assessments/ via listCustomAssessments(). Shown FIRST, above Available Assessments.data/shared/templates/json/ via listMeasures().Each card shows title, description, slug (monospace), field count badge, chart type badge, scoring type badge, and version badge. Links to editor (/editor/[slug]).
Custom assessment cards (the grid passed custom prop) show a delete button on hover (bottom-2 right-2, opacity-0 group-hover/card:opacity-100). Position at bottom-2 NOT top-2 — the card header has an item count badge at top-right that would overlap. Clicking opens a confirmation Dialog. On confirm, calls deleteCustomAssessment(slug) from lib/actions/assessment-files.ts (server action that deletes data/shared/assessments/<slug>.json), shows toast, and router.refresh().
Dashboard header shows combined count: measures.length + customAssessments.length.
An Agent button (Bot icon, emerald) sits in every page header (Dashboard, Editor, Patient, Result Detail). It is a simple <Link> with context-specifying query params — NOT a modal dialog. Clicking navigates to a dedicated full-route chat page at /agent where users type messages directly (no select options, no prompt picker).
Link hrefs with query params:
// Dashboard
<Link href="/agent?dashboard" ...>Agent</Link>
// Patient profile
<Link href={`/agent?profile&patientId=${patientId}`} ...>Agent</Link>
// Editor
<Link href={`/agent?editor&slug=${slug}`} ...>Agent</Link>
// Result detail
<Link href={`/agent?result&patientId=${result.patientId}&resultId=${result.resultId}`} ...>Agent</Link>
The query params tell the chat page's back button where to navigate (resolved via useSearchParams in the chat component).
Patient sub-page Agent links are dynamic via usePathname() in PatientHeader:
/patients/<id>/assessments → ?assessments&patientId=<id>/patients/<id>/results → ?results&patientId=<id>/patients/<id>/sessions → ?sessions&patientId=<id>/patients/<id>/notes → ?notes&patientId=<id>/patients/<id> (profile) → ?profile&patientId=<id>Nested routes like /patients/<id>/results/<resultId> are handled by pathname.includes("/results/").
Link styling (same className used in all pages):
className="inline-flex items-center gap-1.5 h-7 rounded-[min(var(--radius-md),12px)] px-2.5 text-[0.8rem] text-emerald-400 hover:text-emerald-300 hover:bg-emerald-500/10 transition-colors"
The /agent page (app/agent/page.tsx) is a full chat interface with:
mental-health-development skill)/api/agent/chat which wraps the Hermes gateway run APIui-content-page-agent-chat, ui-header-agent-chat, ui-content-section-agent-sidebar, ui-content-section-agent-messages, ui-content-card-agent-empty/loading/error, ui-bottom-agent-input — all visible when "UI Labels" checkbox is toggledThe old prompt catalog (lib/prompts.ts) and AGENT_SKILLS mapping still exist in the codebase but are not wired to any UI button.
The /agent page quick-action buttons (below the chat input) inject pre-built prompts via inject*Prompt functions in app/agent/_components/agent-chat.tsx:
| Button | Function | File |
|---|---|---|
| Safety Check | injectSafetyPrompt | agent-chat.tsx |
| Care Plan | injectCarePlanPrompt | agent-chat.tsx |
| Session Note | injectSessionNotePrompt | agent-chat.tsx |
| Progress Report | injectProgressReportPrompt | agent-chat.tsx |
When the user says "change the prompt when I click X in the agent chat", edit the inject*Prompt function in agent-chat.tsx — NOT lib/prompts.ts. The lib/prompts.ts file feeds the old AgentModal dialog (mostly unused) but has NO effect on the /agent chat page buttons.
The dashboard page (app/(dashboard)/page.tsx) shows collapsible green HermesPromptHint components next to section headings (English prompts). Each hint has a close button (X icon) that collapses the green box but keeps the trigger button visible so it can be reopened:
assessment-review)assessment-review)These hints are client components (DashboardPatientsHint, DashboardMeasuresHint from _components/dashboard-hints.tsx). The HermesPromptHint component itself lives at components/hermes-prompt-hint.tsx.
The Agent button (above) is a simple <Link href="/agent"> that navigates to the full chat page — no dropdown, no prompt selection.
The editor route (/editor/[slug]) now supports both template measures and custom assessments:
getMeasure(slug) first (template catalog)loadCustomMeasure(slug) from lib/data/custom-assessments.ts (reads data/shared/assessments/<slug>.json)MetadataForm accepts both slug and measure props — uses the full measure object for custom assessments when template metadata (getMeasureTitle/getMeasureMeta) returns nullmeasure prop directly (already supports custom assessments)Uses the Hermes Gateway API server (hermes gateway) at http://127.0.0.1:8642:
/api/assessments/generate → Hermes Gateway API (POST /v1/runs + poll GET /v1/runs/{id}) → validate → savemake hermes-gateway (sets HERMES_HOME to project .hermes/, API_SERVER_ENABLED=true)/goal command as the input field, with the schema spec as instructionsdata/shared/assessments/<slug>.json via terminal Python one-liner (API-mode agent does NOT have write_file tool)measureSchema, fixes slug, rewrites clean copydata/shared/templates/index.json — filesystem-only from data/shared/assessments/make hermes-gateway-curl-testREADME-CREATE-WITH-AI.md<html class="dark"> is unconditionalreferences/nextjs-pitfalls.md — Jotai hydration, SSR boundaries, MDX Editor dark theme, fs isolationWhen the user asks to change a prompt triggered by a quick-action button in the /agent chat page (Care Plan, Session Note, Safety Check, Progress Report), the prompt text lives in app/agent/_components/agent-chat.tsx as inject*Prompt functions. Do NOT edit lib/prompts.ts — that file feeds the old modal dialog and is not wired to the chat page. Editing it has zero effect on the agent chat buttons.
// ✅ RIGHT — edit the inject*Prompt function in agent-chat.tsx
const injectCarePlanPrompt = () => {
setInput(`Audit the existing care plans...`);
};
// ❌ WRONG — lib/prompts.ts has no effect on the /agent chat page
When adding a close button to the green HermesPromptHint box, the X button should ONLY collapse the green box (setExpanded(false)) — NEVER dismiss the entire component or hide the trigger button. The trigger must stay visible so the user can re-expand the box. Do NOT use a dismissed state that makes the component return null — just toggle expanded.
The lib/prompts.ts file and AGENT_SKILLS mapping are ONLY used by the legacy AgentModal dialog. The /agent chat page has its own hardcoded inject*Prompt() functions in app/agent/_components/agent-chat.tsx. When updating the "Care Plan", "Session Note", "Progress Report", or "Safety Check" buttons, edit the corresponding function in agent-chat.tsx — do NOT edit lib/prompts.ts or agent-modal.tsx.
Prompt format preference: AUDIT pattern (evaluate existing content against patient data, return score/strengths/gaps/revisions) — not GENERATE pattern (draft new content from scratch). Use "Audit" verb, not "Review". Include specific output structure: quality score, strengths, clinical gaps, measurable-goal issues, missing interventions, safety concerns, recommended revisions.
Do NOT nest <Button> inside <DialogTrigger asChild> — both render <button>,
causing a hydration error: "In HTML, <button> cannot be a descendant of <button>."
// ❌ WRONG
<DialogTrigger asChild>
<Button>Open</Button>
</DialogTrigger>
// ✅ RIGHT — use onClick on Button directly, no DialogTrigger wrapper
<Button onClick={() => setOpen(true)}>Open</Button>
When a shared module (e.g., lib/data/patients.ts) imports fs, it leaks into client
components that transitively import it. Fix by splitting server-only code into a
separate module:
lib/data/patients.ts ← client-safe (seed data, no fs)
lib/data/patients-server.ts ← server-only (scans filesystem, imports fs)
The server module starts with "server-only" (npm package) to enforce the boundary.
Server components (pages) import from patients-server; client components stay on
patients.
references/screenshot-capture.md — Camera-ready screenshot capture for docs: AppleScript bounds + screencapture -D2 for Edge browser on secondary display, scrolling, multi-screenshot strategy, window managementreferences/screenshot-analysis.md — Pixel-level UI debugging: OCR + PIL color inspection for detecting active tabs, buttons, and layout when vision analysis fails.references/nextjs-pitfalls.md — Recurring Next.js + shadcn + Jotai patterns: hydration fixes, Recharts quirks, server-only modules, patient data architecture, inline editing.references/mdx-editor-dark-mode.md — MDX Editor (@mdxeditor/editor) dark mode integration: required global CSS (hashed class selectors, portal popups, combobox trigger buttons), z-index for shadcn Dialog, plugin setup, text visibility gotchas, SSR guard pattern.references/agent-chat-prompts.md — Agent chat quick-inject button prompts and skills mapping (Care Plan audit, Session Note audit, Progress Report, Safety Check).references/screenshot-capture.md — macOS screenshot capture workflow: display-level capture with screencapture -D2, browser navigation script, multi-section page strategy.references/docs-generation-workflow.md — Batch screenshot capture, prev/next nav links, logo embedding for docs/*.md pages.