Skip to content

feat(homepage): smooth load + single-pane-of-glass for all UI apps#1608

Merged
devantler merged 1 commit into
mainfrom
claude/exciting-euclid-00e1c3
May 28, 2026
Merged

feat(homepage): smooth load + single-pane-of-glass for all UI apps#1608
devantler merged 1 commit into
mainfrom
claude/exciting-euclid-00e1c3

Conversation

@devantler
Copy link
Copy Markdown
Contributor

Eliminates the cold-load flicker and surfaces every UI-bearing app on the dashboard, so the homepage is genuinely the one entry point for every hosted service.

Flicker — two root causes

  1. Remote Unsplash background image (~2000px wide) applied via inline style after React hydration. Browser painted default white before the image — and before the slate theme color — applied, producing a visible flash on every cold load and after each oauth2-proxy redirect.
  2. replicaCount=2 with default ClusterIP, no session affinity. The Kubernetes widget polls cluster/node CPU+memory every few seconds; round-robin between two pods (each with its own kube-apiserver watcher cache) made values pop between slightly-stale and slightly-fresh on every refresh.

Fix

  • Drop background.image, background.blur, background.opacity, and cardBlur entirely. Replace with a soft two-point radial mesh gradient in custom.css (slate-950 base, subtle blue + violet auras, background-attachment: fixed). Zero remote assets — flicker is now structurally impossible.
  • Lean into Homepage's own modern UI options: headerStyle: clean, statusStyle: dot, iconStyle: gradient, hideVersion: true, target: _blank.
  • Pin the homepage Service to sessionAffinity: ClientIP via a post-renderer patch so each oauth2-proxy backend sticks to one homepage replica and the widget reads from a consistent cache.

Coverage

Every UI-bearing HTTPRoute now carries gethomepage.dev/* annotations so auto-discovery picks them up:

App Group Source of annotations
actual-budget Finance base (existing)
whoami Diagnostics base — added href + pod-selector
fleetdm Device Management base (existing)
headlamp Kubernetes base — added href + pod-selector
openbao (Vault) Security base (existing)
flux-operator Kubernetes base (existing)
hubble-ui Diagnostics base (existing)
wedding-app Personal Sites hetzner Flux Kustomization patch (new)
ascoachingogvaner Customer Sites hetzner Flux Kustomization patch (new)

wedding-app and ascoachingogvaner ship their HTTPRoute from external OCI artifacts (oci://ghcr.io/devantler-tech/{wedding-app,ascoachingogvaner}/manifests), so the annotations are injected via the existing Flux Kustomization spec.patches — the same place that already rewrites their hostnames. Strategic-merge patch (not JSON-Patch op: add /metadata/annotations) so we merge into — rather than overwrite — any annotations on the upstream HTTPRoute.

The layout: in settings.yaml now lists the previously-unmapped groups (Security, Finance, Personal Sites, Customer Sites) with intentional icons and a deliberate render order.

Correctly excluded from auto-discovery: the HTTP→HTTPS redirect route, homepage's own route, oauth2-proxy, and dex (OIDC IdP — only visited as a login redirect).

Cleanup

  • Removed the stale goldilocks.platform.lan line from hosts — no Goldilocks resources exist anywhere in the repo.

Validation

  • `ksail --config ksail.yaml workload validate` → 254/254 files validated ✓
  • `ksail --config ksail.prod.yaml workload validate` → 254/254 files validated ✓
  • `kubectl kustomize` of both `k8s/clusters/local` and `k8s/clusters/prod` build clean
  • `kubectl kustomize k8s/providers/hetzner/apps/` confirms the wedding-app / ascoachingogvaner Flux Kustomization carries the new strategic-merge patch alongside the existing hostname patch

🤖 Generated with Claude Code

Eliminates the cold-load flicker and surfaces every UI-bearing app on the
dashboard, so the homepage is genuinely the one entry point for every
hosted service.

## Flicker — two root causes

1. **Remote Unsplash background image** (~2000px wide) applied via inline
   style after React hydration. Browser painted default white before the
   image — and before the slate theme color — applied, producing a
   visible flash on every cold load and after each oauth2-proxy redirect.
2. **replicaCount=2 with default ClusterIP, no session affinity.** The
   Kubernetes widget polls cluster/node CPU+memory every few seconds;
   round-robin between two pods (each with its own kube-apiserver watcher
   cache) made values pop between slightly-stale and slightly-fresh on
   every refresh.

## Fix

- Drop `background.image`, `background.blur`, `background.opacity`, and
  `cardBlur` entirely. Replace with a soft two-point radial mesh
  gradient in `custom.css` (slate-950 base, subtle blue + violet auras,
  `background-attachment: fixed`). Zero remote assets — flicker is now
  structurally impossible.
- Lean into Homepage's own modern UI options: `headerStyle: clean`,
  `statusStyle: dot`, `iconStyle: gradient`, `hideVersion: true`,
  `target: _blank`.
- Pin the homepage Service to `sessionAffinity: ClientIP` via a
  post-renderer patch so each oauth2-proxy backend sticks to one
  homepage replica and the widget reads from a consistent cache.

## Coverage

Every UI-bearing HTTPRoute now carries `gethomepage.dev/*` annotations
so auto-discovery picks them up:

| App                | Group           | Source of annotations               |
|--------------------|-----------------|-------------------------------------|
| actual-budget      | Finance         | base (existing)                     |
| whoami             | Diagnostics     | base — added `href`+`pod-selector`  |
| fleetdm            | Device Mgmt     | base (existing)                     |
| headlamp           | Kubernetes      | base — added `href`+`pod-selector`  |
| openbao (Vault)    | Security        | base (existing)                     |
| flux-operator      | Kubernetes      | base (existing)                     |
| hubble-ui          | Diagnostics     | base (existing)                     |
| wedding-app        | Personal Sites  | hetzner Flux Kustomization patch    |
| ascoachingogvaner  | Customer Sites  | hetzner Flux Kustomization patch    |

wedding-app and ascoachingogvaner ship their HTTPRoute from external OCI
artifacts (`oci://ghcr.io/devantler-tech/{wedding-app,ascoachingogvaner}/
manifests`), so the annotations are injected via the existing Flux
Kustomization `spec.patches` — the same place that already rewrites
their hostnames. Strategic-merge patch (not JSON-Patch `op: add
/metadata/annotations`) so we merge into — rather than overwrite — any
annotations on the upstream HTTPRoute.

The `layout:` in settings.yaml now lists the previously-unmapped groups
(`Security`, `Finance`, `Personal Sites`, `Customer Sites`) with
intentional icons and a deliberate render order.

Correctly excluded from auto-discovery: the HTTP→HTTPS redirect route,
homepage's own route, oauth2-proxy, and dex (OIDC IdP — only visited as
a login redirect).

## Cleanup

- Removed the stale `goldilocks.platform.lan` line from `hosts` — no
  Goldilocks resources exist anywhere in the repo.

Validated with `ksail workload validate` against both `ksail.yaml` and
`ksail.prod.yaml` (254/254 each).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 28, 2026 07:38
@devantler devantler marked this pull request as ready for review May 28, 2026 07:40
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR improves the Homepage dashboard experience by removing cold-load flicker sources (remote background + inconsistent widget polling across replicas) and ensuring all UI-bearing apps are discoverable and grouped consistently via gethomepage.dev/* annotations.

Changes:

  • Removes the remote background.image configuration and replaces it with a local CSS radial-mesh gradient backdrop.
  • Adds/extends gethomepage.dev/* discovery annotations (including href and pod-selector) so more UI apps appear correctly on the Homepage dashboard.
  • Pins the Homepage Service with sessionAffinity: ClientIP via Helm post-render patching to stabilize Kubernetes widget polling across multiple replicas.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.

Show a summary per file
File Description
k8s/providers/hetzner/apps/wedding-app/patches/kustomization-patch.yaml Injects Homepage discovery annotations onto the upstream (OCI-sourced) HTTPRoute via strategic-merge patch.
k8s/providers/hetzner/apps/ascoachingogvaner/patches/kustomization-patch.yaml Injects Homepage discovery annotations onto the upstream (OCI-sourced) HTTPRoute via strategic-merge patch.
k8s/bases/apps/whoami/httproute.yaml Adds href + pod-selector annotations to improve Homepage auto-discovery and widget targeting.
k8s/bases/apps/homepage/helm-release.yaml Adds a post-render JSON6902 patch to enable sessionAffinity: ClientIP on the Homepage Service.
k8s/bases/apps/homepage/config-map.yaml Updates Homepage settings (layout/groups/UI style) and replaces the remote background image with local custom.css gradient.
k8s/bases/apps/headlamp/httproute.yaml Adds href + pod-selector annotations to improve Homepage auto-discovery and widget targeting.
hosts Removes stale goldilocks.platform.lan entry.

@devantler devantler added this pull request to the merge queue May 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 28, 2026
@devantler devantler added this pull request to the merge queue May 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 28, 2026
@devantler devantler added this pull request to the merge queue May 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 28, 2026
@devantler devantler added this pull request to the merge queue May 28, 2026
@github-merge-queue github-merge-queue Bot removed this pull request from the merge queue due to failed status checks May 28, 2026
@devantler devantler added this pull request to the merge queue May 28, 2026
Merged via the queue into main with commit 3e6a7c7 May 28, 2026
10 checks passed
@devantler devantler deleted the claude/exciting-euclid-00e1c3 branch May 28, 2026 21:28
@github-project-automation github-project-automation Bot moved this from 🫴 Ready to ✅ Done in 🌊 Project Board May 28, 2026
@botantler
Copy link
Copy Markdown
Contributor

botantler Bot commented May 28, 2026

🎉 This PR is included in version 1.12.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: ✅ Done

Development

Successfully merging this pull request may close these issues.

2 participants