docs: clarify dev hosts and deployment guidance
This commit is contained in:
@@ -10,6 +10,8 @@ PUID=1000
|
|||||||
PGID=1000
|
PGID=1000
|
||||||
|
|
||||||
PORT=3000
|
PORT=3000
|
||||||
|
# Docker Compose quickstart serves the frontend on http://localhost:4174.
|
||||||
|
# Local Vite development usually uses http://localhost:5173 or http://localhost:4173 instead.
|
||||||
CORS_ORIGINS=http://localhost:4174
|
CORS_ORIGINS=http://localhost:4174
|
||||||
|
|
||||||
# Server default timezone for scheduled reminders.
|
# Server default timezone for scheduled reminders.
|
||||||
@@ -18,8 +20,11 @@ TZ=Europe/Berlin
|
|||||||
|
|
||||||
# Public base URL used for notification action links.
|
# Public base URL used for notification action links.
|
||||||
# Required for intake reminder action buttons.
|
# Required for intake reminder action buttons.
|
||||||
|
# Use an externally reachable HTTPS URL for remote/self-hosted access.
|
||||||
# PUBLIC_APP_URL=https://medassist.example.com
|
# PUBLIC_APP_URL=https://medassist.example.com
|
||||||
# If this uses a non-local host, include that origin in CORS_ORIGINS.
|
# If this uses a non-local host, include that origin in CORS_ORIGINS.
|
||||||
|
# Local Vite development automatically allows this hostname; set
|
||||||
|
# VITE_ALLOWED_HOSTS only when you need additional development hostnames.
|
||||||
|
|
||||||
# Log level: debug, info, warn, error, silent
|
# Log level: debug, info, warn, error, silent
|
||||||
LOG_LEVEL=info
|
LOG_LEVEL=info
|
||||||
|
|||||||
@@ -1,26 +1,13 @@
|
|||||||
# MedAssist-ng - Copilot Entry Point
|
# MedAssist-ng - Copilot Entry Point
|
||||||
|
|
||||||
## VERY IMPORTANT - Prioritized Constraints
|
This file is intentionally thin. `AGENTS.md` is the canonical governance file for this repository.
|
||||||
|
|
||||||
**First: Update Memory and Reports**
|
If rules differ between files, follow `AGENTS.md`.
|
||||||
- Always keep agent work memory updated in `doku/memory_notes.md` so progress and decisions remain recoverable across context loss.
|
|
||||||
- If `doku/memory_notes.md` is missing, create it immediately.
|
|
||||||
- Always keep a user-facing work report updated in `doku/report.md` so completed work is easy to review.
|
|
||||||
- If `doku/report.md` is missing, create it immediately.
|
|
||||||
- This memory/report rule replaces the previous `doku/APP_BEHAVIOR.md` persistence requirement.
|
|
||||||
|
|
||||||
**Second: Follow Governance Rules**
|
|
||||||
- Consult `AGENTS.md` for governance, workflow, and skill rules when that file exists in the workspace.
|
|
||||||
|
|
||||||
When `AGENTS.md` exists in the workspace, use it as the single source of truth for governance, workflow, and skill rules.
|
|
||||||
|
|
||||||
## Required Startup Steps
|
## Required Startup Steps
|
||||||
|
|
||||||
1. Read `AGENTS.md` first when it exists in the workspace.
|
1. Read `AGENTS.md` first when it exists in the workspace.
|
||||||
2. If `AGENTS.md` exists, identify triggered skills from it and read each referenced `SKILL.md` before making changes.
|
2. Ensure `doku/memory_notes.md` and `doku/report.md` exist and keep them updated during meaningful work. These files are local-only and must not be staged or committed unless explicitly requested.
|
||||||
3. Follow delegation boundaries exactly (`@testing-manager` for testing, `@release-manager` for release orchestration).
|
3. Identify triggered skills from `AGENTS.md` and read only the matching `SKILL.md` files before making changes.
|
||||||
4. When work moves into a different thematic area, create or switch to a dedicated local branch or worktree before editing code, and reuse the same branch/worktree for follow-up work inside that same theme.
|
4. Follow delegation boundaries from `AGENTS.md`: `@testing-manager` for testing work and `@release-manager` for release orchestration, including the documented fallback protocol when a required specialist is unavailable.
|
||||||
|
5. Keep all non-canonical instruction files brief and aligned with `AGENTS.md`; do not duplicate full governance here.
|
||||||
## Scope
|
|
||||||
|
|
||||||
This file intentionally stays minimal to prevent duplicated or conflicting instructions.
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ on:
|
|||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: docker-build-${{ github.ref }}
|
group: docker-build-${{ github.ref }}
|
||||||
|
# Cancel older runs on the same ref so the shared branch tag stays aligned
|
||||||
|
# with the newest commit instead of racing older builds against newer ones.
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
# Default minimal permissions
|
# Default minimal permissions
|
||||||
|
|||||||
@@ -157,10 +157,13 @@ Share your medication schedule with others via a public link.
|
|||||||
### Multi-Person Support
|
### Multi-Person Support
|
||||||
- Manage medications for multiple people
|
- Manage medications for multiple people
|
||||||
- Share schedules via link. Recipients can mark doses as taken, you see it live
|
- Share schedules via link. Recipients can mark doses as taken, you see it live
|
||||||
|
- Optionally allow shared links to view and edit intake journal notes for their visible schedule window
|
||||||
- Optionally embed the medication overview directly on shared links via a settings toggle
|
- Optionally embed the medication overview directly on shared links via a settings toggle
|
||||||
|
|
||||||
### Data Export & Import
|
### Data Export & Import
|
||||||
- Export all your data (medications, dose history, settings) as JSON
|
- Export all your data (medications, dose history, intake journal notes, settings) as JSON
|
||||||
|
- Review validated import contents before replacing current data
|
||||||
|
- Optionally download a fresh backup before confirming import
|
||||||
- Import previously exported data with automatic ID remapping
|
- Import previously exported data with automatic ID remapping
|
||||||
- Choose whether to include sensitive data in exports
|
- Choose whether to include sensitive data in exports
|
||||||
|
|
||||||
@@ -188,6 +191,16 @@ docker compose -p medassist-ng up -d
|
|||||||
|
|
||||||
Open `http://localhost:4174` and start tracking your medications.
|
Open `http://localhost:4174` and start tracking your medications.
|
||||||
|
|
||||||
|
### Verify Deployment
|
||||||
|
|
||||||
|
After the containers start, confirm the stack is actually healthy:
|
||||||
|
|
||||||
|
1. Run `docker compose ps` and confirm the `backend` service is `healthy` and the `frontend` service is running.
|
||||||
|
2. Open `http://localhost:3000/health` and confirm the backend responds with JSON that includes `"status":"ok"`.
|
||||||
|
3. Open `http://localhost:4174` and confirm the app shell loads and can reach the API.
|
||||||
|
|
||||||
|
If the frontend loads but API requests fail, check the backend health endpoint first and confirm `CORS_ORIGINS` includes the frontend origin you are using. If you plan to open reminder or share links from another device, set `PUBLIC_APP_URL` to the externally reachable app URL instead of relying on `localhost`.
|
||||||
|
|
||||||
# Configuration
|
# Configuration
|
||||||
|
|
||||||
Configure the application with environment variables in `.env`. Keep the basic container settings in the README and use the dedicated docs for the full reference.
|
Configure the application with environment variables in `.env`. Keep the basic container settings in the README and use the dedicated docs for the full reference.
|
||||||
@@ -206,7 +219,7 @@ Optional but commonly needed:
|
|||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
|----------|---------|-------------|
|
|----------|---------|-------------|
|
||||||
| `PUBLIC_APP_URL` | — | Public base URL for notification action links |
|
| `PUBLIC_APP_URL` | — | Public base URL for notification action and share links |
|
||||||
|
|
||||||
Detailed configuration references:
|
Detailed configuration references:
|
||||||
|
|
||||||
|
|||||||
+13
-3
@@ -9,9 +9,9 @@ Configure MedAssist with environment variables in `.env`. Start from `.env.examp
|
|||||||
| `PUID` | `1000` | User ID for container file permissions |
|
| `PUID` | `1000` | User ID for container file permissions |
|
||||||
| `PGID` | `1000` | Group ID for container file permissions |
|
| `PGID` | `1000` | Group ID for container file permissions |
|
||||||
| `PORT` | `3000` | Backend API port |
|
| `PORT` | `3000` | Backend API port |
|
||||||
| `CORS_ORIGINS` | `http://localhost:4174` | Allowed origins for CORS |
|
| `CORS_ORIGINS` | `http://localhost:4174` | Allowed origins for CORS in the Docker Compose quickstart; local Vite development commonly uses `http://localhost:5173` or `http://localhost:4173` |
|
||||||
| `TZ` | `Europe/Berlin` | Server default timezone for scheduled reminders |
|
| `TZ` | `Europe/Berlin` | Server default timezone for scheduled reminders |
|
||||||
| `PUBLIC_APP_URL` | — | Public base URL for notification action links. Must be reachable by phones, browsers, and notification providers; do not point this to `localhost` or an internal Docker hostname. |
|
| `PUBLIC_APP_URL` | — | Public base URL for notification action and share links. Strongly recommended for any deployment used from another device; do not point this to `localhost` or an internal Docker hostname. Local Vite development also allows this hostname automatically. |
|
||||||
| `LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error`, or `silent` |
|
| `LOG_LEVEL` | `info` | Log level: `debug`, `info`, `warn`, `error`, or `silent` |
|
||||||
| `RATE_LIMIT_MAX` | `100` | Maximum requests per minute per IP |
|
| `RATE_LIMIT_MAX` | `100` | Maximum requests per minute per IP |
|
||||||
| `OPENAPI_DOCS_ENABLED` | `auto` | Explicitly enable or disable `/docs` and `/docs/json` |
|
| `OPENAPI_DOCS_ENABLED` | `auto` | Explicitly enable or disable `/docs` and `/docs/json` |
|
||||||
@@ -22,6 +22,12 @@ API docs behavior:
|
|||||||
- `OPENAPI_DOCS_ENABLED=true` enables `/docs` and `/docs/json`.
|
- `OPENAPI_DOCS_ENABLED=true` enables `/docs` and `/docs/json`.
|
||||||
- `OPENAPI_DOCS_ENABLED=false` disables the docs only.
|
- `OPENAPI_DOCS_ENABLED=false` disables the docs only.
|
||||||
|
|
||||||
|
`CORS_ORIGINS` note:
|
||||||
|
|
||||||
|
- The `.env.example` file is optimized for the Docker Compose quickstart, where the frontend runs on `http://localhost:4174`.
|
||||||
|
- Local frontend development uses the Vite dev server instead, so the backend schema defaults cover `http://localhost:5173` and `http://localhost:4173`.
|
||||||
|
- If you use a custom hostname or reverse proxy, include that origin in `CORS_ORIGINS`.
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
| Variable | Default | Description |
|
| Variable | Default | Description |
|
||||||
@@ -102,13 +108,17 @@ API reference:
|
|||||||
|
|
||||||
Reminder timing uses IANA timezones. `TZ` is the server default. Users can override it in Settings.
|
Reminder timing uses IANA timezones. `TZ` is the server default. Users can override it in Settings.
|
||||||
|
|
||||||
|
These values are runtime defaults. User-specific settings can override reminder behavior after first save.
|
||||||
|
|
||||||
## Push Notifications
|
## Push Notifications
|
||||||
|
|
||||||
Push notification setup, provider support, and URL examples are documented in [PUSH_NOTIFICATIONS.md](PUSH_NOTIFICATIONS.md).
|
Push notification setup, provider support, and URL examples are documented in [PUSH_NOTIFICATIONS.md](PUSH_NOTIFICATIONS.md).
|
||||||
|
|
||||||
Recommended provider: `ntfy`, especially for intake reminders with direct actions.
|
Recommended provider: `ntfy`, especially for intake reminders with direct actions.
|
||||||
|
|
||||||
Notification action links use `PUBLIC_APP_URL` as their base URL. For self-hosted setups, this should normally be your externally reachable HTTPS address, for example `https://med.example.com`.
|
Notification action and share links should use `PUBLIC_APP_URL` as their reachable base URL. For self-hosted setups, this should normally be your externally reachable HTTPS address, for example `https://med.example.com`.
|
||||||
|
|
||||||
|
If `PUBLIC_APP_URL` is missing in a remote deployment, reminder links can still be generated from local origins that are unreachable from phones or external browsers.
|
||||||
|
|
||||||
## Default User Settings
|
## Default User Settings
|
||||||
|
|
||||||
|
|||||||
+10
-1
@@ -19,8 +19,17 @@ If the frontend dev server runs behind a reverse proxy or on a remote host, set
|
|||||||
|
|
||||||
These development overrides are documented here intentionally and are not part of the standard operator-focused `.env.example` surface.
|
These development overrides are documented here intentionally and are not part of the standard operator-focused `.env.example` surface.
|
||||||
|
|
||||||
|
## API Proxy Contract
|
||||||
|
|
||||||
|
- Frontend browser code should call `/api/*`, not hardcoded backend hostnames.
|
||||||
|
- Vite rewrites `/api/*` to the backend target configured by `BACKEND_URL` or the built-in default for the current environment.
|
||||||
|
- Default backend target:
|
||||||
|
- local dev outside Docker: `http://localhost:3000`
|
||||||
|
- dev stack inside Docker: `http://backend-dev:3000`
|
||||||
|
- If your backend runs on a different host or service name, set `BACKEND_URL` explicitly before starting Vite.
|
||||||
|
|
||||||
- `BACKEND_URL`: backend target used by the Vite `/api` proxy; default `http://localhost:3000` outside Docker and `http://backend-dev:3000` in Docker
|
- `BACKEND_URL`: backend target used by the Vite `/api` proxy; default `http://localhost:3000` outside Docker and `http://backend-dev:3000` in Docker
|
||||||
- `VITE_ALLOWED_HOSTS`: comma-separated hostnames allowed to connect to the dev server; default `localhost,127.0.0.1`
|
- `VITE_ALLOWED_HOSTS`: comma-separated hostnames allowed to connect to the dev server; default `localhost,127.0.0.1` plus the hostname from `PUBLIC_APP_URL` when configured
|
||||||
- `VITE_HMR_HOST`: public hostname for HMR websocket connections
|
- `VITE_HMR_HOST`: public hostname for HMR websocket connections
|
||||||
- `VITE_HMR_PROTOCOL`: websocket protocol override (`ws` or `wss`)
|
- `VITE_HMR_PROTOCOL`: websocket protocol override (`ws` or `wss`)
|
||||||
- `VITE_HMR_CLIENT_PORT`: public websocket port exposed to the browser
|
- `VITE_HMR_CLIENT_PORT`: public websocket port exposed to the browser
|
||||||
|
|||||||
+19
-1
@@ -20,6 +20,22 @@ function parseOptionalPort(value: string | undefined) {
|
|||||||
return Number.isFinite(parsed) ? parsed : undefined;
|
return Number.isFinite(parsed) ? parsed : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseUrlHostname(value: string | undefined) {
|
||||||
|
if (!value) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
return new URL(value).hostname;
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function uniqueHosts(hosts: Array<string | undefined>) {
|
||||||
|
return [...new Set(hosts.filter((host): host is string => Boolean(host)))];
|
||||||
|
}
|
||||||
|
|
||||||
// Read version from package.json at build time
|
// Read version from package.json at build time
|
||||||
const packageJson = JSON.parse(readFileSync("./package.json", "utf-8"));
|
const packageJson = JSON.parse(readFileSync("./package.json", "utf-8"));
|
||||||
|
|
||||||
@@ -27,7 +43,9 @@ const packageJson = JSON.parse(readFileSync("./package.json", "utf-8"));
|
|||||||
// In Docker, prefer backend-dev to avoid localhost proxy failures.
|
// In Docker, prefer backend-dev to avoid localhost proxy failures.
|
||||||
const defaultBackendTarget = existsSync("/.dockerenv") ? "http://backend-dev:3000" : "http://localhost:3000";
|
const defaultBackendTarget = existsSync("/.dockerenv") ? "http://backend-dev:3000" : "http://localhost:3000";
|
||||||
const backendTarget = process.env.BACKEND_URL || defaultBackendTarget;
|
const backendTarget = process.env.BACKEND_URL || defaultBackendTarget;
|
||||||
const allowedHosts = parseCsvEnv(process.env.VITE_ALLOWED_HOSTS, ["localhost", "127.0.0.1"]);
|
const configuredAllowedHosts = parseCsvEnv(process.env.VITE_ALLOWED_HOSTS, []);
|
||||||
|
const baseAllowedHosts = configuredAllowedHosts.length > 0 ? configuredAllowedHosts : ["localhost", "127.0.0.1"];
|
||||||
|
const allowedHosts = uniqueHosts([...baseAllowedHosts, parseUrlHostname(process.env.PUBLIC_APP_URL)]);
|
||||||
const hmrHost = process.env.VITE_HMR_HOST?.trim();
|
const hmrHost = process.env.VITE_HMR_HOST?.trim();
|
||||||
const hmrProtocol = process.env.VITE_HMR_PROTOCOL === "ws" ? "ws" : process.env.VITE_HMR_PROTOCOL === "wss" ? "wss" : undefined;
|
const hmrProtocol = process.env.VITE_HMR_PROTOCOL === "ws" ? "ws" : process.env.VITE_HMR_PROTOCOL === "wss" ? "wss" : undefined;
|
||||||
const hmrClientPort = parseOptionalPort(process.env.VITE_HMR_CLIENT_PORT);
|
const hmrClientPort = parseOptionalPort(process.env.VITE_HMR_CLIENT_PORT);
|
||||||
|
|||||||
Reference in New Issue
Block a user