Skip to content

feat(brand): live wallpaper page - #136

Merged
wavekat-eason merged 5 commits into
mainfrom
feat/brand-wallpaper
Jul 26, 2026
Merged

feat(brand): live wallpaper page#136
wavekat-eason merged 5 commits into
mainfrom
feat/brand-wallpaper

Conversation

@wavekat-eason

@wavekat-eason wavekat-eason commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Adds /brand/wallpaper/ — a chrome-free, animated WaveKat wordmark on a flowing waveform field. Leave it fullscreen on a spare monitor, point a screen recorder / OBS browser source at it, or export it as a PNG and set it as your desktop background.

What's on the page

Aspect presets do two jobs: they letterbox the stage (not the window), so a capture crop can be framed to a real target while you work in a normal browser window — and they're the pixel size the PNG export writes. Fit screen, 16:9, 34-inch (3440 × 1440), 16:10, MacBook, Square, Vertical. Fit screen exports at the display's real resolution including devicePixelRatio, which is why there's no separate 4K chip: on a 4K monitor it already gives you 3840 × 2160, and every fixed preset is a distinct aspect rather than the same shape at another scale. The crop boundary shows a hairline only while the controls are up, so it can never land in a recording.

Motion. Unattended, the field carries itself: seven wave layers with mixed wavelengths that never re-align, each breathing on its own slow cycle, plus a highlight band swept across the wordmark's own silhouette (the SVG used as an alpha mask, so it follows the letters rather than a rectangle).

Cursor reactivity, deliberately restrained — the field should acknowledge the pointer, not reorganise around it: waves swell and brighten around the cursor, the wordmark leans toward it, and a click sends a ripple out through every layer. The influence decays to nothing ~1.8s after the last move, easing out slower than it eases in — a wallpaper is mostly left alone, and a bright blob frozen wherever the mouse was parked would sit in every recording. Pausing motion clears it outright rather than freezing it.

Optional clock, off by default: a 24h HH:MM readout that lives inside .mark, so it floats and leans with the wordmark as one lockup. Sized in container units like the wordmark, so the pair holds its proportions from 9:16 to 21:9. Not tied to the motion toggle — a clock isn't motion, and a stopped clock is worse than no clock.

PNG export, redrawn at the target resolution rather than scaled up from the on-screen canvas. The wave math lives in drawField(ctx, w, h, t, cursor), shared by the live canvas and the export, so the file is the same artwork rather than a lookalike that drifts as the on-screen version gets tuned. Three things are deliberately left out of the file: the cursor swell and in-flight ripples, the shimmer (a moving highlight, not a resting state), and the clock (a wallpaper frozen at 21:07 forever is a bug, not a feature).

Controls fade out after 3 idle seconds and return on pointer move. H pins them hidden (recording mode), F fullscreen, C clock, S save PNG, 17 presets. Preset, clock and motion persist in localStorage; the theme toggle uses the same key as the site header, so the choice carries back to the rest of the site.

Supporting changes

  • Base.astro takes a siteBackground prop so this page can skip the shared backdrop rather than animating two canvases at once.
  • The sitemap gains a filter that drops the page — it's noindex, and advertising a URL we then tell crawlers to ignore is a contradictory signal.
  • The footer's More column links it, English-only. The page isn't translated, so the link is offered where the reader is already reading English rather than pointing a localized footer at an English destination — which also keeps it from costing a ninth translation of a label for a brand extra. More is the right column; Tools is for product surfaces.

Notes

  • Deliberately noindex and English-only. It's an internal brand tool, not a marketing page: out of the sitemap, out of translatedRoutes, not in the nav.
  • SEO checklist applied by hand rather than via the claude-seo skills, since the page is deindexed and has no indexable copy: real title and description, one <h1> (screen-reader only — the page is pure artwork), noindex, excluded from the sitemap, no JSON-LD.
  • Motion off and prefers-reduced-motion both hold a still frame and disable cursor reactivity.

Testing

  • npm run build — 214 pages, clean
  • npm run check:links — no broken or leaking internal links
  • Rendered in headless Chrome across presets and both themes
  • Cursor effects verified by driving synthetic pointer events into the built page
  • Export verified by intercepting the blob and reading it back: 3440 × 1440 dark and 1080 × 1080 light both produced correct pixel dimensions and composition, with the clock and cursor swell absent as intended

🤖 Generated with Claude Code

https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD

wavekat-eason and others added 2 commits July 26, 2026 20:55
Adds /brand/wallpaper/ — a chrome-free, animated WaveKat wordmark on a
flowing waveform field, for leaving fullscreen on a spare monitor or
pointing a screen recorder / OBS browser source at.

- Aspect presets letterbox the stage (not the window), so a capture crop
  can be framed to a real target: 16:9, 34-inch 3440x1440, 16:10,
  MacBook, square, vertical. Each preset is a distinct aspect — a 4K chip
  would letterbox identically to the 1080p one.
- Cursor reactivity, kept restrained: waves swell and brighten around the
  pointer, the wordmark leans toward it, and a click sends a ripple out
  through every layer. The influence decays to nothing ~1.8s after the
  last move, so an unattended page never holds a bright spot where the
  mouse was parked.
- Controls fade out after 3 idle seconds and return on pointer move.
  H pins them hidden, F toggles fullscreen, 1-7 pick a preset. Preset and
  motion persist; the theme toggle shares the site header's key.
- Motion off and prefers-reduced-motion both hold a still frame and
  disable cursor reactivity.

Supporting changes:
- Base.astro takes a `siteBackground` prop so the page can skip the
  shared backdrop rather than animating two canvases at once.
- The sitemap filter drops the page: it is noindex, and advertising a URL
  we then tell crawlers to ignore is a contradictory signal.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD
One line at the end of "What we build", framed as what it is rather than
as a product. English only for now — the wallpaper page itself is
English-only, so a localized About page would be sending readers to an
English destination; the eight localized About pages are unchanged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD
@github-actions

Copy link
Copy Markdown
Contributor

wavekat-eason and others added 3 commits July 26, 2026 21:07
A 24h HH:MM readout under the wordmark, off by default. Toggled from the
control panel or with C, and persisted alongside the preset.

- Lives inside .mark, so it floats and leans with the wordmark as one
  lockup rather than drifting against it. Positioned at top:100%, so it
  never affects .mark's own box.
- Sized in container units like the wordmark, so the pair holds its
  proportions from a 9:16 phone shape to a 21:9 ultrawide. With the clock
  showing, the lockup is lifted so it stays optically centred.
- Set in JetBrains Mono and muted rather than full-strength: the mark is
  the subject, the clock is a readout.
- Not tied to the motion toggle — a clock isn't motion, and a stopped
  clock on a wallpaper is worse than no clock. The tick is polled once a
  second and only writes to the DOM on the minute, so it recovers on its
  own from sleep, a timezone change, or the system clock being set.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD
Swaps the About-page prose mention for a link in the footer's More
column, so it's reachable from any English page rather than only from
About. about.astro returns to its previous state byte for byte.

English-only, deliberately: the wallpaper page isn't translated, so the
link is offered where the reader is already reading English rather than
pointing a localized footer at an English destination — which also keeps
it from costing a ninth translation of a label for a brand extra. More is
the right column for it; Tools is for product surfaces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD
Adds a download button (and S) that writes the current wallpaper to a PNG
at the selected preset's real pixel size, so it can be saved and set as a
desktop background.

- Redrawn at the target resolution rather than scaled up from the
  on-screen canvas, so a 3440x1440 wallpaper is genuinely 3440x1440 and
  stays sharp on the display it's meant for. The stage's CSS radial
  ground and the field's edge mask are reproduced on the canvas.
- Presets now carry pixel dimensions, not just an aspect, and drive both
  the on-screen letterbox and the export size. Fit screen exports at the
  display's real resolution including devicePixelRatio — which is also
  why there's still no 4K chip: on a 4K monitor Fit screen already gives
  3840x2160.
- The wave math moved into drawField(ctx, w, h, t, cursor), shared by the
  live canvas and the export, so the file is the same artwork rather than
  a lookalike that drifts as the on-screen version is tuned.

Three things are deliberately left out of the file: the cursor swell and
any in-flight ripples (a wallpaper shouldn't have a bright blob baked in
wherever the mouse was), the shimmer (a moving highlight, not a resting
state), and the clock (a desktop wallpaper frozen at 21:07 forever is a
bug, not a feature).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EwxQJL43iApJRb4NS5p6vD
@wavekat-eason
wavekat-eason merged commit 4aafecf into main Jul 26, 2026
2 checks passed
@wavekat-eason
wavekat-eason deleted the feat/brand-wallpaper branch July 26, 2026 09:31
wavekat-eason pushed a commit that referenced this pull request Jul 26, 2026
🤖 I have created a release *beep* *boop*
---


##
[0.0.50](wavekat-com-v0.0.49...wavekat-com-v0.0.50)
(2026-07-26)


### Features

* **brand:** live wallpaper page
([#136](#136))
([4aafecf](4aafecf))
* **home:** link hero carousel screenshots to their blog posts
([#139](#139))
([7271776](7271776))
* **home:** rotating hero screenshot carousel
([#137](#137))
([a673831](a673831))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant