diff --git a/README.md b/README.md index c541ce0..b784539 100644 --- a/README.md +++ b/README.md @@ -1,94 +1,155 @@ -# MedAssist-ng +

+ MedAssist Logo +

-πŸ“Š Medication tracking and planning app with stock monitoring, intake reminders, and email notifications. +

MedAssist

-## Quick Start (Production) +

+ Never run out of your medications again.
+ A medication tracking and planning app with stock monitoring, intake schedules, and reminder notifications. +

+ +

+ React 18 + TypeScript + Fastify + SQLite + Docker +

+ +### πŸ€– AI-Generated Code + +> This app was 100% coded with Claude Opus 4.5. Use at your own risk. + +### ⚠️ Disclaimer + +> **Your health is your responsibility.** Take it seriously and don't rely on any app, especially not this one! I don't have a medical or programming degreeβ€”this app is made with more love than knowledge, and it may have serious flaws. +> +> Follow your doctor's instructions closely, keep track of your medication supply, and plan ahead for reordering. +> +> **Think of this app as a helpful tool, but make all health decisions independently!** + +- [Features](#features) +- [Getting Started](#getting-started) +- [Configuration](#configuration) +- [Development](#development) + +# Features + +

+ MedAssist Dashboard +

+ +### Smart Inventory +- Track exact stock: packs, blisters, and loose pills +- Display remaining days of supply +- Automatic calculation based on intake schedule + +### Flexible Schedules +- Daily, weekly, or custom intervals per medication +- Independent schedules for each medication + +### Stock Alerts & Reminders +- Notifications before stock runs out +- Configurable warning thresholds +- Intake reminders via push notifications + +### Multi-Person Support +- Manage medications for multiple people +- Share links allow caregivers to mark doses as taken + +### Notifications +- Email via SMTP +- Push notifications via ntfy, Gotify, Telegram, Discord (Shoutrrr) +- Supports both stock warnings and intake reminders + +### Privacy & Security +- Fully self-hosted +- SSO via OIDC (Authelia, Authentik, Pocket ID, Keycloak) +- Dark mode included 😎 + +# Getting Started + +The easiest way to deploy MedAssist is with Docker Compose: ```bash -# 1. Clone and configure -git clone https://github.com/your-username/medassist-ng.git +git clone https://github.com/DanielVolz/medassist-ng.git cd medassist-ng cp .env.example .env - -# 2. Generate secure secrets (required!) -# Edit .env and replace CHANGE_ME values with output of: -openssl rand -hex 32 - -# 3. Start docker compose up -d - -# App runs on http://localhost:4174 (frontend) and http://localhost:4000 (API) ``` -## Development +Open `http://localhost:4174` and start tracking your medications. + +# Configuration + +All configuration is done via environment variables in `.env`. Copy `.env.example` to get started. + +### General + +| Variable | Default | Description | +|----------|---------|-------------| +| `PUID` | `1000` | User ID for container file permissions | +| `PGID` | `1000` | Group ID for container file permissions | +| `PORT` | `3000` | Backend API port | +| `CORS_ORIGINS` | `http://localhost:4174` | Allowed origins for CORS | +| `LOG_LEVEL` | `info` | Log verbosity (`debug`, `info`, `warn`, `error`) | +| `TZ` | `Europe/Berlin` | Timezone for scheduled reminders | + +### Authentication + +| Variable | Default | Description | +|----------|---------|-------------| +| `AUTH_ENABLED` | `false` | Enable user authentication | +| `REGISTRATION_ENABLED` | `false` | Allow new user registrations | +| `JWT_SECRET` | β€” | Access token signing key (required if auth enabled) | +| `REFRESH_SECRET` | β€” | Refresh token signing key (required if auth enabled) | +| `COOKIE_SECRET` | β€” | Cookie signing key (required if auth enabled) | +| `ACCESS_TOKEN_TTL_MINUTES` | `15` | Access token lifetime | +| `REFRESH_TOKEN_TTL_DAYS` | `7` | Refresh token lifetime | + +Generate secrets with: `openssl rand -hex 32` + +### OIDC / SSO + +| Variable | Default | Description | +|----------|---------|-------------| +| `OIDC_ENABLED` | `false` | Enable OIDC authentication | +| `OIDC_ISSUER_URL` | β€” | OIDC provider URL | +| `OIDC_CLIENT_ID` | β€” | Client ID from OIDC provider | +| `OIDC_CLIENT_SECRET` | β€” | Client secret from OIDC provider | +| `OIDC_REDIRECT_URI` | β€” | Callback URL | +| `OIDC_SCOPES` | `openid profile email` | Scopes to request | +| `OIDC_USERNAME_CLAIM` | `preferred_username` | Claim for username | +| `OIDC_AUTO_CREATE_USERS` | `true` | Auto-create users on first SSO login | +| `OIDC_PROVIDER_NAME` | `SSO` | Name shown on login button | + +### Email (SMTP) + +| Variable | Default | Description | +|----------|---------|-------------| +| `SMTP_HOST` | β€” | SMTP server hostname | +| `SMTP_PORT` | `587` | SMTP server port | +| `SMTP_USER` | β€” | SMTP username | +| `SMTP_PASS` | β€” | SMTP password | +| `SMTP_TOKEN` | β€” | OAuth2/App token (takes precedence over password) | +| `SMTP_FROM` | β€” | Sender email address | +| `SMTP_SECURE` | `false` | Use TLS | + +### Reminders + +| Variable | Default | Description | +|----------|---------|-------------| +| `REMINDER_DAYS_BEFORE` | `7` | Days before stock runs out to send reminder | +| `REMINDER_HOUR` | `6` | Hour to send daily reminders (24h format) | +| `REMINDER_MINUTES_BEFORE` | `15` | Minutes before intake to send reminder | +| `EXPIRY_WARNING_DAYS` | `30` | Days before expiry to show warning | + +# Development ```bash -# Start dev environment with hot-reload docker compose -f docker-compose.dev.yml up - -# Frontend: http://localhost:5173 -# Backend: http://localhost:3000 ``` -## Architecture - -``` -β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” -β”‚ Frontend β”‚ β”‚ Backend β”‚ β”‚ SQLite β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -- **Frontend**: React 18 + Vite + TypeScript, nginx-unprivileged (prod) -- **Backend**: Fastify 5 + TypeScript + SQLite (Drizzle ORM) -- **Security**: Non-root containers, read-only filesystem, no-new-privileges - -## Features - -- πŸ“¦ **Medication Inventory** - Track packs, blisters, loose pills -- πŸ“… **Intake Scheduling** - Multiple daily schedules with reminders -- πŸ“Š **Stock Monitoring** - Automatic low-stock detection -- πŸ“§ **Notifications** - Email (SMTP) and Push (ntfy, Discord, Telegram) -- 🌍 **i18n** - German and English -- πŸŒ™ **Dark/Light Mode** - -## Configuration - -Copy `.env.example` to `.env` and configure: - -| Variable | Required | Description | -|----------|----------|-------------| -| `JWT_SECRET` | βœ… | Access token signing (min 10 chars) | -| `REFRESH_SECRET` | βœ… | Refresh token signing | -| `COOKIE_SECional) | - -## File Structure - -``` -medassist-ng/ -β”œβ”€β”€ backend/ # Fastify API -β”‚ β”œβ”€β”€ src/ -β”‚ β”‚ β”œβ”€β”€ db/ # Schema + migrations -β”‚ β”‚ β”œβ”€β”€ routes/ # API endpoints -β”‚ β”‚ └── services/ # Business logic -β”‚ └── Dockerfile -β”œβ”€β”€ frontend/ # React SPA -β”‚ β”œβ”€β”€ src/ -β”‚ β”‚ β”œβ”€β”€ App.tsx # Main application -β”‚ β”‚ └── i18n/ # Translations -β”‚ └── Dockerfile -β”œβ”€β”€ docker-compose.yml # Production (default) -β”œβ”€β”€ docker-compose.dev.yml # Development -└── .env.example -``` - -## Reverse Proxy (Caddy example) - -``` -med.example.com { - reverse_proxy localhost:4174 -} -``` - -## License - -MIT +- Frontend: `http://localhost:5173` (hot reload) +- Backend: `http://localhost:3000` diff --git a/docs/screenshots/dashboard.png b/docs/screenshots/dashboard.png new file mode 100644 index 0000000..aa233c9 Binary files /dev/null and b/docs/screenshots/dashboard.png differ