From 9e367010d9e14ce8d9e39bcb778419bf29f47bca Mon Sep 17 00:00:00 2001 From: Shivam Patel Date: Mon, 9 Feb 2026 00:30:12 -0500 Subject: [PATCH] Add admin dashboard integration docs Co-Authored-By: Claude Opus 4.6 --- ADMIN_DASH_INTEGRATION.md | 106 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 ADMIN_DASH_INTEGRATION.md diff --git a/ADMIN_DASH_INTEGRATION.md b/ADMIN_DASH_INTEGRATION.md new file mode 100644 index 0000000..b679364 --- /dev/null +++ b/ADMIN_DASH_INTEGRATION.md @@ -0,0 +1,106 @@ +# Admin Dashboard Integration + +How to integrate with the website container from an external admin dashboard. + +## 1. Uptime Check + +**GET** `http://website-container:3000/api/health` + +Returns: +```json +{ "status": "ok", "timestamp": "2026-02-09T05:19:53.468Z" } +``` + +- 200 = up, anything else (timeout, connection refused, non-200) = down +- Both containers must be on the same Docker network for hostname resolution: + +```bash +docker network create app-net +docker network connect app-net website-container +docker network connect app-net admin-dash-container +``` + +Alternatively, use `http://host.docker.internal:8080/api/health` to go through the host port mapping (no shared network needed, but adds overhead). + +## 2. Visitors Database + +The website writes visitor data to a SQLite DB at `/server_storage/visitors.db`. Mount the same host volume in the admin dashboard container (read-only): + +```bash +docker run -d \ + --name admin-dash-container \ + -v /server_storage:/server_storage:ro \ + admin-dash:latest +``` + +### Schema + +```sql +CREATE TABLE visits ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + ip_address TEXT NOT NULL, -- e.g. "2600:6c65:6740:..." or "18.199.106.183" + path TEXT NOT NULL, -- e.g. "/", "/blog", "/resume" + visited_at TEXT NOT NULL -- UTC datetime, e.g. "2026-02-09 05:19:53" +); +``` + +### Reading from the DB + +The DB uses WAL mode, so reads won't block the website's writes. Open in **read-only** mode to avoid conflicts: + +```typescript +// Node.js with better-sqlite3 +import Database from 'better-sqlite3'; +const db = new Database('/server_storage/visitors.db', { readonly: true }); +const visits = db.prepare('SELECT * FROM visits ORDER BY visited_at DESC LIMIT 100').all(); +``` + +```python +# Python with sqlite3 +import sqlite3 +conn = sqlite3.connect('file:///server_storage/visitors.db?mode=ro', uri=True) +visits = conn.execute('SELECT * FROM visits ORDER BY visited_at DESC LIMIT 100').fetchall() +``` + +### Useful Queries + +```sql +-- Unique visitors today +SELECT COUNT(DISTINCT ip_address) FROM visits +WHERE visited_at >= date('now'); + +-- Page view counts +SELECT path, COUNT(*) as views FROM visits +GROUP BY path ORDER BY views DESC; + +-- Visits per hour (last 24h) +SELECT strftime('%Y-%m-%d %H:00', visited_at) as hour, COUNT(*) as views +FROM visits WHERE visited_at >= datetime('now', '-1 day') +GROUP BY hour ORDER BY hour; +``` + +## Docker Compose Example + +```yaml +services: + website: + image: my-website:latest + ports: + - "8080:3000" + volumes: + - /server_storage:/server_storage + networks: + - app-net + + admin-dash: + image: admin-dash:latest + ports: + - "3333:3000" + volumes: + - /server_storage:/server_storage:ro + networks: + - app-net + +networks: + app-net: +```