mirror of
https://github.com/Tony0410/nextstep.git
synced 2026-05-24 21:31:43 +08:00
Initial commit: Next Step health management app
A calm, reliable app to help manage appointments, medications, and notes for chemo patients and their families. Features: - Today dashboard with next appointment and medications due - Medication tracking with multiple schedule types (fixed times, interval, weekdays, PRN) - One-tap dose logging with 5-minute undo window - Questions for doctor tracking - Family sharing with workspace model and invite links - Offline-first with IndexedDB and sync - Docker Compose deployment with Tailscale Funnel support Tech stack: - Next.js 14 (App Router) + TypeScript + Tailwind CSS - PostgreSQL + Prisma - Argon2 password hashing + session cookies - Dexie.js for IndexedDB Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
318
README.md
Normal file
318
README.md
Normal file
@@ -0,0 +1,318 @@
|
||||
# Next Step
|
||||
|
||||
A calm, reliable health management app for families supporting a loved one through treatment. Built to be "mum-proof" — simple, clear, and accessible.
|
||||
|
||||

|
||||
|
||||
## Features
|
||||
|
||||
### Today Dashboard
|
||||
- **Next appointment** with location and map link
|
||||
- **Medications due** with one-tap "Taken" button
|
||||
- **Quick note** for jotting down thoughts
|
||||
- **Call clinic** button for easy access
|
||||
|
||||
### Appointments
|
||||
- Simple timeline view with date groupings
|
||||
- Add title, date/time, location, map link, and notes
|
||||
- Soft delete with recovery
|
||||
|
||||
### Medications
|
||||
- **Multiple schedule types:**
|
||||
- Fixed times daily (e.g., 8am, 8pm)
|
||||
- Every X hours (e.g., every 8 hours)
|
||||
- Specific weekdays (e.g., Mon/Wed/Fri at 9am)
|
||||
- PRN/As needed with cooldown period
|
||||
- One-tap dose logging with 5-minute undo window
|
||||
- "What did I take?" history view (last 7 days)
|
||||
- Overdue indicators with grace period
|
||||
|
||||
### Notes
|
||||
- **Questions for doctor** — track what to ask, mark as asked
|
||||
- **General notes** — timestamped thoughts
|
||||
- Copy questions for appointments
|
||||
|
||||
### Family Sharing
|
||||
- Workspace model (e.g., "Grace's Plan")
|
||||
- Invite family via link
|
||||
- Roles: Owner, Editor, Viewer
|
||||
- Audit log of all changes
|
||||
|
||||
### Offline-First
|
||||
- Works without internet connection
|
||||
- IndexedDB local cache
|
||||
- Automatic sync when online
|
||||
- Conflict detection with "updated on another device" banner
|
||||
|
||||
## Tech Stack
|
||||
|
||||
- **Frontend:** Next.js 14 (App Router), TypeScript, Tailwind CSS
|
||||
- **Database:** PostgreSQL with Prisma ORM
|
||||
- **Auth:** Session cookies with argon2 password hashing
|
||||
- **Offline:** IndexedDB via Dexie.js
|
||||
- **Deployment:** Docker Compose
|
||||
|
||||
## Quick Start
|
||||
|
||||
### Prerequisites
|
||||
- Docker and Docker Compose
|
||||
- Tailscale (for external access)
|
||||
|
||||
### 1. Clone and Configure
|
||||
|
||||
```bash
|
||||
cd /path/to/nextstep
|
||||
|
||||
# Copy environment template
|
||||
cp .env.example .env
|
||||
|
||||
# Edit .env and set:
|
||||
# - NEXTAUTH_SECRET (generate with: openssl rand -base64 32)
|
||||
# - DB_PASSWORD (choose a secure password)
|
||||
# - NEXT_PUBLIC_APP_URL (your Tailscale Funnel URL)
|
||||
```
|
||||
|
||||
### 2. Start the Application
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
The app will:
|
||||
1. Build the Next.js application
|
||||
2. Start PostgreSQL
|
||||
3. Run database migrations
|
||||
4. Start the app on `127.0.0.1:3000`
|
||||
|
||||
### 3. Set Up Tailscale Funnel
|
||||
|
||||
Tailscale Funnel exposes your local app to the internet with automatic HTTPS.
|
||||
|
||||
```bash
|
||||
# Enable Funnel (one-time setup)
|
||||
tailscale funnel --https=443 http://127.0.0.1:3000 --bg
|
||||
|
||||
# Check status
|
||||
tailscale funnel status
|
||||
|
||||
# Your app is now accessible at:
|
||||
# https://[your-machine-name].[your-tailnet].ts.net
|
||||
```
|
||||
|
||||
### 4. Update Your Environment
|
||||
|
||||
Edit `.env` and set `NEXT_PUBLIC_APP_URL` to your Funnel URL:
|
||||
|
||||
```
|
||||
NEXT_PUBLIC_APP_URL=https://your-machine.your-tailnet.ts.net
|
||||
```
|
||||
|
||||
Then restart the app:
|
||||
|
||||
```bash
|
||||
docker compose down
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
### 5. Create Your Account
|
||||
|
||||
1. Open your Funnel URL in a browser
|
||||
2. Click "Create Account"
|
||||
3. Accept the disclaimer
|
||||
4. Create your workspace (e.g., "Grace's Plan")
|
||||
5. Add your clinic phone number
|
||||
|
||||
## Development
|
||||
|
||||
### Local Development
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
# Set up local PostgreSQL (or use Docker)
|
||||
docker run -d \
|
||||
--name nextstep-postgres \
|
||||
-e POSTGRES_USER=nextstep \
|
||||
-e POSTGRES_PASSWORD=nextstep \
|
||||
-e POSTGRES_DB=nextstep \
|
||||
-p 5432:5432 \
|
||||
postgres:16-alpine
|
||||
|
||||
# Set up environment
|
||||
cp .env.example .env
|
||||
# Edit .env with DATABASE_URL=postgresql://nextstep:nextstep@localhost:5432/nextstep
|
||||
|
||||
# Generate Prisma client
|
||||
npm run db:generate
|
||||
|
||||
# Run migrations
|
||||
npm run db:migrate
|
||||
|
||||
# Start dev server
|
||||
npm run dev
|
||||
```
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
Tests cover:
|
||||
- Medication scheduling logic
|
||||
- PRN cooldown calculations
|
||||
- Fixed times, interval, and weekday schedules
|
||||
|
||||
## Environment Variables
|
||||
|
||||
| Variable | Description | Required |
|
||||
|----------|-------------|----------|
|
||||
| `DATABASE_URL` | PostgreSQL connection string | Yes |
|
||||
| `NEXTAUTH_SECRET` | Session encryption secret (min 32 chars) | Yes |
|
||||
| `NEXT_PUBLIC_APP_URL` | Public URL of the app | Yes |
|
||||
| `DB_PASSWORD` | PostgreSQL password (for Docker) | Yes |
|
||||
| `TZ` | Timezone (default: Australia/Perth) | No |
|
||||
| `RATE_LIMIT_MAX_REQUESTS` | Max requests per minute (default: 100) | No |
|
||||
| `LOGIN_MAX_ATTEMPTS` | Failed logins before lockout (default: 5) | No |
|
||||
| `LOGIN_LOCKOUT_MINUTES` | Lockout duration (default: 15) | No |
|
||||
| `SESSION_MAX_AGE_DAYS` | Session lifetime (default: 30) | No |
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### Authentication
|
||||
- `POST /api/auth/register` — Create account
|
||||
- `POST /api/auth/login` — Sign in
|
||||
- `POST /api/auth/logout` — Sign out
|
||||
- `GET /api/auth/me` — Get current user
|
||||
|
||||
### Workspaces
|
||||
- `GET /api/workspaces` — List user's workspaces
|
||||
- `POST /api/workspaces` — Create workspace
|
||||
- `GET /api/workspaces/[id]` — Get workspace details
|
||||
- `PATCH /api/workspaces/[id]` — Update workspace settings
|
||||
- `POST /api/workspaces/[id]/invite` — Create invite link
|
||||
- `GET /api/invite/[token]` — Get invite details
|
||||
- `POST /api/invite/[token]` — Accept invite
|
||||
|
||||
### Sync
|
||||
- `GET /api/sync?workspaceId=...&since=...` — Pull changes
|
||||
- `POST /api/sync` — Push offline operations
|
||||
|
||||
### Health
|
||||
- `GET /api/health` — Health check
|
||||
|
||||
## Security
|
||||
|
||||
- **Password hashing:** Argon2id with secure parameters
|
||||
- **Session cookies:** HTTPOnly, Secure, SameSite=Lax
|
||||
- **Rate limiting:** Per-IP request limits
|
||||
- **Login protection:** Lockout after failed attempts
|
||||
- **Input validation:** Zod schemas on all endpoints
|
||||
- **HTTPS:** Enforced via Tailscale Funnel
|
||||
|
||||
## Tailscale Funnel Commands
|
||||
|
||||
```bash
|
||||
# Start Funnel (background mode)
|
||||
tailscale funnel --https=443 http://127.0.0.1:3000 --bg
|
||||
|
||||
# Check Funnel status
|
||||
tailscale funnel status
|
||||
|
||||
# Stop Funnel
|
||||
tailscale funnel off
|
||||
|
||||
# View Funnel logs
|
||||
tailscale funnel status --json
|
||||
```
|
||||
|
||||
## Backup & Restore
|
||||
|
||||
### Backup Database
|
||||
|
||||
```bash
|
||||
docker exec nextstep-db pg_dump -U nextstep nextstep > backup.sql
|
||||
```
|
||||
|
||||
### Restore Database
|
||||
|
||||
```bash
|
||||
cat backup.sql | docker exec -i nextstep-db psql -U nextstep nextstep
|
||||
```
|
||||
|
||||
### Export User Data
|
||||
|
||||
Users can export their data as JSON from Settings > Export Data.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### App won't start
|
||||
|
||||
```bash
|
||||
# Check logs
|
||||
docker compose logs app
|
||||
|
||||
# Common issues:
|
||||
# - Database not ready: wait a few seconds, it will retry
|
||||
# - Missing env vars: check .env file
|
||||
```
|
||||
|
||||
### Database connection failed
|
||||
|
||||
```bash
|
||||
# Check database is running
|
||||
docker compose ps
|
||||
|
||||
# Check database logs
|
||||
docker compose logs db
|
||||
|
||||
# Verify connection string in .env
|
||||
```
|
||||
|
||||
### Tailscale Funnel not working
|
||||
|
||||
```bash
|
||||
# Ensure Funnel is enabled for your tailnet
|
||||
# (requires admin access to Tailscale admin console)
|
||||
|
||||
# Check if Funnel is running
|
||||
tailscale funnel status
|
||||
|
||||
# Restart Funnel
|
||||
tailscale funnel off
|
||||
tailscale funnel --https=443 http://127.0.0.1:3000 --bg
|
||||
```
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Tailscale Funnel │
|
||||
│ (HTTPS termination) │
|
||||
└────────────────────────┬────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Next.js App │
|
||||
│ (127.0.0.1:3000) │
|
||||
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
|
||||
│ │ App │ │ API │ │ Auth │ │
|
||||
│ │ Router │ │ Routes │ │ (Sessions) │ │
|
||||
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
|
||||
└────────────────────────┬────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ PostgreSQL │
|
||||
│ (Internal only) │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
MIT License. See LICENSE file for details.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
**Next Step is a tracking tool only.** It does not provide medical advice. Always consult your healthcare team for medical decisions. For emergencies, call 000 (Australia) or your local emergency services.
|
||||
Reference in New Issue
Block a user