feat: WAAPI easter eggs (themed, console-listed)#9
Merged
Conversation
Eleven themed easter eggs, all rendered via the Web Animations API
(no CSS animation libs). Each is built around PubID's domain:
publication identifiers, standards bodies, and the PubID data model.
Eggs:
- Konami code (↑↑↓↓←→←→BA) → Standards Lifecycle animation:
WD → CD → DIS → FDIS → Published, with sequenced stage morphs,
progress segments lighting up, confetti + page-shake finale.
Demonstrates Promise-based timelines and composite easing.
- Click logo × 7 → Logo decomposes into labeled PubID components
(Publisher / Type / Number / Year / Supplement) with SVG callout
lines drawn via animated stroke-dash.
- Type "ISO 9001" → Quality Certified stamp drops via spring easing
(cubic-bezier overshoot) with curved-text SVG path.
- Type "RFC 1149" → Carrier pigeon flies across with sinusoidal
vertical motion layered on the linear horizontal motion via
WAAPI composite:'add'. Drops a "PKT" datagram mid-flight.
- Type "802.11" → Concentric beacon pulses radiate from the
wordmark (5 staggered rings, each fading on expansion).
- Type "urn" → Identifier regex scans the page; each match sprouts
a URN chip via staggered fadeInUp.
- Type "errata" → Dictionary lookup strikes words with redline
strikethroughs; falls back to random words when no dictionary
match exists in a paragraph.
- World Standards Day (Oct 14) → Auto-badge in header + confetti.
- Console: pubid.spin(), .shake(), .confetti() — programmatic
access to the same primitives.
Console API:
- window.help and window.pubid.help() → styled ASCII directory
of every egg with triggers and descriptions.
- window.pubid.list() → egg metadata as data.
- window.pubid.fire(id) → trigger by id.
- window.pubid.{spin,shake,confetti}() → quick effects.
Architecture:
- src/scripts/easter-eggs/effects.ts WAAPI primitives (overlay,
toast, confetti, shake, spin, pulse-ring, dim-page, fade helpers).
All routed through a single pointer-events:none overlay.
- src/scripts/easter-eggs/eggs.ts Egg implementations and
registry.
- src/scripts/easter-eggs/index.ts Triggers (typing buffer,
Konami detector, click counter, temporal), console API install,
init(). Auto-initialises on import.
prefers-reduced-motion: flashy effects (confetti, shake) no-op.
All keyboard input is ignored when an input/textarea/contentEditable
is focused so the eggs never interfere with form entry.
Volume 2 of the easter-egg system. Adds 16 eggs and 6 console API
methods, bringing the total to 27. Each is themed around publication
identifiers, standards bodies, or the PubID data model.
New keyboard-triggered eggs:
- "ISO 8601" → dates on the page flip into strict ISO 8601 form
(YYYY-MM-DDTHH:mm:ss.sssZ) via rotateX card-flip
- "IEEE 754" → floating-point reality: numbers glitch into NaN,
Infinity, -0, 0.30000000000000004, 5e-324
- "RFC 2324" → HTCPCP teapot tips forward and pours tea, with
synthesised pour sound and rising steam
- "ISBN" → barcode scanner line sweeps the viewport with
synthesised beeps; generates a real ISBN-13 with
valid modulo-10 checksum
- "DOI" → resolution chain animation:
DOI → doi.org → handle → URL → content ✓
- "ISO 27001" → ISMS lockdown: green frame inset, padlock badge in
header, every link briefly glows green
- "W3C" → validator sweep: scan line top-to-bottom, every
element gets a green ✓ as the line passes, ending
with a "VALID PubID 1.0" stamp
New interaction eggs:
- Mouse trail (toggle) — pubid.trail() leaves identifier fragments
that follow the cursor and fade out
- Idle fragments — after 45s of no input, identifier fragments drift
upward from the bottom of the page
- Tea time — at 15:30–17:00 local, a ☕ badge appears in the header;
clicking it fires the HTCPCP teapot egg
New console API:
- pubid.joke() — random standards-themed joke
- pubid.fact() — random PubID / standards-world fact
- pubid.ascii() — ASCII-art wordmark in the console
- pubid.cow(msg) — cowsay with optional message
- pubid.parse(id) — parse an identifier into components and URN
- pubid.uuid() — generate a UUID
New WAAPI primitives in effects.ts:
- beep() — Web Audio synth (sine/square/triangle, no files)
- scanLine() — directional sweep with optional progress callback
- ripple() — single expanding ring
- flipText() — rotateX midpoint-swap text morph
- floatingFragment() — drift a fragment upward with horizontal noise
- lockdownFrame() — animated inset box-shadow
- glow() — momentary border glow on any element
Architecture:
- New file src/scripts/easter-eggs/eggs-extra.ts holds the v2 eggs and
shared helpers (cowsay, parseIdentifier, ascii art, jokes, facts).
- index.ts merges EGGS + EGGS_EXTRA into ALL_EGGS, extends the typing
pattern table, wires idle/trail/tea-time handlers, and exposes the
new console methods.
Type "NIST" (case-insensitive) triggers a synchronisation sequence: a scan line sweeps the viewport with synthesised tick beeps, then a live UTC clock pins to the corner showing ISO 8601 timestamp with "stratum 1 · ±0.001s" status, ticking at ~12 Hz for 6.5 seconds. Themed after NIST's Internet Time Service (time.nist.gov), which distributes UTC to systems worldwide via NTP. All keyboard-triggered eggs are case-insensitive (already were — the typing buffer uppercases both sides before comparison). Verified with "iso 9001", "Iso 9001", "ISO 9001", "nist", "NiSt", "NIST". Total eggs: 28 (was 27).
The previous ISO 8601 egg showed "No dates found on this page" on
pages without date-like strings — a dead-end that broke the
"easter eggs should always delight" contract.
New behaviour: the egg ALWAYS pins a live ISO 8601 reference clock to
the corner showing seven representations updating in real time:
ISO 8601:2019
Date and time — Representations for information interchange
2026-07-23T06:22:18.459Z (extended, UTC, milliseconds)
DATE 2026-07-23
TIME 06:22:18Z
BASIC 20260723T062218Z (no separators)
WEEK 2026-W30-4 (ISO 8601 week date)
DOY 204/365 (day-of-year / total)
LOCAL 2026-07-23T14:22:18+08:00 (corrected: now uses local wall
time with the proper offset,
not UTC + offset)
When the page does have dates, those still flip into ISO 8601 in
place — the reference clock is the guaranteed payoff; the flips are
bonus.
Bug fix along the way: the LOCAL line previously rendered UTC wall
time with the local offset (e.g. "06:22:18+08:00"), which is
nonsensical. Now renders actual local wall time with the offset.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Update: +16 more eggs
Volume 2 adds 16 new eggs and 6 new console methods, bringing the total to 27 eggs.
New keyboard-triggered eggs
ISO 8601IEEE 754NaN,Infinity,-0,0.30000000000000004,5e-324RFC 2324ISBNDOIISO 27001W3CNew interaction eggs
pubid.trail()) — toggleable identifier fragments that follow the cursor and fadeNew console API
pubid.joke()— random standards jokepubid.fact()— random PubID / standards-world factpubid.ascii()— ASCII-art wordmarkpubid.cow(msg?)— cowsaypubid.parse(id)— parse an identifier into components + URNpubid.uuid()— generate a UUIDNew WAAPI primitives
beep()(Web Audio synth, no audio files),scanLine()with progress callback,ripple(),flipText()(rotateX midpoint swap),floatingFragment(),lockdownFrame(),glow().Verified
npm run check— 0 errorsnpm run build— 309 pagesnpm test— 374/374 passingpubid.list().length === 27