From 1dba721a9a7e4b58d56a85b32ab1e674b7b1bd5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Br=C3=BCckner?= Date: Mon, 8 Jun 2026 14:51:36 +0200 Subject: [PATCH] feat(ui): light-mode sky palette for Caddy card, favicon, doc sync - index.css: add :root.light overrides for the sky-* accent used only by the Caddy settings card (buttons, badges, hovers) + the missing red-950/30 hover - favicon: add public/favicon.svg (GhostGrid logo) and link it in index.html - ARCHITECTURE.md: GET /caddy/routes returns a plain array, document the Caddy startup import, https:// upstream, favicon/public dir, and the SPA-catch-all-last + Cache-Control: no-store invariant --- ARCHITECTURE.md | 22 +++++++++++++++------- index.html | 2 ++ public/favicon.svg | 24 ++++++++++++++++++++++++ src/index.css | 39 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 80 insertions(+), 7 deletions(-) create mode 100644 public/favicon.svg diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index b018356..4f68d2a 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -374,7 +374,7 @@ All `/api/*` routes return JSON. Every route except the public auth/config endpo | +-- /caddy +-- GET /status # Caddy admin API reachable? [auth] - +-- GET /routes # { system, custom } routes [auth] + +-- GET /routes # Custom routes (plain array) [auth] +-- POST /routes # Add custom route + push config [auth] +-- PUT /routes/{id} # Update custom route + push config [auth] +-- DELETE /routes/{id} # Remove custom route + push config [auth] @@ -481,15 +481,19 @@ pushCaddyConfig(): POST /load (Content-Type: text/caddyfile) ### 6.4 First-start Initialization -Runs in `startServer()` before any routes are registered, every startup — both operations -are idempotent and only fire once on a blank database. +Runs in `startServer()` on every startup — each step is idempotent. ``` -Default admin user: +Default admin user (only on a blank database): if users table is empty: - INSERT user (name='Admin', role='Admin', email='admin@ghostgrid.local', password=bcrypt('admin')) + INSERT user (name='admin', role='admin', email='admin@ghostgrid.local', password=bcrypt('admin')) → log "[Init] Default admin user created" +Caddy route import (re-deploy safety net): + if caddy_enabled === 'true' AND caddy table is empty: + importCaddyfileRoutes() → seed routes from /etc/caddy/Caddyfile + (also runs in PUT /api/settings on the disabled → enabled transition) + Default settings: INSERT OR IGNORE all DEFAULT_SETTINGS keys from server-db.ts → existing values in the settings table are never overwritten @@ -577,7 +581,8 @@ Settings +-- CheckMK (API URL/user/secret, sync interval, "Run sync now") +-- Ansible Semaphore (API URL/token/project, "Test connection") +-- Caddy (admin URL, custom route management; - auto-seeded from /etc/caddy/Caddyfile on first enable) + auto-seeded from /etc/caddy/Caddyfile on first enable; + https:// upstream → TLS proxy, certificate not verified) +-- Secret inputs use the __SET__ sentinel (blank = keep existing) ``` @@ -696,7 +701,9 @@ Backup : ghostgrid.db + ghostgrid.db-wal + ghostgrid.db-shm GhostGrid/ +-- server.ts # Express app: all routes, auth, integrations, background jobs +-- server-db.ts # SQLite connection, full schema, settings/Caddy helpers -+-- index.html # Vite HTML entry (#root > src/main.tsx) ++-- index.html # Vite HTML entry (#root > src/main.tsx); links /favicon.svg ++-- public/ +| +-- favicon.svg # app favicon (GhostGrid logo; served at site root by Vite) +-- vite.config.ts # Vite + React + Tailwind; '@' alias > repo root +-- tsconfig.json # noEmit, react-jsx, bundler resolution +-- package.json # scripts + deps (package name "react-example" is vestigial) @@ -820,6 +827,7 @@ Express (server.ts) ──► better-sqlite3 (ghostgrid.db, WAL) - Booking boolean flags are 0/1 integers in SQLite, mapped on read. - A new settings key must be: **seeded** in `server-db.ts`, **allow-listed** in `PUT /api/settings`, and (if secret) added to `SECRET_KEYS`. - Schema changes go straight into the `CREATE TABLE` block in `server-db.ts` — fresh-install model, no migration helper. +- The SPA catch-all (`app.get('*')`) + static serving are registered **last** in `startServer()`, after every `/api` route — otherwise GET `/api/*` falls through to `index.html`. All `/api` responses carry `Cache-Control: no-store`. - All user-facing strings are in **English**. --- diff --git a/index.html b/index.html index 80f5d5e..004334c 100644 --- a/index.html +++ b/index.html @@ -3,6 +3,8 @@ + + GhostGrid diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..43b6654 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/index.css b/src/index.css index a5b8127..a7971a8 100644 --- a/src/index.css +++ b/src/index.css @@ -872,3 +872,42 @@ :root.light .group:hover .group-hover\:text-slate-300 { color: var(--text-muted) !important; } + +/* ── Settings → Caddy section: sky accent ─────────────────────────── */ +/* sky-* is used only by the Caddy card; map its dark tokens to light. */ +:root.light .bg-sky-950\/60, +:root.light .bg-sky-950\/40, +:root.light .bg-sky-900\/40 { + background-color: #e0f2fe !important; + border-color: #7dd3fc !important; + color: #0369a1 !important; +} + +:root.light .border-sky-900\/50, +:root.light .border-sky-900\/40 { + border-color: #7dd3fc !important; +} + +:root.light .text-sky-400, +:root.light .text-sky-500 { + color: #0284c7 !important; +} + +:root.light .bg-sky-950\/30, +:root.light .hover\:bg-sky-950\/30:hover { + background-color: #e0f2fe !important; +} + +:root.light .hover\:bg-sky-900\/40:hover { + background-color: #bae6fd !important; +} + +:root.light .hover\:text-sky-400:hover { + color: #0284c7 !important; +} + +/* Delete-icon hover (red-950/30 is the only red opacity not yet mapped) */ +:root.light .bg-red-950\/30, +:root.light .hover\:bg-red-950\/30:hover { + background-color: #fee2e2 !important; +}