From 4172b63dc2b098d9fb26d38f3b43e91e82741de6 Mon Sep 17 00:00:00 2001 From: derekc Date: Mon, 23 Mar 2026 22:50:30 -0700 Subject: [PATCH] Add footer with CHNS.tech credit and Buy Me a Coffee button Adds a green footer (matching nav colour) to all authenticated pages with a "Created by: CHNS.tech" link and a styled BMC button. CSP updated to allow buymeacoffee CDN domains. Co-Authored-By: Claude Sonnet 4.6 --- README.md | 34 +++++++++++++++++++++++------ nginx/html/admin.html | 5 +++++ nginx/html/budget.html | 5 +++++ nginx/html/css/style.css | 47 ++++++++++++++++++++++++++++++++++++++++ nginx/html/flock.html | 5 +++++ nginx/html/index.html | 5 +++++ nginx/html/log.html | 5 +++++ nginx/html/summary.html | 5 +++++ nginx/nginx.conf | 2 +- 9 files changed, 105 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d9e0639..abcf00d 100644 --- a/README.md +++ b/README.md @@ -44,17 +44,24 @@ A self-hosted, multi-user web app for backyard chicken keepers to track egg prod cp .env.example .env ``` - Key variables: + Required variables: | Variable | Description | |----------|-------------| | `MYSQL_ROOT_PASSWORD` | MySQL root password — generate with `openssl rand -hex 16` | + | `MYSQL_DATABASE` | Database name (default: `eggtracker`) | + | `MYSQL_USER` | MySQL app username | | `MYSQL_PASSWORD` | MySQL app user password | | `ADMIN_USERNAME` | Username for the built-in admin account | | `ADMIN_PASSWORD` | Password for the built-in admin account | | `JWT_SECRET` | JWT signing secret — generate with `openssl rand -hex 32` | - | `SECURE_COOKIES` | Set to `true` (default) when behind HTTPS; `false` for local HTTP testing only | - | `ALLOWED_ORIGINS` | Comma-separated list of external origins allowed to call the API. Leave empty if accessed only through the bundled nginx frontend. | + + Optional variables (with defaults): + + | Variable | Default | Description | + |----------|---------|-------------| + | `SECURE_COOKIES` | `true` | Set to `false` for local HTTP testing only; leave `true` when behind HTTPS | + | `ALLOWED_ORIGINS` | *(empty)* | Comma-separated list of external origins allowed to call the API. Leave empty if accessed only through the bundled nginx frontend. | 3. Start the stack: ```bash @@ -109,6 +116,10 @@ The gear icon (⚙) in the top-right nav opens the Settings panel: | SQL injection | SQLAlchemy ORM with parameterized queries throughout | | Container security | API runs as non-root user; all volume mounts read-only except database | +## Footer + +All authenticated pages include a footer with a **Created by: [CHNS.tech](https://chns.tech)** credit and a Buy Me a Coffee button linking to [buymeacoffee.com/CHNS](https://www.buymeacoffee.com/CHNS). + ## Migrating an Existing Install (pre-multi-user) If you have an existing single-user install, run the migration script before rebuilding: @@ -161,17 +172,26 @@ yolkbook/ │ └── Dockerfile ├── nginx/ │ ├── html/ # Frontend (HTML, CSS, JS) -│ │ ├── login.html -│ │ ├── admin.html │ │ ├── index.html # Dashboard │ │ ├── log.html # Log Eggs + full collection history +│ │ ├── flock.html # Flock management +│ │ ├── budget.html # Budget / cost analysis +│ │ ├── summary.html # Monthly summary +│ │ ├── admin.html # Admin panel +│ │ ├── login.html +│ │ ├── 404.html +│ │ ├── 50x.html │ │ ├── js/ │ │ │ ├── api.js # Shared fetch helpers │ │ │ ├── auth.js # Auth utilities, nav, settings modal │ │ │ ├── login.js # Login/register page logic -│ │ │ ├── admin.js # Admin panel +│ │ │ ├── dashboard.js +│ │ │ ├── log.js # Egg logging interface │ │ │ ├── history.js # Collection history table (used on log page) -│ │ │ └── dashboard.js +│ │ │ ├── flock.js +│ │ │ ├── budget.js +│ │ │ ├── summary.js +│ │ │ └── admin.js # Admin panel │ │ └── css/style.css │ └── nginx.conf ├── mysql/ diff --git a/nginx/html/admin.html b/nginx/html/admin.html index ef2ad0d..8029ed6 100644 --- a/nginx/html/admin.html +++ b/nginx/html/admin.html @@ -77,6 +77,11 @@ + + diff --git a/nginx/html/budget.html b/nginx/html/budget.html index c490712..62de959 100644 --- a/nginx/html/budget.html +++ b/nginx/html/budget.html @@ -122,6 +122,11 @@ + + diff --git a/nginx/html/css/style.css b/nginx/html/css/style.css index 330abc4..af992ae 100644 --- a/nginx/html/css/style.css +++ b/nginx/html/css/style.css @@ -23,6 +23,9 @@ body { background: var(--bg); color: var(--text); line-height: 1.5; + min-height: 100vh; + display: flex; + flex-direction: column; } a { color: var(--green); text-decoration: none; } @@ -75,6 +78,8 @@ a:hover { text-decoration: underline; } max-width: 980px; margin: 0 auto; padding: 2rem 1.5rem; + flex: 1; + width: 100%; } h1 { font-size: 1.6rem; margin-bottom: 1.5rem; } @@ -414,3 +419,45 @@ td input[type="date"] { padding: 0 0.25rem; line-height: 1; } + +/* ── Footer ──────────────────────────────────────────────────────────────── */ +.site-footer { + background: var(--green); + color: rgba(255,255,255,0.85); + padding: 1rem 1.5rem; + display: flex; + align-items: center; + justify-content: center; + gap: 1.25rem; + flex-wrap: wrap; + font-size: 0.9rem; + margin-top: auto; +} + +.site-footer a { + color: #fff; + font-weight: 600; + text-decoration: none; +} + +.site-footer a:hover { + text-decoration: underline; +} + +.bmc-btn { + display: inline-block; + background: #d4850a; + color: #000 !important; + font-family: Arial, sans-serif; + font-size: 0.8rem; + font-weight: 700; + padding: 0.3rem 0.75rem; + border-radius: 6px; + border: 1px solid rgba(0,0,0,0.3); + white-space: nowrap; + text-decoration: none !important; +} +.bmc-btn:hover { + background: #c07609; + text-decoration: none !important; +} diff --git a/nginx/html/flock.html b/nginx/html/flock.html index 8dd546f..f1095a1 100644 --- a/nginx/html/flock.html +++ b/nginx/html/flock.html @@ -79,6 +79,11 @@ + + diff --git a/nginx/html/index.html b/nginx/html/index.html index 66005dd..8359f7c 100644 --- a/nginx/html/index.html +++ b/nginx/html/index.html @@ -70,6 +70,11 @@ + + diff --git a/nginx/html/log.html b/nginx/html/log.html index 6a87091..3e3dda9 100644 --- a/nginx/html/log.html +++ b/nginx/html/log.html @@ -83,6 +83,11 @@ + + diff --git a/nginx/html/summary.html b/nginx/html/summary.html index bf53a47..eba2d4a 100644 --- a/nginx/html/summary.html +++ b/nginx/html/summary.html @@ -66,6 +66,11 @@ + + diff --git a/nginx/nginx.conf b/nginx/nginx.conf index 0f55c84..e8292a6 100644 --- a/nginx/nginx.conf +++ b/nginx/nginx.conf @@ -33,7 +33,7 @@ http { add_header X-Frame-Options "SAMEORIGIN" always; add_header X-XSS-Protection "1; mode=block" always; add_header Referrer-Policy "strict-origin-when-cross-origin" always; - add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'; font-src 'self'; frame-ancestors 'none'" always; + add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net https://cdnjs.buymeacoffee.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://cdn.buymeacoffee.com https://img.buymeacoffee.com; connect-src 'self'; font-src 'self'; frame-ancestors 'none'" always; # ── Static files ────────────────────────────────────────────────────── location / {