# Project export: Somni AI

This document was generated by HackStack to give an AI agent context about a hackathon project. Sections are labeled with their provenance; content marked as truncated was cut to keep this document small.

## Project metadata

- Hackathon: TreeHacks 2026
- Tagline: Your smartwatch is collecting sleep data every single night — but what does it actually mean for your health? We built a system that turns those patterns into clinical intelligence.
- Devpost: https://devpost.com/software/somni-ai
- GitHub: https://github.com/KartikeyaGoel/treehacks
- Demo: https://treehacks-six.vercel.app/
- Video: https://player.vimeo.com/video/1165088350?byline=0&portrait=0&title=0#t=
- Team: 3 GitHub contributor(s) — KartikeyaGoel (5 commits), Claude Sonnet 4.5 (2 commits), Bilalmkhn07 (2 commits)

## Devpost submission (written by the team)

### Inspiration

Over 100 million people wear sleep trackers, yet the data sits underutilized in app dashboards. We asked: what if disrupted sleep isn't just about being tired, but an early biomarker for serious health conditions? Sleep is one of the body's most sensitive indicators — changes in sleep architecture can precede clinical disease by months or years. We built SOMNI AI to transform wearable sleep data into evidence-based clinical intelligence, empowering people to detect health risks early and have informed conversations with their doctors.

### What it does

SOMNI AI is a multi-agent clinical evidence synthesis platform that analyzes 30 days of sleep data from Apple Health, Fitbit, or Oura and generates two comprehensive reports: Statistical Analysis: Computes z-scores using standard error of the mean (SEM) to detect deviations from personal baseline Calculates Sleep Health Deviation Index (SHDI) — a weighted composite of fragmentation, deep sleep, REM, efficiency, and variability Identifies sleep phenotypes (fragmentation-dominant, deep sleep reduction, REM instability, efficiency instability) Patient Report: Written at 8th-grade reading level, empathetic and non-alarming, designed to be shared with family members. Includes "What This Does NOT Mean" section and clear next steps. Clinical Report: GRADE-style evidence for healthcare providers with structured tables, effect sizes, evidence strength ratings (strong/moderate/emerging), limitations, and screening recommendations.

### How we built it

Multi-Agent Architecture: We built a sub-agent team system powered by Claude as the main orchestrator. Each sub-agent has its own context window and specializes in a specific task: Literature Search Agent: Queries PubMed using NCBI E-utilities Medical Reasoning Agent: GPT-4.5 with specialized prompts for ranking risk domains and generating structured reasoning traces Evidence Assessment Agent: Evaluates consistency across sources and provides refinement instructions Guidelines Agent: BrightData integration for CDC/AHA-style clinical guidelines and health disparity data Consensus Agent: Perplexity Sonar queries for scientific consensus and controversy Agents communicate like a real research team — when conflicts are detected, the assessment agent instructs the search agent to refine queries, and the system re-searches before finalizing reports. Technical Implementation: Frontend: Next.js 14 App Router, React, Tailwind CSS Backend: Serverless API routes on Vercel (single deployment, no separate backend) Statistical Engine: Pure TypeScript implementation of sleep analysis algorithms (30-day baseline, SEM-based z-scores, SHDI calculation, phenotype classification) APIs: Claude (orchestration), GPT-4.5 (reasoning), PubMed (literature), BrightData (guidelines), Perplexity Sonar (consensus) Safety: Prompt injection protection at every API boundary, context compaction for token efficiency Data Parsing: Support for Apple Health XML, Fitbit CSV, and Oura CSV formats

### Challenges we ran into

1. Context Window Management Across Sub-Agents: With 30 days of sleep data, multiple research papers, and multi-turn agent conversations, we hit token limits quickly. We solved this with context compaction strategies that preserve critical information while summarizing less relevant details, and by giving each sub-agent its own focused context window. 2. Evidence Synthesis Without Over-Claiming: Medical information requires extraordinary precision. We had to build a feedback loop where the evidence assessment agent evaluates source quality and consistency, flagging conflicts before the system writes reports. This ensures we never make claims stronger than the evidence supports. 3. Balancing Technical Sophistication with Readability: The patient report needed to be accessible to someone with no medical background, while the clinical report needed to meet evidence-based medicine standards. We iterated extensively on tone, reading level, and structure to serve both audiences without compromising either. 4. Autonomous Agent Reliability: Getting Claude to consistently choose the right sub-agent at the right time required careful prompt engineering and tool design. We implemented explicit pipeline tracking so we could debug and optimize the decision-making flow.

### Accomplishments we're proud of

Sub-Agent Team Architecture: We didn't just chain API calls — we built agents that genuinely collaborate, with separate context windows and inter-agent communication protocols. Evidence-Based Medicine Standards: Our clinical reports follow GRADE methodology with explicit evidence strength ratings, effect sizes, and limitations — this is the standard used by top medical journals. Human-Centered Design: The patient report opens with validation, not alarm. It's written to empower, not frighten. We tested it with non-technical readers to ensure accessibility. Production-Ready on Day One: Single Vercel deployment, TypeScript-only analysis engine, full PDF export, parser support for three major wearable platforms. This isn't a demo — it's deployable. Prompt Injection Protection: We hardened every API boundary to prevent malicious inputs from compromising the integrity of medical analysis.

### What we learned

Agent orchestration is harder than it looks. Building a system where multiple AI agents communicate and refine each other's work required deep thinking about tool design, context management, and feedback loops. We learned that autonomous doesn't mean hands-off — it means building the right constraints. Medical applications demand a different standard. We couldn't treat this like a typical hackathon project. Every claim needed a citation. Every report needed disclaimers. Every edge case needed careful handling. We learned to think like clinical researchers, not just engineers. Sleep data is incredibly information-rich. Even "simple" metrics like awakenings or REM percentage can correlate with metabolic, cardiovascular, and neurological health. The challenge isn't finding signals — it's interpreting them responsibly.

### What's next

for SOMNI AI 1. Longitudinal Tracking: Extend analysis beyond 30 days to detect long-term trends and seasonal patterns. Add alerts for significant trajectory changes. 2. Provider Integration: Build FHIR-compliant export so clinical reports can be sent directly to electronic health records with patient consent. 3. Expanded Biomarkers: Integrate heart rate variability, SpO2, and activity data for multi-modal health intelligence. 4. Clinical Validation Studies: Partner with sleep labs and primary care clinics to validate our deviation indices against clinical outcomes. 5. Disparity-Aware Recommendations: Use BrightData more extensively to ensure recommendations account for population-specific risk factors and access barriers. 6. Explainability Dashboard: Add visualizations showing exactly which sleep patterns triggered which research associations, making the "black box" transparent. SOMNI AI: Detecting tomorrow's health crisis in tonight's sleep.

## README (from the GitHub repository)

# SOMNI AI - Sleep Health Intelligence System

🏆 **TreeHacks 2026 Project** | Multi-Agent Clinical Evidence Synthesis

## 🎯 Overview

SOMNI AI transforms consumer wearable sleep data into actionable health intelligence through **autonomous multi-agent scientific analysis**. The system detects statistical deviations from personal sleep baselines and maps patterns to peer-reviewed longitudinal research associations.

**Core Thesis**: Sleep deviation is an early biomarker of systemic health drift. SOMNI AI detects trajectory shifts before clinical disease manifests.

### Key Features

- 📊 **Statistical Sleep Analysis** - Z-scores, trend detection, variability indices
- 🤖 **Multi-Agent Orchestration** - Claude SDK → OpenAI o1 → PubMed → BrightData → Perplexity
- 📝 **Dual Report Generation** - Patient-friendly (8th grade) + Clinical (evidence-graded)
- 🔬 **Scientific Rigor** - GRADE methodology, effect sizes, confidence intervals
- 🚀 **Production Architecture** - Next.js 14 App Router, FastAPI, Edge streaming

## 🚀 Quick Start

### Prerequisites

- Node.js 18+
- Python 3.11+
- API Keys (Anthropic, OpenAI, Perplexity, BrightData)

### Installation

```bash
# Install Node.js dependencies
npm install

# Install Python dependencies
cd python
pip install -r requirements.txt
cd ..

# Set up environment variables
cp .env.example .env
# Edit .env with your API keys
```

### Running the Application

```bash
# Terminal 1: Start Python backend
cd python
python api/main.py

# Terminal 2: Start Next.js frontend (in project root)
npm run dev
```

Open [http://localhost:3000](http://localhost:3000)

## 📁 Project Structure

```
somni-ai/
├── app/                        # Next.js 14 App Router
│   ├── page.tsx                # Landing page with upload
│   ├── analysis/[id]/page.tsx  # Analysis results
│   └── api/                    # API routes
├── lib/
│   ├── agents/                 # Multi-agent orchestration
│   └── reports/                # Report generators
├── python/
│   ├── sleep_analysis/         # Statistical analysis engine
│   └── api/                    # FastAPI backend
├── components/ui/              # shadcn/ui components
└── public/demo_data/           # Sample datasets
```

## 🏆 Prize Narratives & Demonstrations

### Greylock — 5+ API Agent with Feedback Reasoning

**Criterion:** Best hack with an agent that reasons about feedback to dynamically complete complex tasks.

**How we meet this:**
- **5+ API sequence:** Claude (orchestrator) → OpenAI o1 (medical reasoning) → PubMed (literature) → BrightData (guidelines) → Perplexity Sonar (consensus)
- **Feedback loop:** `assess_evidence_quality` tool evaluates consistency; returns `refine_query`, `broaden_query`, or `proceed`. When conflicts detected, Claude refines search and re-queries.
- **Visible proof:** "Multi-API Pipeline" card on analysis page shows all services used. Terminal logs show `[Pipeline]` sequence and `[Feedback]` refinements.

**Demo points:** "Our agent autonomously chooses which API to call and when. When evidence is inconsistent, it refines the query and re-searches before writing reports."

---

### OpenAI — Most Creative Use of API

**Criterion:** Top three teams that use OpenAI API most creatively.

**How we meet this:**
- **o1 as medical reasoning engine:** Dedicated system prompt frames task as research associations and risk domain ranking (not diagnosis).
- **Structured reasoning:** Ask for step-by-step reasoning trace, then structured output (ranked domains, confidence, screening, reasoning).
- **`reasoning_effort: 'high'`:** Uses o1's extended reasoning for medical analysis.

**Demo points:** "We use o1 creatively as a clinical reasoning engine with a specialized system prompt. It stays strictly in research associations while providing explicit reasoning traces."

---

### Anthropic Human Flourishing

**Criterion:** Patient report reads empathetically (test with family). Show how AI serves human potential.

**How we meet this:**
- **Empathetic tone:** Opening validates effort ("Taking an interest..."), normalizes variation ("Many people see temporary changes").
- **Family-tested design:** Report designed for reading with family members (see `docs/human-flourishing-note.md`).
- **No alarm:** 8th-grade reading level, hopeful framing, clear disclaimers.

**Demo points:** "We designed the patient report to be read with a parent or partner — supportive, clear, and without fear. AI should make life better by making health intelligence accessible."

---

### Anthropic Best Agent (Claude SDK)

**Criterion:** Autonomous AI application that tackles real problems.

**How we meet this:**
- **Autonomous tool use:** Claude agent chooses when to call each of 5 tools based on evidence quality.
- **Real problem:** Turning messy wearable data into trustworthy, evidence-based health intelligence.
- **No hand-coded sequence:** Agent dynamically plans pipeline each run.

**Demo points:** "The orchestrator is a Claude agent with 5 tools. It autonomously decides the pipeline, reasons about evidence, and only then writes reports."

---

### OpenEvidence — Clinical Info & Healthcare Track

**Criterion (Clinical Info):** Convert clinical data into product that improves understanding/decision-making/care delivery.
**Criterion (Healthcare):** Most innovative healthcare product.

**How we meet this:**
- **Clinical data sources:** PubMed (literature), BrightData (guidelines), Perplexity (consensus).
- **Dual products:**
  1. **Patient report:** Improves understanding (empathetic, actionable, clear next steps)
  2. **Clinical report:** Supports decision-making (GRADE evidence, screening suggestions, differential diagnosis)
- **Innovation:** Multi-agent AI + wearable data + evidence synthesis, strictly non-diagnostic.

**Demo points:** "We convert existing clinical data into two reports: one for patient understanding, one for clinician decision-making. That's healthcare innovation with clear boundaries."

---

### TreeHacks Most Impactful

**Criterion:** Potential to create significant positive change or address pressing societal issue.

**How we meet this:**
- **Early warning system:** Sleep deviation as biomarker of systemic health drift before clinical disease.
- **Preventive focus:** Detect trajectory shifts early so people and providers can act sooner.
- **Equity angle:** Consumer wearable analysis accessible where sleep labs are scarce.

**Impact statement:** "SOMNI AI turns wearable data into evidence-based insights so people can spot patterns before they become disease — reducing healthcare burden and supporting preventive, equitable access to understanding."

**Demo points:** "We're not diagnosing — we're surfacing research-backed patterns early. That's preventive, person-centered, and reduces pressure on the system."

---

### Vercel — Best Use of Vercel

**Criterion:** Best leverages Vercel to build, deploy, and scale production-ready app.

**How we meet this:**
- **Single deployment:** TypeScript sleep analysis (no Python backend required) — everything on Vercel.
- **Next.js 14 App Router:** Server components, API routes, serverless functions.
- **Production-ready:** Full deployment with caching and edge capabilities.

**Demo points:** "The whole app runs on Vercel — frontend and APIs. We ported sleep analysis to TypeScript so there's no separate backend. One deploy, production-ready."

---

### BrightData — Best AI-Powered Web Hack

**Criterion:** Use BrightData in an innovative way.

**How we meet this:**
- **Innovative use:** Pull public health guidelines and disparity data (CDC/AHA-style) into agent pipeline.
- **Value-add:** Grounds recommendations in current guidelines; surfaces population-level context (disparities).
- **Real usage:** `BRIGHTDATA_API_KEY` set in production; "BrightData: real" shown in UI.

**Demo points:** "BrightData feeds our agent with guideline and disparity datasets so recommendations align with public health guidance."

---

### Perplexity — Best Use of S

[README truncated for size]

## Detected evidence (automated analysis)

Indexed codebase: 54 recognized source files, 280 KB.
- Anthropic (technology) — detected in the code
- CSS (language) — detected in the code
- FastAPI (technology) — detected in the code
- JavaScript (language) — detected in the code
- Next.js (technology) — detected in the code
- OpenAI (technology) — detected in the code
- Python (language) — detected in the code
- React (technology) — detected in the code
- Tailwind CSS (technology) — detected in the code
- TypeScript (language) — detected in the code
- Vercel AI SDK (technology) — detected in the code
- Vercel (technology) — claimed on Devpost, not found in the code
- AI coding agent: Claude Code — evidence: commit authorship or trailers

## Codebase structure (from repository index)

### Files (67 of 67)

```
.env.example
.gitignore
.playwright-mcp/console-2026-02-14T19-58-09-882Z.log
app/analysis/[id]/page.tsx
app/api/analyze/route.ts
app/api/export-pdf/route.ts
app/api/generate-reports/route.ts
app/api/get-analysis/route.ts
app/globals.css
app/layout.tsx
app/page.tsx
components/ui/alert.tsx
components/ui/badge.tsx
components/ui/button.tsx
components/ui/card.tsx
components/ui/label.tsx
components/ui/progress.tsx
components/ui/toast.tsx
docs/DEMO_DATA_GUIDE.md
docs/DEMO_QUICK_REF.md
docs/DEMO_SCRIPT.md
docs/DEPLOY_VERCEL.md
docs/human-flourishing-note.md
docs/plans/DEPLOYMENT_AND_FEATURES_PLAN.md
docs/plans/HACKATHON_PRIZES_PLAN.md
docs/plans/vercel-deployment-cache-and-logging.md
docs/TEST_RESULTS.md
jest.config.js
jest.setup.js
lib/agents/__tests__/pubmed.test.ts
lib/agents/orchestrator.ts
lib/agents/types.ts
lib/cache.ts
lib/claude-orchestrator.ts
lib/reports/clinical-pdf.tsx
lib/reports/clinical-report.ts
lib/reports/generate-pdf.ts
lib/reports/patient-report.ts
lib/sleep-analysis/analyzer.ts
lib/sleep-analysis/index.ts
lib/sleep-analysis/types.ts
lib/sleep-analysis/validators.ts
lib/utils.ts
next.config.js
package.json
playwright.config.ts
postcss.config.js
public/demo_data/demo_dramatic.csv
public/demo_data/demo_healthy_30days.csv
public/demo_data/demo_sick_30days.csv
public/demo_data/demo_ultra_dramatic.csv
public/demo_data/fitbit_30days.csv
public/demo_data/fitbit_sample.csv
public/demo_data/README.md
python/anomaly_detector.py
python/api/__init__.py
python/api/main.py
python/pytest.ini
python/requirements.txt
python/sleep_analysis/__init__.py
python/sleep_analysis/core.py
python/sleep_analysis/models.py
python/sleep_analysis/validators.py
README.md
start.sh
tailwind.config.ts
tsconfig.json
```

### Dependencies

- package.json: @anthropic-ai/sdk@^0.30.1, @playwright/test@^1.41.2, @radix-ui/react-alert-dialog@^1.0.5, @radix-ui/react-dialog@^1.0.5, @radix-ui/react-dropdown-menu@^2.0.6, @radix-ui/react-label@^2.0.2, @radix-ui/react-progress@^1.0.3, @radix-ui/react-separator@^1.0.3, @radix-ui/react-slot@^1.0.2, @radix-ui/react-toast@^1.1.5, @react-pdf/renderer@^3.4.2, @types/jest@^30.0.0, @types/node@^20.11.17, @types/react@^18.2.55, @types/react-dom@^18.2.19, @vercel/kv@^3.0.0, ai@^3.0.23, autoprefixer@^10.4.17, class-variance-authority@^0.7.0, clsx@^2.1.0, eslint@^8.56.0, eslint-config-next@14.2.35, fast-xml-parser@^5.3.6, jest@^30.2.0, jest-environment-node@^30.2.0, lucide-react@^0.344.0, nanoid@^5.0.5, next@14.2.35, openai@^4.26.0, postcss@^8.4.35, prettier@^3.2.5, react@^18.2.0, react-dom@^18.2.0, react-markdown@^10.1.0, recharts@^2.12.0, remark-gfm@^4.0.1, simple-statistics@^7.8.8, tailwind-merge@^2.2.1, tailwindcss@^3.4.1, tailwindcss-animate@^1.0.7, typescript@^5.3.3, zod@^3.22.4
- python/requirements.txt: fastapi@>=0.100.0, httpx@>=0.24.0, lxml@>=4.9.0, numpy@>=1.24.0, pandas@>=2.0.0, pydantic@>=2.0.0, pydantic-settings@>=2.0.0, pytest@>=7.4.0, pytest-asyncio@>=0.21.0, pytest-cov@>=4.1.0, python-dotenv@>=1.0.0, python-multipart@>=0.0.6, scipy@>=1.10.0, statsmodels@>=0.14.0, uvicorn[standard]@>=0.23.0

### Recent commits (newest first)

- fixing
- vercel fixes
- cleanup
- final changes
- feat: Complete TreeHacks 2026 prize strategy + visual redesign
- 2 more plans need to be scoped out
- feat: Add 4 production features for Vercel deployment
- changes
- Add deployment and features plan for collaborators
- feat: Complete SOMNI AI - TreeHacks 2026 submission
- Medsense project scaffold
- Initial commit

## Key source files (fetched from GitHub, selected and truncated for size)

### docs/human-flourishing-note.md

```markdown
# Human Flourishing: Family-Tested Patient Report

The SOMNI AI patient report is designed to be read with or to a family member (parent, partner, or trusted person).

## Design Principles

- **8th-grade reading level** (Flesch-Kincaid scoring)
- **Hopeful, empathetic tone** that validates effort
- **Normalizes variation** ("Many people see temporary changes...")
- **Clear disclaimers** — "What This Does NOT Mean" section
- **Actionable next steps** — "What You Can Do"
- **Avoids alarming language** — frames findings as patterns to understand, not problems to fear

## Empathy Elements

### Opening Validation
"Taking an interest in your sleep patterns is a positive step toward understanding your health."

### Normalization Statement
For non-stable findings: "Many people experience temporary changes in sleep patterns. Our goal is to help you understand patterns over time, not to cause worry. Sleep naturally varies, and these observations are meant to support conversations with your provider."

### Supportive Framing
- Findings presented as research associations, not diagnoses
- Confidence levels clearly stated
- Uncertainty acknowledged
- Agency emphasized ("What You Can Do")

## Testing

- Designed for family reading: suitable for sharing with loved ones in healthcare conversations
- Reviewed for clarity and emotional tone
- Tested to ensure it feels supportive, not clinical or scary

## Alignment with Human Flourishing

This approach aligns with our belief that **AI technology should serve human potential** by:
- Making health intelligence **accessible** (clear language, visual aids)
- Making it **understandable** (no jargon, explained statistics)
- Making it **supportive** (empathetic tone, hope-focused)
- **Reducing fear** (disclaimers, normalization, actionable steps)

By designing the patient report to be shared with family members, we ensure that sleep health insights strengthen relationships and support informed healthcare conversations — not create anxiety or confusion.

---

**For judges:** This document demonstrates our commitment to the Anthropic Human Flourishing prize criterion: "test with a family member" and "show how AI can make life better."

```

### docs/DEPLOY_VERCEL.md

```markdown
# Deploy SOMNI AI to Vercel

## Is the app ready?

Yes. The app is set up for a single Vercel deployment:

- **No Python backend required**: When `PYTHON_API_URL` is not set (default on Vercel), the analyze API uses the TypeScript sleep-analysis pipeline in `lib/sleep-analysis/`.
- **Build**: `npm run build` succeeds.
- **Cache**: Uses in-memory cache by default. For persistence across serverless invocations, set up [Vercel KV](https://vercel.com/docs/storage/vercel-kv) and add `KV_REST_API_URL` and `KV_REST_API_TOKEN` (optional for demo).

## How to deploy

### 1. Push your code to GitHub

Ensure your project is in a GitHub repository (e.g. `your-username/treehacks`).

### 2. Import the project in Vercel

1. Go to [vercel.com](https://vercel.com) and sign in (GitHub).
2. Click **Add New…** → **Project**.
3. Import your GitHub repo (e.g. `treehacks`).
4. Leave **Framework Preset** as **Next.js** and **Root Directory** as `.`.
5. Click **Deploy**. The first deploy may succeed without env vars; the app will work for analysis; report generation needs API keys (step 3).

### 3. Add environment variables

In the Vercel dashboard: **Project → Settings → Environment Variables**. Add (for production and preview if you want):

| Name | Value | Required for |
|------|--------|----------------|
| `ANTHROPIC_API_KEY` | Your Anthropic API key | Claude orchestration |
| `OPENAI_API_KEY` | Your OpenAI API key | o1 medical reasoning |
| `PERPLEXITY_API_KEY` | Your Perplexity API key | Sonar consensus (optional; mock if missing) |
| `BRIGHTDATA_API_KEY` | Your Bright Data API key | Guidelines (optional; mock if missing) |

Optional (for persistent cache across requests):

| Name | Value |
|------|--------|
| `KV_REST_API_URL` | From Vercel KV (Storage) |
| `KV_REST_API_TOKEN` | From Vercel KV |

Do **not** set `PYTHON_API_URL` so the app uses the TypeScript pipeline on Vercel.

### 4. Redeploy

After saving env vars, go to **Deployments** → **⋯** on the latest deployment → **Redeploy** so the new variables are applied.

## After deploy

- **App URL**: `https://your-project.vercel.app`
- **Analyze**: Upload a CSV or Apple Health XML (≥14 days) on the home page.
- **Reports**: After analysis, the report page calls the generate-reports API (requires Anthropic + OpenAI keys for full multi-agent flow).
- **PDF export**: Uses the Node.js runtime and works on Vercel.

## Notes

- **Python**: The repo includes a Python backend for local dev. On Vercel only the Next.js app runs; analysis is 100% TypeScript.
- **Rewrite**: `next.config.js` has a rewrite for `/python-api/*` to localhost. On Vercel that target does not exist; the main app does not use it. Ignore or remove that rewrite if you prefer.
- **Cache**: Without Vercel KV, analysis and report data are stored in memory per serverless instance and can be lost between requests or after cold starts. For a demo or single-user use this is usually fine; for producti
[truncated — 13 more characters]
```

### package.json

```
{
  "name": "somni-ai",
  "version": "1.0.0",
  "description": "Sleep Health Intelligence System - Multi-agent clinical evidence synthesis",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "test": "jest",
    "test:e2e": "playwright test",
    "test:watch": "jest --watch",
    "python:dev": "cd python && uvicorn api.main:app --reload --port 8000",
    "python:test": "cd python && pytest tests/ -v --cov=sleep_analysis",
    "format": "prettier --write \"**/*.{ts,tsx,js,jsx,json,md}\"",
    "type-check": "tsc --noEmit"
  },
  "dependencies": {
    "@anthropic-ai/sdk": "^0.30.1",
    "@radix-ui/react-alert-dialog": "^1.0.5",
    "@radix-ui/react-dialog": "^1.0.5",
    "@radix-ui/react-dropdown-menu": "^2.0.6",
    "@radix-ui/react-label": "^2.0.2",
    "@radix-ui/react-progress": "^1.0.3",
    "@radix-ui/react-separator": "^1.0.3",
    "@radix-ui/react-slot": "^1.0.2",
    "@radix-ui/react-toast": "^1.1.5",
    "@react-pdf/renderer": "^3.4.2",
    "@vercel/kv": "^3.0.0",
    "ai": "^3.0.23",
    "class-variance-authority": "^0.7.0",
    "clsx": "^2.1.0",
    "fast-xml-parser": "^5.3.6",
    "lucide-react": "^0.344.0",
    "nanoid": "^5.0.5",
    "next": "14.2.35",
    "openai": "^4.26.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-markdown": "^10.1.0",
    "recharts": "^2.12.0",
    "remark-gfm": "^4.0.1",
    "simple-statistics": "^7.8.8",
    "tailwind-merge": "^2.2.1",
    "tailwindcss-animate": "^1.0.7",
    "zod": "^3.22.4"
  },
  "devDependencies": {
    "@playwright/test": "^1.41.2",
    "@types/jest": "^30.0.0",
    "@types/node": "^20.11.17",
    "@types/react": "^18.2.55",
    "@types/react-dom": "^18.2.19",
    "autoprefixer": "^10.4.17",
    "eslint": "^8.56.0",
    "eslint-config-next": "14.2.35",
    "jest": "^30.2.0",
    "jest-environment-node": "^30.2.0",
    "postcss": "^8.4.35",
    "prettier": "^3.2.5",
    "tailwindcss": "^3.4.1",
    "typescript": "^5.3.3"
  },
  "engines": {
    "node": "24.x"
  }
}

```

### python/requirements.txt

```
# Core Data Science
pandas>=2.0.0
numpy>=1.24.0
scipy>=1.10.0
statsmodels>=0.14.0

# Web Framework
fastapi>=0.100.0
uvicorn[standard]>=0.23.0
python-multipart>=0.0.6

# Data Validation
pydantic>=2.0.0
pydantic-settings>=2.0.0

# XML Parsing (for Apple Health)
lxml>=4.9.0

# Testing
pytest>=7.4.0
pytest-cov>=4.1.0
pytest-asyncio>=0.21.0
httpx>=0.24.0

# Utilities
python-dotenv>=1.0.0

```

### app/layout.tsx

```typescript
import type { Metadata } from 'next'
import { Inter, Playfair_Display, Space_Mono } from 'next/font/google'
import './globals.css'

const inter = Inter({
  subsets: ['latin'],
  variable: '--font-inter',
  display: 'swap'
})

const playfair = Playfair_Display({
  subsets: ['latin'],
  weight: ['400', '700', '900'],
  variable: '--font-playfair',
  display: 'swap'
})

const spaceMono = Space_Mono({
  subsets: ['latin'],
  weight: ['400', '700'],
  variable: '--font-space-mono',
  display: 'swap'
})

export const metadata: Metadata = {
  title: 'SOMNI AI - Sleep Health Intelligence System',
  description: 'Transform wearable sleep data into actionable health insights through multi-agent clinical evidence synthesis',
}

export default function RootLayout({
  children,
}: {
  children: React.ReactNode
}) {
  return (
    <html lang="en">
      <body className={`${inter.variable} ${playfair.variable} ${spaceMono.variable} font-sans`}>{children}</body>
    </html>
  )
}

```

### app/page.tsx

```typescript
"use client";

import { useState } from "react";
import { Upload, FileText, AlertCircle, CheckCircle2 } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { Alert } from "@/components/ui/alert";
import { Badge } from "@/components/ui/badge";
import { useRouter } from "next/navigation";

export default function HomePage() {
  const [file, setFile] = useState<File | null>(null);
  const [uploading, setUploading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const router = useRouter();

  const handleFileChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFile = e.target.files?.[0];
    if (selectedFile) {
      setFile(selectedFile);
      setError(null);
    }
  };

  const handleUpload = async () => {
    if (!file) return;

    setUploading(true);
    setError(null);

    try {
      const formData = new FormData();
      formData.append("file", file);

      const response = await fetch("/api/analyze", {
        method: "POST",
        body: formData,
      });

      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(errorData.detail || "Analysis failed");
      }

      const { analysisId } = await response.json();
      router.push(`/analysis/${analysisId}`);
    } catch (err: any) {
      setError(err.message);
    } finally {
      setUploading(false);
    }
  };

  return (
    <div className="min-h-screen bg-gradient-to-br from-violet-50/50 via-blue-50/30 to-emerald-50/20">
      {/* Glass navigation bar */}
      <nav className="sticky top-0 z-50 glass-nav bg-white/70 border-b border-gray-200/30 shadow-sm">
        <div className="max-w-7xl mx-auto px-6 py-4">
          <h1 className="text-2xl font-playfair font-bold bg-gradient-to-r from-purple-600 to-blue-600 bg-clip-text text-transparent">
            SOMNI AI
          </h1>
        </div>
      </nav>

      {/* Hero section */}
      <div className="max-w-5xl mx-auto px-6 py-20 animate-fadeIn">
        <div className="text-center mb-12">
          <h1 className="heading-hero text-gray-900 mb-6">
            Sleep Health Intelligence
            <span className="block text-5xl bg-gradient-to-r from-purple-600 via-blue-600 to-emerald-600 bg-clip-text text-transparent mt-2">
              Powered by Multi-Agent AI
            </span>
          </h1>

          <p className="text-xl font-inter text-gray-600 max-w-2xl mx-auto leading-relaxed">
            Transform your wearable sleep data into evidence-based health intelligence
            through autonomous scientific analysis
          </p>
        </div>

        {/* Disclaimer alert with glass effect */}
        <div className="mb-8 p-4 rounded-xl glass-card bg-amber-50/80 border border-amber-200/40 max-w-3xl mx-auto">
          <div className="flex items-start gap-3">
            <AlertCircle className="h-5 w-5 text-amber-600 flex-shrink-0 mt-0.5" />
            <div>
              <p className="font-semibold text-amber-900 font-inter">Not a Diagnostic Tool</p>
              <p className="text-sm mt-1 text-amber-800 font-inter">
                Findings represent research associations from peer-reviewed literature, not medical diagnoses.
                Always consult healthcare providers for medical decisions.
              </p>
            </div>
          </div>
        </div>

        {/* Upload card with glass effect and glow border */}
        <Card className="relative overflow-hidden border-0 shadow-2xl glass-card bg-gradient-to-br from-white/80 to-white/40 p-8 max-w-3xl mx-auto">
          {/* Glowing border gradient */}
          <div className="absolute inset-0 bg-gradient-to-r from-purple-500/10 via-blue-500/10 to-emerald-500/10 rounded-lg" />

          <div className="relative">
            <h2 className="heading-card text-gray-900 mb-6">
              Upload Your Sleep Data
            </h2>

            <div
              className="border-2 border-dashed border-gray-300 rounded-xl p-12 text-center hover:border-purple-400 hover:bg-purple-50/30 cursor-pointer transition-all duration-300 card-hover"
              onClick={() => document.getElementById("file-upload")?.click()}
            >
              <div className="w-16 h-16 mx-auto mb-4 rounded-full bg-gradient-to-br from-purple-100 to-blue-100 flex items-center justify-center">
                <Upload className="h-8 w-8 text-purple-600" />
              </div>
              <p className="text-lg mb-2 font-inter text-gray-700">Drop your sleep export file</p>
              <p className="text-sm text-gray-500 mb-4 font-inter">
                Apple Health (.xml), Fitbit (.csv), or Oura (.csv)
              </p>
              <div className="flex items-center justify-center gap-2 flex-wrap">
                <Badge variant="secondary" className="bg-purple-100 text-purple-700 font-inter text-xs">
                  Apple Health
                </Badge>
                <Badge variant="secondary" className="bg-blue-100 text-blue-700 font-inter text-xs">
                  Fitbit
                </Badge>
                <Badge variant="secondary" className="bg-emerald-100 text-emerald-700 font-inter text-xs">
                  Oura Ring
                </Badge>
              </div>
              <input
                type="file"
                accept=".xml,.csv"
                onChange={handleFileChange}
                className="hidden"
                id="file-upload"
              />
            </div>

            {file && (
              <div className="mt-6 p-5 rounded-lg glass-card bg-gradient-to-r from-purple-50/80 to-blue-50/80 border border-purple-200/30 animate-fadeIn">
                <div className="flex items-center justify-between">
                  <div className="flex items-center gap-3">
 
[truncated — 3437 more characters]
```

### lib/sleep-analysis/index.ts

```typescript
/**
 * Sleep Analysis Library - TypeScript Implementation
 * Pure TypeScript port of Python sleep analysis engine for Vercel deployment
 */

export * from './types';
export * from './analyzer';
export * from './validators';

```

### python/api/main.py

```python
"""
FastAPI main application
Handles file upload, validation, and sleep analysis
"""

from fastapi import FastAPI, UploadFile, File, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse, HTMLResponse
import sys
from pathlib import Path

# Add parent directory to path for imports
sys.path.insert(0, str(Path(__file__).parent.parent))

from sleep_analysis.core import SleepAnalyzer
from sleep_analysis.validators import detect_format_and_parse, validate_sleep_data
from sleep_analysis.models import SleepAnalysisResult

app = FastAPI(
    title="SOMNI AI API",
    description="Sleep Health Intelligence System - Backend API",
    version="1.0.0"
)

# CORS middleware for Next.js frontend
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:3000", "http://127.0.0.1:3000", "https://*.vercel.app"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


@app.get("/health")
async def health():
    """Health check (JSON) for scripts and load balancers"""
    return {"status": "healthy", "service": "SOMNI AI Backend", "version": "1.0.0"}


@app.get("/", response_class=HTMLResponse)
async def root():
    """Root: show message for browsers; API is at /api/analyze and /docs"""
    return """
    <!DOCTYPE html>
    <html>
    <head><title>SOMNI AI API</title></head>
    <body style="font-family:sans-serif;max-width:480px;margin:2rem auto;padding:1rem;">
      <h1>SOMNI AI Backend</h1>
      <p>This is the <strong>API server</strong> (port 8000). It does not serve the app UI.</p>
      <p><strong>Open the frontend</strong> in your browser:</p>
      <p><a href="http://localhost:3000">http://localhost:3000</a></p>
      <p>API docs: <a href="/docs">/docs</a></p>
    </body>
    </html>
    """


@app.post("/api/analyze")
async def analyze_sleep_data(file: UploadFile = File(...)):
    """
    Analyze sleep data from uploaded file

    Supports:
    - Apple Health export.xml
    - Fitbit sleep.csv
    - Oura sleep.csv

    Returns:
        Sleep analysis result with z-scores, SHDI, phenotype classification
    """
    try:
        # Read file content
        content = await file.read()
        file_content = content.decode('utf-8')

        # Detect format and parse
        try:
            sleep_records = detect_format_and_parse(file_content, file.filename)
        except ValueError as e:
            raise HTTPException(
                status_code=422,
                detail=f"Failed to parse file: {str(e)}"
            )

        # Validate data
        records_dict = [r.model_dump() for r in sleep_records]
        validation = validate_sleep_data(records_dict)

        if not validation.valid:
            raise HTTPException(
                status_code=422,
                detail=validation.error_message
            )

        # Run analysis
        analyzer = SleepAnalyzer()
        try:
            result = analyzer.analyze(sleep_records)
        except Exception as e:
            raise HTTPException(
                status_code=500,
                detail=f"Analysis failed: {str(e)}"
            )

        # Return result as JSON
        return JSONResponse(
            content=result.model_dump(mode='json'),
            status_code=200
        )

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"Internal server error: {str(e)}"
        )


@app.get("/health")
async def health_check():
    """Detailed health check"""
    return {
        "status": "healthy",
        "components": {
            "api": "up",
            "analyzer": "ready"
        }
    }


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000, reload=True)

```

### app/api/get-analysis/route.ts

```typescript
import { NextRequest, NextResponse } from 'next/server';
import { getAnalysis } from '@/lib/cache';

// Force dynamic: this route uses request (query params) and must not be statically generated
export const dynamic = 'force-dynamic';

export async function GET(req: NextRequest) {
  try {
    const id = req.nextUrl.searchParams.get('id');

    if (!id) {
      return NextResponse.json(
        { error: 'Analysis ID required' },
        { status: 400 }
      );
    }

    // Retrieve cached analysis
    const cached = await getAnalysis(id);
    if (!cached) {
      return NextResponse.json(
        { error: 'Analysis not found' },
        { status: 404 }
      );
    }

    return NextResponse.json(cached.analysis);

  } catch (error: any) {
    console.error('[Get Analysis] Error:', error);
    return NextResponse.json(
      { error: `Failed to retrieve analysis: ${error.message}` },
      { status: 500 }
    );
  }
}

```

### app/api/export-pdf/route.ts

```typescript
import { NextRequest, NextResponse } from 'next/server';
import { generateClinicalReportPDF } from '@/lib/reports/generate-pdf';
import { getAnalysis } from '@/lib/cache';

export async function POST(req: NextRequest) {
  try {
    const { analysisId } = await req.json();

    // Retrieve cached analysis and reports
    const analysisData = await getAnalysis(analysisId);
    if (!analysisData) {
      return NextResponse.json(
        { error: 'Analysis not found' },
        { status: 404 }
      );
    }

    // Generate PDF buffer
    const pdfBuffer = await generateClinicalReportPDF(
      analysisData.analysis,
      analysisData.reports?.evidence || [],
      analysisId
    );

    // Return as downloadable PDF (Uint8Array for BodyInit type compatibility)
    return new NextResponse(new Uint8Array(pdfBuffer), {
      headers: {
        'Content-Type': 'application/pdf',
        'Content-Disposition': `attachment; filename="somni-clinical-report-${analysisId}.pdf"`
      }
    });

  } catch (error: any) {
    console.error('[PDF Export] Error:', error);
    return NextResponse.json(
      { error: 'Failed to generate PDF' },
      { status: 500 }
    );
  }
}

// Required for @react-pdf/renderer to work in Node.js environment
export const runtime = 'nodejs';

```

[44 more indexed source files omitted to keep this export small. The full file list is in the Codebase structure section above.]