Architecture

WallCab separates the public website and renderer from a deliberately narrow cache service. The Next.js application remains useful when the cache or every upstream provider is unavailable.

Apple Shortcut / browser
          |
          v
  Next.js wallpaper route
     |             |
 cache lookup    daily resolver
     |             |
     |      active-day KV lesson
     |        |           |
     |     provider    fallback
     |             |
     +--------> Sharp renderer
                    |
              PNG response now
                    |
          shared-image KV upload

Deterministic daily content

The normalized interest set and UTC date select one category for the day. The order is random-looking but deterministic, and complete cycles give every selected interest a turn. Vocabulary uses rotating advanced semantic prompts plus Datamuse frequency and syllable metadata to discover an uncommon term; Free Dictionary then enriches its definition and pronunciation. The other categories rotate through advanced, category-specific Wikimedia searches before selecting a concept and page summary. Themes and device sizes never alter the day’s lesson.

Every provider candidate passes structural and editorial validation independently. One malformed search result cannot reject an otherwise usable provider response. WallCab rejects excessive text, unsafe titles, missing source links, overly common vocabulary, absent pronunciation, duplicates, and content that cannot fit the composition. The reviewed advanced fallback record for that date and category is used as a complete unit when validation fails.

The accepted lesson and its provenance are stored in Workers KV until the next UTC rollover. This keeps provider traffic bounded to one resolution per category per day and makes external versus fallback observable through response headers, the preview, and the status APIs.

Background pipeline

The five photography themes use Openverse searches restricted to CC0 and public-domain images with mature content disabled. The server validates the returned source host, redirect destination, content type, byte length, image dimensions, and attribution. Those photography backgrounds change at the UTC rollover.

Six WallCab Original themes use bundled SVG artwork: AMOLED, Minimal, Abstract, Gradient, Black & White, and Grid. Their artwork remains fixed while the lesson changes each day. When no eligible remote photograph is available, the selected photography theme uses a bundled procedural SVG fallback. This keeps rendering functional without making an unverifiable license claim.

An optional custom image replaces only the background layer. The browser first resizes it to stay below the Vercel request limit. After Turnstile verification, the server validates the decoded format and dimensions, removes metadata, applies orientation, and creates a 1320×2868 WebP. Raw custom images live in a private Workers KV binding; there is no public object URL. If the opaque ID is missing or expired, rendering continues with the URL's selected built-in theme.

Image composition

The Node.js renderer uses Sharp with an SVG overlay:

  • the clock and Dynamic Island zone remains quiet;
  • the lesson occupies the middle and lower fields;
  • vocabulary terms include a bounded IPA pronunciation line;
  • titles, definitions, quotations, and optional personal notes have separate hard line and block bounds;
  • a contrast gradient protects readability;
  • lesson and image credits are always visible;
  • adaptive indexed-palette compression targets 2.2 MiB.

The renderer version is part of the cache key. A composition change can therefore roll forward without colliding with an earlier file.

Cache boundary

The Cloudflare Worker exposes a signed public GET and HEAD endpoint. Private lookup and upload routes require a timestamped HMAC signature covering method, path, and body hash. KV records expire at the next UTC rollover.

On a hit, the Next.js route returns a temporary 307 to the signed Worker URL. On a miss, Next.js sends the newly rendered image immediately and schedules the cache upload after the response. If the Worker is unavailable, image generation still succeeds. Active-day lesson and background records reduce repeated upstream requests even when a complete rollover manifest is unavailable.

Personalized requests are intentionally different. The optional note is validated to 80 characters and changes only the SVG text layer. Its raw value never appears in an internal cache key, and the completed personalized PNG bypasses the shared Worker image cache. Daily lesson and background inputs can still use their normal active-day caches.

Custom-object routes share the same timestamped HMAC boundary and expose private KV data only to the renderer. Separate KV metadata records creation time, a hash of the deletion token, and a daily-bounded last-use timestamp. A Worker cron removes items after 30 inactive days and cleans old orphaned keys. User deletion removes the source object, metadata, and matching active-day PNG variants.

Trust boundaries

Provider data, uploads, and personal notes are untrusted input. Remote image fetches use an explicit hostname allowlist, bounded redirects, media and size validation, timeouts, and Sharp decoding. Enumerated query values are validated before they reach the renderer; notes are bounded, control characters are rejected, and text is escaped before SVG composition. Turnstile tokens are verified server-side against the exact action and hostname. The Shortcut URL contains an unguessable custom ID and, when chosen, the personal note; the deletion token remains in browser storage and the fragment of a private deletion link. Users are warned not to put sensitive information in a URL-visible note.