diff --git a/deploy/caddy/Caddyfile.snapshot b/deploy/caddy/Caddyfile.snapshot index 33a1eb1..6f211be 100644 --- a/deploy/caddy/Caddyfile.snapshot +++ b/deploy/caddy/Caddyfile.snapshot @@ -46,6 +46,12 @@ upbeatbytes.com { } encode gzip zstd + # Retired prototype routes (promoted/removed at the news relaunch) → the hub. + @oldhome path /home2 /home2.html /home3 /home3.html + handle @oldhome { + redir / permanent + } + # Dynamic API + server-rendered pages (share, digest, sitemap) → FastAPI. @api path /api/* /healthz /docs /docs/* /openapi.json /a/* /today /sitemap.xml handle @api { @@ -60,15 +66,10 @@ upbeatbytes.com { # Hidden in-progress prototypes — keep crawlers out at the HTTP level (the JS # isn't seen by non-JS bots since the static shell is generic). - @hidden path /home2 /home3 /word /word.html /quote /quote.html /onthisday /onthisday.html /admin /admin.html + # Only admin stays out of the index now — news, art, play, and the joy pages are public. + @hidden path /admin /admin.html header @hidden X-Robots-Tag "noindex, nofollow" - # /news is the feed's future home — rendered during the relaunch transition but kept - # noindex (FOLLOW, so link equity still flows) until cutover, when this line is removed - # and /news enters the sitemap. Avoids publishing a duplicate indexable feed. - @newsHidden path /news /news.html - header @newsHidden X-Robots-Tag "noindex, follow" - # Content-hashed assets never change for a given URL — cache them forever. @immutable path /_app/immutable/* header @immutable Cache-Control "public, max-age=31536000, immutable" diff --git a/frontend/scripts/patch-static-heads.mjs b/frontend/scripts/patch-static-heads.mjs index f79ba49..dd1ba88 100644 --- a/frontend/scripts/patch-static-heads.mjs +++ b/frontend/scripts/patch-static-heads.mjs @@ -11,6 +11,12 @@ const BASE = 'https://upbeatbytes.com'; // Per-page overrides. Keep titles/descriptions in sync with each page's intent. const PAGES = [ + { + file: 'news.html', path: '/news', + title: 'News · upbeatBytes — calm, constructive news', + desc: 'Calm, constructive news, newest first — and a daily Highlights brief. ' + + 'No ads, no paywalls, no doomscrolling.', + }, { file: 'play.html', path: '/play', title: 'Play · Upbeat Bytes — calm daily games', diff --git a/frontend/src/app.html b/frontend/src/app.html index 3079735..283dda1 100644 --- a/frontend/src/app.html +++ b/frontend/src/app.html @@ -7,17 +7,17 @@ - + Upbeat Bytes — calm, constructive news - + - + %sveltekit.head% diff --git a/frontend/src/lib/components/HubBar.svelte b/frontend/src/lib/components/HubBar.svelte index b579a83..3b460bb 100644 --- a/frontend/src/lib/components/HubBar.svelte +++ b/frontend/src/lib/components/HubBar.svelte @@ -2,9 +2,8 @@ // Shared editorial top bar for the hub (/home3) and its detail pages (/word, /quote, // /onthisday). Full horizontal nav on wide screens; a hamburger + drop panel on phones // so the bar stays clean. `active` highlights the current section. - // `newsHref` is configurable so the transitional /news instance links News → /news - // (not the current `/`, which is still the live feed until cutover). - let { active = '', newsHref = '/' } = $props(); + // News now lives at /news (the hub is `/`). `newsHref` stays overridable for safety. + let { active = '', newsHref = '/news' } = $props(); let open = $state(false); // Close the menu when we cross into desktop width, so it can't linger open and reappear @@ -17,7 +16,7 @@ }); let LINKS = $derived([ - { key: 'home', href: '/home3', label: 'Home' }, + { key: 'home', href: '/', label: 'Home' }, { key: 'news', href: newsHref, label: 'News' }, { key: 'games', href: '/play', label: 'Games' }, { key: 'art', href: '/art', label: 'Art' }, @@ -27,7 +26,7 @@ { if (e.key === 'Escape') open = false; }} />
- + upbeatBytes diff --git a/frontend/src/lib/components/HubShell.svelte b/frontend/src/lib/components/HubShell.svelte index 5c1704e..51a909e 100644 --- a/frontend/src/lib/components/HubShell.svelte +++ b/frontend/src/lib/components/HubShell.svelte @@ -3,6 +3,7 @@ // top bar, footer, fonts, and design tokens. Content goes in the default slot. import { afterNavigate, goto } from '$app/navigation'; import HubBar from './HubBar.svelte'; + import Footer from './Footer.svelte'; let { active = '', back = true, backLabel = 'Back', children } = $props(); // Same single-history rule as the News reader's in-page Back: if we arrived here by an @@ -14,7 +15,7 @@ if (cameFromApp && typeof history !== 'undefined') history.back(); // Cold deep-link: no in-app origin. REPLACE this entry rather than pushing one, so the // browser Back from the hub doesn't bounce the reader straight back into the detail page. - else goto('/home3', { replaceState: true }); + else goto('/', { replaceState: true }); } @@ -33,7 +34,7 @@ {@render children?.()} -
upbeatBytes — no ads, no paywalls, no doomscrolling.
+