brand: standardize "Upbeat Bytes" → "upbeatBytes" everywhere
Per the logo + brand: the name is upbeatBytes (camelCase). Swept all user-facing strings — titles/og:site_name/og:title, logo alt text, share pages (share.py), emails (email_send), classifier prompt (llm), digest/unsubscribe (api), PWA manifest, game share text, sign-in, the SPA shell + patch-static-heads (play title) — plus README/publish.sh and the email test fixture. (SMTP From env was already upbeatBytes.) Domains (upbeatbytes.com) unchanged. 425 BE + 36 FE green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -19,7 +19,7 @@ const PAGES = [
|
||||
},
|
||||
{
|
||||
file: 'play.html', path: '/play',
|
||||
title: 'Play · Upbeat Bytes — calm daily games',
|
||||
title: 'Play · upbeatBytes — calm daily games',
|
||||
desc: 'A calm set of daily games — Daily Word, Word Search, Bloom, and Memory Match. ' +
|
||||
'A friendly little break from the doomscroll.',
|
||||
},
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
font-display: swap;
|
||||
}
|
||||
|
||||
/* Upbeat Bytes calm design system.
|
||||
/* upbeatBytes calm design system.
|
||||
Sand, sea, and sun: warm paper surfaces, a vivid-azure accent, gold highlight,
|
||||
a serif voice for headlines, strong readable contrast, generous space.
|
||||
No urgency colors (no red). Built around the logo's #0083ad azure. */
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<meta name="description" content="A calmer, brighter corner of the internet: good news, daily art, small games, and little resets." />
|
||||
<title>upbeatBytes — a calmer, brighter corner of the internet</title>
|
||||
<link rel="canonical" href="https://upbeatbytes.com/" />
|
||||
<meta property="og:site_name" content="Upbeat Bytes" />
|
||||
<meta property="og:site_name" content="upbeatBytes" />
|
||||
<meta property="og:type" content="website" />
|
||||
<meta property="og:title" content="upbeatBytes — a calmer, brighter corner of the internet" />
|
||||
<meta property="og:description" content="A calmer, brighter corner of the internet: good news, daily art, small games, and little resets. No ads, no paywalls, no doomscrolling." />
|
||||
@@ -128,9 +128,9 @@
|
||||
<div style="display: contents">%sveltekit.body%</div>
|
||||
<div id="boot-fallback" role="alert" aria-live="polite">
|
||||
<div class="bf">
|
||||
<img src="%sveltekit.assets%/logo.svg" alt="Upbeat Bytes" />
|
||||
<img src="%sveltekit.assets%/logo.svg" alt="upbeatBytes" />
|
||||
<p>We had a little trouble loading. A quick refresh usually sorts it out.</p>
|
||||
<button type="button" onclick="location.reload()">Refresh Upbeat Bytes</button>
|
||||
<button type="button" onclick="location.reload()">Refresh upbeatBytes</button>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
@@ -59,7 +59,7 @@
|
||||
if (value) onaction?.(kind, value);
|
||||
}
|
||||
|
||||
// Sharing: share the branded Upbeat Bytes card page (default), with copy-source.
|
||||
// Sharing: share the branded upbeatBytes card page (default), with copy-source.
|
||||
let shareOpen = $state(false);
|
||||
let copied = $state('');
|
||||
const canNativeShare = typeof navigator !== 'undefined' && !!navigator.share;
|
||||
@@ -105,7 +105,7 @@
|
||||
</a>
|
||||
{:else if usePlaceholder}
|
||||
<a class="media placeholder" href={summaryHref} onclick={opened} style="--c:{accentColor}" tabindex="-1" aria-hidden="true">
|
||||
<span class="ph-word">{humanize(article.topic) || 'upbeat bytes'}</span>
|
||||
<span class="ph-word">{humanize(article.topic) || 'upbeatBytes'}</span>
|
||||
</a>
|
||||
{/if}
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@
|
||||
const breakdown = Object.keys(byLen).sort((a, b) => b - a).map((l) => `${l}×${byLen[l]}`).join(' ');
|
||||
const pang = found.some(isPangram) ? ' · pangram ✓' : '';
|
||||
const bloomV = mode === 'daily' ? 'daily' : (format === 'wild' ? 'free-wild' : 'free-center');
|
||||
const text = `Upbeat Bytes · Bloom ${date}\n${fullBloom ? 'Full Bloom 🌸' : tier.name} · ${found.length} words${pang}\n${breakdown}\n${gameShareUrl('bloom', bloomV)}`;
|
||||
const text = `upbeatBytes · Bloom ${date}\n${fullBloom ? 'Full Bloom 🌸' : tier.name} · ${found.length} words${pang}\n${breakdown}\n${gameShareUrl('bloom', bloomV)}`;
|
||||
if (navigator.share) navigator.share({ text }).then(() => trackGame('bloom', 'shared')).catch(() => {});
|
||||
else navigator.clipboard?.writeText(text).then(() => { trackGame('bloom', 'shared'); copied = true; setTimeout(() => (copied = false), 1500); });
|
||||
}
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
|
||||
<header class="appbar">
|
||||
<div class="container bar">
|
||||
<a class="brand" href="/" aria-label="Upbeat Bytes — home">
|
||||
<img class="logo" src="/logo.svg" alt="Upbeat Bytes" width="586" height="196" />
|
||||
<a class="brand" href="/" aria-label="upbeatBytes — home">
|
||||
<img class="logo" src="/logo.svg" alt="upbeatBytes" width="586" height="196" />
|
||||
</a>
|
||||
|
||||
<nav class="utils" aria-label="Your controls">
|
||||
|
||||
@@ -133,7 +133,7 @@
|
||||
function share() {
|
||||
const label = `${TIER_LABEL[tier] || tier} · ${format === 'colors' ? 'colors' : 'icons'}`;
|
||||
const when = isFree ? 'Free play' : date;
|
||||
const text = `Upbeat Bytes · Memory Match (${label}) ${when}\nCleared in ${moves} moves\n${gameShareUrl('match', `${mode}-${format}-${tier}`)}`;
|
||||
const text = `upbeatBytes · Memory Match (${label}) ${when}\nCleared in ${moves} moves\n${gameShareUrl('match', `${mode}-${format}-${tier}`)}`;
|
||||
if (navigator.share) navigator.share({ text }).then(() => trackGame('match', 'shared')).catch(() => {});
|
||||
else navigator.clipboard?.writeText(text).then(() => { trackGame('match', 'shared'); copied = true; setTimeout(() => (copied = false), 1500); });
|
||||
}
|
||||
|
||||
@@ -181,7 +181,7 @@
|
||||
);
|
||||
let viewSubtitle = $derived(
|
||||
selected === 'today' ? localDateLabel(brief)
|
||||
: selected === 'search' ? 'Results across Upbeat Bytes'
|
||||
: selected === 'search' ? 'Results across upbeatBytes'
|
||||
: selected.startsWith('source:') ? 'Latest from this source'
|
||||
: selected === 'latest' ? 'Freshest calm reads — newest first'
|
||||
: selected === 'following' ? 'From the sources & topics you follow'
|
||||
@@ -629,7 +629,7 @@
|
||||
moods = m; topics = c.topics;
|
||||
await loadView(selected);
|
||||
} catch (e) {
|
||||
if (!brief) error = 'Could not reach Upbeat Bytes.'; // keep painted content if a refresh failed
|
||||
if (!brief) error = 'Could not reach upbeatBytes.'; // keep painted content if a refresh failed
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
@@ -872,7 +872,7 @@
|
||||
|
||||
{#if families.length}
|
||||
<section id="explore" class="explore">
|
||||
<h2>Explore Upbeat Bytes</h2>
|
||||
<h2>Explore upbeatBytes</h2>
|
||||
<div class="families">
|
||||
{#each families as f (f.name)}
|
||||
{@const tags = f.tags.filter((t) => t.count > 0)}
|
||||
@@ -895,7 +895,7 @@
|
||||
{#if !pwa.isStandalone && !pwa.dismissed && (pwa.canInstall || pwa.isIOS)}
|
||||
<aside class="install rise">
|
||||
<div class="install-text">
|
||||
<strong>Keep Upbeat Bytes a tap away.</strong>
|
||||
<strong>Keep upbeatBytes a tap away.</strong>
|
||||
{#if pwa.canInstall}Add it to your home screen — it opens like an app, no store needed.
|
||||
{:else}On iPhone: tap the <span class="ios-share">Share</span> button, then “Add to Home Screen.”{/if}
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</p>
|
||||
<button class="primary" onclick={onclose}>Done</button>
|
||||
{:else}
|
||||
<h2>Sign in to Upbeat Bytes</h2>
|
||||
<h2>Sign in to upbeatBytes</h2>
|
||||
<p class="sub">
|
||||
Save articles and keep your history across devices.
|
||||
</p>
|
||||
|
||||
@@ -167,7 +167,7 @@
|
||||
const label = variant === '6' ? 'Long Word' : 'Daily Word';
|
||||
const score = status === 'won' ? guesses.length : 'X';
|
||||
const grid = cols.map((cs) => cs.map((c) => EMOJI[c]).join('')).join('\n');
|
||||
const text = `Upbeat Bytes · ${label} ${date}\n${score}/${maxGuesses}\n${grid}\n${gameShareUrl('word', variant)}`;
|
||||
const text = `upbeatBytes · ${label} ${date}\n${score}/${maxGuesses}\n${grid}\n${gameShareUrl('word', variant)}`;
|
||||
// Count a share only once it actually happens (sheet completed / clipboard wrote),
|
||||
// never on a cancelled share sheet or denied clipboard.
|
||||
if (navigator.share) navigator.share({ text }).then(() => trackGame('word', 'shared')).catch(() => {});
|
||||
|
||||
@@ -223,7 +223,7 @@
|
||||
|
||||
function share() {
|
||||
const label = { small: 'Small', med: 'Medium', large: 'Large' }[size] || '';
|
||||
const text = `Upbeat Bytes · Word Search (${label}) ${date}\n${theme} — cleared in ${fmt(resultMs)}\n${gameShareUrl('wordsearch', size)}`;
|
||||
const text = `upbeatBytes · Word Search (${label}) ${date}\n${theme} — cleared in ${fmt(resultMs)}\n${gameShareUrl('wordsearch', size)}`;
|
||||
if (navigator.share) navigator.share({ text }).then(() => trackGame('wordsearch', 'shared')).catch(() => {});
|
||||
else navigator.clipboard?.writeText(text).then(() => { trackGame('wordsearch', 'shared'); copied = true; setTimeout(() => (copied = false), 1500); });
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<header class="bar">
|
||||
<div class="container inner">
|
||||
<a class="brand" href="/" aria-label="Upbeat Bytes — home"><img class="logo" src="/logo.svg" alt="Upbeat Bytes" /></a>
|
||||
<a class="brand" href="/" aria-label="upbeatBytes — home"><img class="logo" src="/logo.svg" alt="upbeatBytes" /></a>
|
||||
<div class="baractions">
|
||||
<button class="fb" onclick={openFeedback} aria-label="Share feedback" title="Share feedback">
|
||||
<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true"><path d="M4 5h16v11H8l-4 3z" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linejoin="round" /></svg>
|
||||
|
||||
@@ -675,7 +675,7 @@
|
||||
|
||||
<header class="bar">
|
||||
<div class="container inner">
|
||||
<a class="brand" href="/"><img class="logo" src="/logo.svg" alt="Upbeat Bytes" /></a>
|
||||
<a class="brand" href="/"><img class="logo" src="/logo.svg" alt="upbeatBytes" /></a>
|
||||
<a class="back" href="/account"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19 12H5M11 6l-6 6 6 6" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"/></svg>Account</a>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
{:else}
|
||||
<h1>Couldn't sign you in</h1>
|
||||
<p class="muted">{error}</p>
|
||||
<a class="back" href="/">← Back to Upbeat Bytes</a>
|
||||
<a class="back" href="/">← Back to upbeatBytes</a>
|
||||
{/if}
|
||||
</main>
|
||||
|
||||
|
||||
@@ -273,7 +273,7 @@
|
||||
<!-- Canonical/OG/description for /play are baked into the static play.html at build
|
||||
time (scripts/patch-static-heads.mjs) so non-JS social scrapers get them; we keep
|
||||
only the browser-tab title + dev-gate noindex here to avoid duplicate tags. -->
|
||||
<title>Play · Upbeat Bytes — calm daily games</title>
|
||||
<title>Play · upbeatBytes — calm daily games</title>
|
||||
{#if isDevGated(game)}<meta name="robots" content="noindex" />{/if}
|
||||
</svelte:head>
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>The Zen Den · Upbeat Bytes</title>
|
||||
<title>The Zen Den · upbeatBytes</title>
|
||||
{#if isDevGated('zen')}<meta name="robots" content="noindex" />{/if}
|
||||
</svelte:head>
|
||||
|
||||
<header class="bar">
|
||||
<div class="container inner">
|
||||
<a class="brand" href="/"><img class="logo" src="/logo.svg" alt="Upbeat Bytes" /></a>
|
||||
<a class="brand" href="/"><img class="logo" src="/logo.svg" alt="upbeatBytes" /></a>
|
||||
<a class="back" href="/play">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true"><path d="M19 12H5M11 6l-6 6 6 6" fill="none" stroke="currentColor" stroke-width="2.1" stroke-linecap="round" stroke-linejoin="round"/></svg>Play
|
||||
</a>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Upbeat Bytes",
|
||||
"short_name": "Upbeat Bytes",
|
||||
"name": "upbeatBytes",
|
||||
"short_name": "upbeatBytes",
|
||||
"description": "A calmer, brighter corner of the internet: good news, daily art, small games, and little resets.",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
|
||||
Reference in New Issue
Block a user