Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -163,3 +163,14 @@ cython_debug/
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
.vercel

# Next.js / Node
frontend/node_modules/
frontend/.next/
frontend/out/
frontend/.env.local
frontend/.env*.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.env
15 changes: 11 additions & 4 deletions api/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,30 @@
allow_headers=["*"]
)

client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))

class ChatRequest(BaseModel):
message: str
# Optional per-request override so the Matrix UI can supply a key via password field
api_key: str | None = None

@app.get("/")
def root():
return {"status": "ok"}

@app.get("/api/health")
def health():
return {"status": "ok"}

@app.post("/api/chat")
def chat(request: ChatRequest):
if not os.getenv("OPENAI_API_KEY"):
# Prefer a client-supplied key (UI config), otherwise fall back to server env
api_key = (request.api_key or "").strip() or os.getenv("OPENAI_API_KEY")
if not api_key:
raise HTTPException(status_code=500, detail="OPENAI_API_KEY not configured")

try:
user_message = request.message
response = client.chat.completions.create(
request_client = OpenAI(api_key=api_key)
response = request_client.chat.completions.create(
model="gpt-5",
messages=[
{"role": "system", "content": "You are a supportive mental coach."},
Expand Down
3 changes: 3 additions & 0 deletions frontend/.env.local.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Local only — copy to .env.local for `npm run dev`.
# Do NOT set this on Vercel; the UI should call same-origin /api/chat there.
NEXT_PUBLIC_API_URL=http://localhost:8000
43 changes: 43 additions & 0 deletions frontend/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files (can opt-in for committing if needed)
.env*
!.env.local.example
!.env*.example

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
5 changes: 5 additions & 0 deletions frontend/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<!-- BEGIN:nextjs-agent-rules -->
# This is NOT the Next.js you know

This version has breaking changes — APIs, conventions, and file structure may all differ from your training data. Read the relevant guide in `node_modules/next/dist/docs/` before writing any code. Heed deprecation notices.
<!-- END:nextjs-agent-rules -->
1 change: 1 addition & 0 deletions frontend/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
@AGENTS.md
119 changes: 117 additions & 2 deletions frontend/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,118 @@
### Front End
# NEURAL_COACH // Blade Runner Console

Please populate this README with instructions on how to run the application!
Welcome to a rainy neon night in Los Angeles.

This Next.js frontend wraps the supportive mental coach API in a **Blade Runner**-inspired console: amber signage, cyan uplink glow, slanted city rain, film grain, and a live chat panel that still talks straight to FastAPI.

Brand first. Atmosphere second. Coach replies when you transmit.

## What's on screen

- Full-bleed neon rain over a dark night sky (not a flat black void)
- `NEURAL_COACH` as the hero signal in the console chrome
- Password-masked **CONFIG** panel for an optional OpenAI API key
- Chat uplink to `POST /api/chat`

## Prerequisites

- Node.js 18+ (`brew install node` works great)
- The FastAPI backend from this repo (`api/README.md`)
- An OpenAI API key — set as `OPENAI_API_KEY` on the backend, **or** paste it into the console CONFIG panel

## Setup

From the `frontend/` directory:

```bash
cd frontend
npm install
```

Optional: point the UI at a custom backend URL (defaults to `http://localhost:8000`):

```bash
cp .env.local.example .env.local
# edit NEXT_PUBLIC_API_URL if needed
```

## Run locally

Keep two terminals open — one for the night city, one for the uplink.

**Terminal 1 — backend** (repo root):

```bash
export OPENAI_API_KEY=sk-your-key-here
uv run uvicorn api.index:app --reload
```

**Terminal 2 — frontend**:

```bash
cd frontend
npm run dev
```

Open [http://localhost:3000](http://localhost:3000), watch the rain, and hit **TRANSMIT**.

### Scripts

| Command | What it does |
| --- | --- |
| `npm run dev` | Dev server with hot reload on port 3000 |
| `npm run build` | Production build |
| `npm start` | Serve the production build |
| `npm run lint` | ESLint |

> If Next complains that port 3000 is already in use, stop the old process (`kill <PID>`) and run `npm run dev` again so you land on **3000**, not 3001.

## How the console talks to the backend

The UI POSTs to `{NEXT_PUBLIC_API_URL}/api/chat` with:

```json
{
"message": "your text",
"api_key": "optional override"
}
```

and expects:

```json
{
"reply": "coach response"
}
```

Open **CONFIG** in the title bar to paste an API key (password field). Leave it blank to use the server's `OPENAI_API_KEY` env var.

## Deploying on Vercel

Root `vercel.json` builds this Next.js app alongside the Python API.

1. Push your repo to GitHub and sign into [vercel.com](https://vercel.com) with that GitHub account.
2. From the **repo root** (not `frontend/`):

```bash
npm install -g vercel
vercel
```

3. Follow the prompts (link the GitHub repo / confirm project settings).
4. In the Vercel dashboard → **Settings → Environment Variables**, add:

| Name | Value | Notes |
| --- | --- | --- |
| `OPENAI_API_KEY` | `sk-...` | Required for the coach API |
| `NEXT_PUBLIC_API_URL` | *(leave unset)* | Same-origin `/api/chat` on Vercel |

5. Redeploy if you added env vars after the first deploy:

```bash
vercel --prod
```

6. Open the **Domains** URL from the Vercel dashboard (test it in an Incognito window).

Local tip: keep `NEXT_PUBLIC_API_URL=http://localhost:8000` only in `frontend/.env.local` so local dev still hits uvicorn. Do not set that variable on Vercel.
18 changes: 18 additions & 0 deletions frontend/eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineConfig, globalIgnores } from "eslint/config";
import nextVitals from "eslint-config-next/core-web-vitals";
import nextTs from "eslint-config-next/typescript";

const eslintConfig = defineConfig([
...nextVitals,
...nextTs,
// Override default ignores of eslint-config-next.
globalIgnores([
// Default ignores of eslint-config-next:
".next/**",
"out/**",
"build/**",
"next-env.d.ts",
]),
]);

export default eslintConfig;
7 changes: 7 additions & 0 deletions frontend/next.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import type { NextConfig } from "next";

const nextConfig: NextConfig = {
/* config options here */
};

export default nextConfig;
Loading