From 2900a668616894c6350ad46def8e3eb71bf32c58 Mon Sep 17 00:00:00 2001 From: xarmian Date: Wed, 29 Apr 2026 23:23:39 -0400 Subject: [PATCH] feat(auth): footer parity with marketing site on auth-page family (TASK-903) (#314) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(auth): footer parity with marketing site on auth-page family (TASK-903) New replaces the prior LegalFooter + SupportFooter pair. Single component matches the brand spec (docs/brand.md §7) which describes ONE footer pattern, not two separate strips. Cloud mode (cloudMode=true) carries the full getpad.dev marketing footer: copyright line ("© Pad · Perpetual Software") + the nine-link list in canonical order — GitHub, Docs, Changelog, Contribute, FAQ, Security, Privacy, Terms, Sub-processors. Visual contract anchored on pad-web/src/routes/+layout.svelte (border-top, max-w-6xl, flex-wrap, sm: breakpoint at 640px). Self-hosted (cloudMode=false) renders the legal-essentials only — Terms / Privacy / Sub-processors — preserving the visual treatment of the prior LegalFooter exactly so existing self-hosted deployments see no change after this PR. The Status / Support / GitHub / Changelog / Contribute / FAQ / Security links were Cloud-only in the prior shape too; that stays the case. Wired the new AuthFooter into all five auth-family pages: - /login (replaces LegalFooter + SupportFooter) - /register (replaces LegalFooter + SupportFooter) - /forgot-password (replaces LegalFooter + SupportFooter) - /reset-password/[token] (NEW — was footer-less) - /join/[code] (NEW — was footer-less) LegalFooter.svelte and SupportFooter.svelte are deleted; they were internal to the auth-pages feature and never used elsewhere (grep-verified). AuthHeader's comment that referenced them is updated to point at AuthFooter instead. Year is computed once per page render via new Date().getFullYear() — no auto-refresh needed since auth pages don't sit open across a year boundary in any realistic flow. Parent: PLAN-900. Test plan: - web/npm run check — 0 errors (692 files now, was 693; net -1 reflects 2 deletions + 1 addition) - web/npm run build — clean - go build ./... && go vet ./... && go test ./... — all pass - Svelte autofixer — clean * fix(auth): self-hosted AuthFooter renders nothing per Codex review (round 2) Codex P1: the prior LegalFooter + SupportFooter both gated their entire body on `{#if cloudMode}` — i.e. self-hosted rendered nothing at all. The first draft of AuthFooter incorrectly assumed self-hosted should get the legal-essentials subset (Terms / Privacy / Sub-processors links), which would have rendered getpad.dev's hosted-service legal links on someone else's deployment, misrepresenting the operator's own legal terms. Revert the self-hosted branch to render nothing. The brand spec (docs/brand.md §7) already flags an operator-owned legal/footer mechanism as deferred to the operator-branding follow-up plan, so this restores the prior behavior exactly. Removed the now-dead self-hosted link list, the .auth-footer-legal CSS rules, and the $derived links computation. * fix(auth): flex-direction on reset-password + join wrappers per Codex (round 3) Codex P2: AuthFooter on /reset-password/[token] and /join/[code] sat horizontally next to the auth card instead of below it because those two page wrappers were `display: flex` without `flex-direction: column`. The other three auth pages (login, register, forgot-password) already had column layout so they were unaffected — only the two pages that gained a footer in this PR were broken. Add `flex-direction: column` to .page (reset-password) and .join-page so the footer renders below the card on those routes too. --- web/src/lib/components/auth/AuthFooter.svelte | 156 ++++++++++++++++++ web/src/lib/components/auth/AuthHeader.svelte | 2 +- .../lib/components/auth/LegalFooter.svelte | 51 ------ .../lib/components/auth/SupportFooter.svelte | 47 ------ web/src/routes/forgot-password/+page.svelte | 6 +- web/src/routes/join/[code]/+page.svelte | 4 + web/src/routes/login/+page.svelte | 6 +- web/src/routes/register/+page.svelte | 6 +- .../reset-password/[token]/+page.svelte | 4 + 9 files changed, 171 insertions(+), 111 deletions(-) create mode 100644 web/src/lib/components/auth/AuthFooter.svelte delete mode 100644 web/src/lib/components/auth/LegalFooter.svelte delete mode 100644 web/src/lib/components/auth/SupportFooter.svelte diff --git a/web/src/lib/components/auth/AuthFooter.svelte b/web/src/lib/components/auth/AuthFooter.svelte new file mode 100644 index 00000000..9bc9c072 --- /dev/null +++ b/web/src/lib/components/auth/AuthFooter.svelte @@ -0,0 +1,156 @@ + + +{#if cloudMode} + +{/if} + + + diff --git a/web/src/lib/components/auth/AuthHeader.svelte b/web/src/lib/components/auth/AuthHeader.svelte index 797f16ac..fd10beb1 100644 --- a/web/src/lib/components/auth/AuthHeader.svelte +++ b/web/src/lib/components/auth/AuthHeader.svelte @@ -12,7 +12,7 @@ // // Self-hosted (cloudMode === false) renders nothing — operators ship Pad // under their own brand and must not get getpad.dev chrome imposed on them. - // This matches the existing pattern in LegalFooter.svelte / SupportFooter.svelte. + // Same pattern as the companion AuthFooter.svelte in this directory. let { cloudMode = false }: { cloudMode?: boolean } = $props(); diff --git a/web/src/lib/components/auth/LegalFooter.svelte b/web/src/lib/components/auth/LegalFooter.svelte deleted file mode 100644 index 7b728f8c..00000000 --- a/web/src/lib/components/auth/LegalFooter.svelte +++ /dev/null @@ -1,51 +0,0 @@ - - -{#if cloudMode} - -{/if} - - diff --git a/web/src/lib/components/auth/SupportFooter.svelte b/web/src/lib/components/auth/SupportFooter.svelte deleted file mode 100644 index bdad00f1..00000000 --- a/web/src/lib/components/auth/SupportFooter.svelte +++ /dev/null @@ -1,47 +0,0 @@ - - -{#if cloudMode} - -{/if} - - diff --git a/web/src/routes/forgot-password/+page.svelte b/web/src/routes/forgot-password/+page.svelte index dc850f37..9a2f3511 100644 --- a/web/src/routes/forgot-password/+page.svelte +++ b/web/src/routes/forgot-password/+page.svelte @@ -3,8 +3,7 @@ import { api } from '$lib/api/client'; import { authStore } from '$lib/stores/auth.svelte'; import AuthHeader from '$lib/components/auth/AuthHeader.svelte'; - import LegalFooter from '$lib/components/auth/LegalFooter.svelte'; - import SupportFooter from '$lib/components/auth/SupportFooter.svelte'; + import AuthFooter from '$lib/components/auth/AuthFooter.svelte'; let email = $state(''); let error = $state(''); @@ -100,8 +99,7 @@ {/if} - - +