feat: add about page, sitemap, social links component, Apple sign-in

prompt on win screen, and layout/theme improvements

  ## New features

  - **About page** (`src/routes/about/`): New static about page rendered
    from `static/about.md` using the `marked` library (added as a
    dependency). Includes the project backstory content.

  - **XML sitemap** (`src/routes/sitemap.xml/`): Dynamic sitemap
    endpoint for SEO, registered in `static/robots.txt` via `Sitemap:`
    directive.

  - **Apple Sign In prompt on win screen** (`WinScreen.svelte`): When
    the game is won and the user is not logged in, a "Sign in to save
    your streak & see your stats" prompt with an Apple Sign In button is
    shown below the share card. Passes `anonymousId` so stats migrate on
    sign-up. Driven by new `isLoggedIn` and `anonymousId` props, passed
    from `+page.svelte`.

  ## Refactoring

  - **`SocialLinks` component**
    (`src/lib/components/SocialLinks.svelte`): Extracted the Bluesky,
    Twitter/X, and email social link icons from `Credits.svelte` into a
    reusable component. `Credits.svelte` now imports and renders
    `<SocialLinks />`.

  - **`ThemeToggle` component**
    (`src/lib/components/ThemeToggle.svelte`): New component for
    toggling light/dark mode, persisted to `localStorage`. Currently
    rendered but hidden (`hidden` class) in `+page.svelte` —
    infrastructure is in place for future use.

  ## Layout changes

  - **`+layout.svelte`**: Moved the page title/header (`<h1>` with
    `TitleAnimation`) and the gradient background wrapper from
    `+page.svelte` into the root layout, so it applies across all
    routes. Also removed the `browser` guard around the analytics script
    injection (it's
    already inside `onMount` which is client-only). Added `<meta
    name="description">`.

  - **`+page.svelte`**: Removed the title/header and gradient wrapper
    (now in layout). Minor formatting cleanup (reformatted `SearchInput`
    props, moved `currentDate` derived state earlier). `ThemeToggle`
    import swapped in place of `TitleAnimation` (which moved to layout).

  ## Styling

  - **`layout.css`**: Added `@custom-variant dark` for class-based dark
    mode toggling (supports `.dark` class on `<html>`). Added explicit
    `html.dark` / `html.light` rules alongside the existing
    `prefers-color-scheme` media query, so the `ThemeToggle` component
    can
    override the system preference. Added background transition
    animation.
This commit is contained in:
George Powell
2026-03-12 18:22:59 -04:00
parent 3de55ba216
commit 884bbe65c7
16 changed files with 444 additions and 94 deletions
+89
View File
@@ -39,6 +39,8 @@
verseText,
streak = 0,
streakPercentile = null,
isLoggedIn = false,
anonymousId = '',
}: {
statsData: StatsData | null;
correctBookId: string;
@@ -53,6 +55,8 @@
verseText: string;
streak?: number;
streakPercentile?: number | null;
isLoggedIn?: boolean;
anonymousId?: string;
} = $props();
let bookName = $derived(getBookById(correctBookId)?.name ?? "");
@@ -319,6 +323,24 @@
</button>
</div>
{/if}
{#if !isLoggedIn}
<div class="signin-prompt">
<p class="signin-text">Sign in to save your streak &amp; see your stats</p>
<form method="POST" action="/auth/apple">
<input type="hidden" name="anonymousId" value={anonymousId} />
<button
type="submit"
class="apple-signin-btn"
>
<svg class="apple-icon" viewBox="0 0 24 24" fill="currentColor">
<path d="M17.05 20.28c-.98.95-2.05.88-3.08.4-1.09-.5-2.08-.48-3.24 0-1.44.62-2.2.44-3.06-.4C2.79 15.25 3.51 7.59 9.05 7.31c1.35.07 2.29.74 3.08.8 1.18-.24 2.31-.93 3.57-.84 1.51.12 2.65.72 3.4 1.8-3.12 1.87-2.38 5.98.48 7.13-.57 1.5-1.31 2.99-2.54 4.09zM12.03 7.25c-.15-2.23 1.66-4.07 3.74-4.25.29 2.58-2.34 4.5-3.74 4.25z"/>
</svg>
Sign in with Apple
</button>
</form>
</div>
{/if}
</div>
<style>
@@ -598,4 +620,71 @@
.snippet-toggle.on .toggle-thumb {
transform: translateX(16px);
}
/* ── Apple Sign In prompt ── */
.signin-prompt {
display: flex;
flex-direction: column;
align-items: center;
gap: 0.75rem;
padding: 1rem 0 0.25rem;
}
.signin-text {
font-size: 0.85rem;
color: #555;
text-align: center;
font-weight: 500;
}
@media (prefers-color-scheme: dark) {
.signin-text {
color: #aaa;
}
}
.apple-signin-btn {
display: flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.6rem 1.5rem;
background: #000;
color: #fff;
border-radius: 0.5rem;
font-size: 0.95rem;
font-weight: 600;
border: none;
cursor: pointer;
transition: background 150ms ease, transform 80ms ease;
}
.apple-signin-btn:hover {
background: #222;
transform: translateY(-1px);
}
.apple-signin-btn:active {
background: #111;
transform: scale(0.98);
}
@media (prefers-color-scheme: dark) {
.apple-signin-btn {
background: #fff;
color: #000;
}
.apple-signin-btn:hover {
background: #e5e5e5;
}
.apple-signin-btn:active {
background: #ccc;
}
}
.apple-icon {
width: 1.1rem;
height: 1.1rem;
flex-shrink: 0;
}
</style>