Skip to content

Seasonal themes: a themed animation for every week of the year, plus All Things Open - #231

Open
darkmastermindz wants to merge 3 commits into
mainfrom
seasons
Open

darkmastermindz wants to merge 3 commits into
mainfrom
seasons

Conversation

@darkmastermindz

@darkmastermindz darkmastermindz commented Oct 20, 2026 •

Copy link
Copy Markdown
Owner

Summary

Every week of the year now has a theme:

  • Emoji: a few themed emoji drift down, or float up, over the background on every page.
  • Background: the topographic lines take the theme's two colours.

October is spooky: Hacktoberfest, the pumpkin patch, bats and spiders, then Halloween and Día de Muertos. Dated events take over while they run. All Things Open (Oct 19–21, 2026) shows laptops 💻, Linux penguins 🐧, Raleigh's acorns 🌰 (the City of Oaks), mics 🎤, stars ⭐ and open locks 🔓 in orange and cyan.

Everything lives in config.toml under [seasons], with 52 weekly themes plus events.

Related Issue

None. The user asked for it directly.

Changes Made

  • config.toml [seasons]:
    • enabled, and particles (12; phones show at most 8).
    • 52 [[seasons.week]] themes, one per week from Jan 1. Each has a name, up to 8 emoji, two colors, and a motion (fall or rise).
    • The All Things Open [[seasons.event]].
  • utils/seasons.mjs:
    • buildSeasonsConfig checks the config:
      • Emoji: no markup, quotes or words.
      • Colours: #rrggbb only.
      • Dates must be real days, and weeks must start on 01-01 and run in order.
      • A theme with any bad value is dropped and fails the build.
    • themeFor(config, day): an event running that day, or else that week's theme. Feb 29 goes with Feb 28's week.
    • particleLayout: a random position, size, speed, sway and spin for each emoji.
  • scripts/build-seasons.mjs: writes data/seasons.generated.mjs (git-ignored). It's wired into pretest and predev like the other config sections.
  • composables/useSeason.js: picks today's theme in the browser (Eastern time). It changes on its own with no redeploy, and the prerendered page has no theme, so it fits any day.
  • components/SeasonalParticles.vue (added to the default layout):
    • CSS animations only, and pointer-events: none.
    • Sits behind the content, over the topographic lines.
    • Hidden for reduced motion and data saving.
  • components/TopoBackground.vue: the gradient takes the theme's colours, or the usual purple-to-green when there's no theme.
  • Tests:
    • tests/app/seasons.test.mjs:
      • The real config builds.
      • Every day of 2026 and 2028 (a leap year) has a theme.
      • Oct 31 is Halloween with 🎃, and Oct 16 is Spooky.
      • All Things Open runs Oct 19–21, 2026 only.
      • New Year, Valentine's, St Patrick's, July 4th, Christmas and NYE land in their weeks.
      • The ordering rules hold, and the particle layout is right.
    • tests/security/seasons-config.test.mjs, with a HOSTILE_COLORS payload list:
      • Unknown and prototype keys are refused, including nested ones.
      • Hostile colours, emoji, names and dates are refused.
      • Names stay strings in the generated module.
  • README.md: a Seasonal themes section, plus the build list and background notes.
  • Merged main into this branch after Playwright: touch scrolling tests on every Android device (100 profiles) #238 (the Android touch tests). The repo's auto-rebase couldn't do it because both changed the package.json scripts. I kept main's test:android and this branch's build:seasons step in predev.

How to Test

  1. npm test (232 pass, after the merge with main) and npm run generate. The build log shows [build-seasons] 52 weekly themes, 1 event(s); today: All Things Open.
  2. Open any page: the emoji drift behind the content, and taps go through to the page.
  3. To see another season, change the system date, or set an event in config.toml for today.

I checked it in Playwright (Chromium) with a fake clock:

Date Device Emoji showing Topo colours
Oct 20, 2026 desktop 💻🐧🌰🎤⭐🔓 ×2 #f97316 → #22d3ee
Oct 31, 2026 Pixel 7 🎃👻🦇🍬💀🎃👻🦇 (8 on a phone) #f97316 → #a855f7
Dec 24, 2026 desktop 🎄🎁🎉✨ ×3 #facc15 → #ef4444
Oct 31, reduced motion desktop none #f97316 → #a855f7

Android touch tests (npm run test:android, from #238), on this branch with the All Things Open emoji showing:

  • Devices: Galaxy S9+, Pixel 7, Galaxy Tab S9 (landscape), Galaxy Z Fold 7 and Moto G4 (landscape).
  • Result: 94 passed, 11 skipped, 0 failed.
  • Scrolling, the sideways-scroll check, swipes on the coin, card, links and menu, and taps all work with the emoji drifting over the page.
  • The full 100-device run is in this PR's CI (the Android touch workflow).

Additional Notes

  • There's a hydration warning on dates after Oct 21. It isn't from this PR: main's build shows the same warning, because the event-only footer code and home page title are rendered at build time. The next deploy after the event clears it. A follow-up could move those to the browser like the themes.
  • The emoji are decorative (aria-hidden), at 55% opacity.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS

Every week of the year gets a theme from config.toml [seasons]: a few
themed emoji drift down (or float up) behind the content on every page,
and the topographic lines take the theme's two colours. October is
spooky, December has the winter holidays, and dated events take over
while they run (All Things Open, Oct 19-21 2026).

The theme is picked in the browser from today's date, so it changes with
no redeploy. CSS animations only, never in the way of a tap, and hidden
for reduced motion and data saving. The config is checked at build time
like the other sections (emoji, colours, names and dates), with tests.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS
Conflict in package.json scripts: kept main's test:android and this
branch's build:seasons step in predev.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Nginuw5wmUjUSkmQB1J3pS
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.

2 participants