0027 - 2026-02-26 - Dynamic Backup Buttons & TEKMidian Registration

Context

Changes made from the TEKMidian project session while registering TEKMidian in the ops dashboard.

Changes

1. Dynamic "Create Backup" Buttons (app.js)

Problem: The "Create Backup" buttons on the Backups page were hardcoded to only mdf and seriousletter: ```javascript for (const p of ['mdf', 'seriousletter']) { for (const e of ['dev', 'int', 'prod']) { ```

Fix: Made buttons dynamic from the /api/schedule/ endpoint. Now all backup-enabled projects get buttons automatically based on their configured environments: ```javascript for (const s of (cachedSchedules || [])) { if (!s.enabled) continue; const envs = s.backup_environments || s.environments || []; // render button per environment } ```

Also added schedule data fetch in renderBackups() alongside the existing backup/offsite fetches: ```javascript const [local, offsite, schedules] = await Promise.all([ api('/api/backups/'), api('/api/backups/offsite').catch(() => []), cachedSchedules ? Promise.resolve(cachedSchedules) : api('/api/schedule/').catch(() => []), ]); ```

2. Empty-State Project Cards (app.js)

Problem: Projects with backup config but no backups yet didn't appear in the project cards grid (only projects with existing backup files showed up).

Fix: After the existing project cards loop, added a second loop over cachedSchedules to show backup-configured projects that have 0 backups as dashed-border cards: ```javascript for (const s of (cachedSchedules || [])) { if (!s.enabled || projects[s.project]) continue; // render dashed card with "0 backups" and "No backups yet" } ```

3. Cache Busting

Files Modified (on server)

Notes