This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Pexels Dynamic Wallpaper — a static web app (hosted on GitHub Pages at docs/) that displays a rotating slideshow of Pexels collection photos. Powers three frontends from a single codebase: Plash (macOS), Lively (Windows), and a Samsung Smart TV app built with Tizen Studio (docs/config.xml). A Node script fetches photo URLs from the Pexels API and writes them to a local text/JSON file used as the fallback source.
npm test # Run Jest tests (uses --experimental-vm-modules for ESM)npm run lint # Run all linters (ESLint + Prettier)
npm run lint:js # ESLint only on docs/js/**/*.{js,mjs}
npm run format:js # Prettier check on docs/js/**/*.{js,mjs}npm run fetch # node fetch_pexels_urls.mjs
node --env-file=.env fetch_pexels_urls.mjs # load .env automatically (Node 20.6+)Requires PEXELS_API_KEY in .env (copy from .env.example) or as an environment variable. Zero npm dependencies — uses built-in fetch and AbortController.
Static site served by GitHub Pages. All JS uses native ES modules (.mjs).
main.mjs— App entry point. Handles DOM setup, settings form show/hide, slideshow lifecycle (start/stop/pause/resume), URL parameter parsing, and collection ID extraction from Pexels URLs. ExportsextractCollectionIdFromUrl.slideshow.mjs— Pexels API fetching (paginated with 30s timeout), local fallback file loading, photo entry building with attribution links, and the sharedextractPexelsIdutility. Pure data-fetching logic separated from DOM.storage.mjs— localStorage wrapper with in-memory fallback. Handles API key/collection persistence, URL cache with TTL (CACHE_DURATION_MS = 24h), and address bar sanitization (strips sensitive query params viahistory.replaceState).config.mjs— All constants: API URLs, storage keys, timing, sensitive param list.i18n.mjs— Loadstranslations.jsonat runtime; falls back to hardcoded English. Language auto-detected from browser.status.mjs— Status overlay management (show/hide with auto-dismiss timers,aria-live="assertive"for errors).
- On load: check URL params → check localStorage → if no API key, start default slideshow from
pexels_photo_urls.txt - With API key: fetch from Pexels API → cache in localStorage (24h TTL) → shuffle → rotate every 5 min
- Settings stored in localStorage (not cookies) to avoid sending keys to server
- Settings dialog is hidden by default; only shown when user clicks the settings button
Standalone Node ESM script (zero deps) that fetches all photos from a hardcoded Pexels collection (COLLECTION_ID = "vmnecek") with retry logic and rate limit (429) handling, writes URLs to docs/pexels_photo_urls.txt and metadata to docs/pexels_photo_data.json. Runs daily via GitHub Actions (.github/workflows/update_photos.yml).
docs/config.xmlis the Tizen widget manifest. CSP allowsconnect-src 'self' https://geert.github.iofor the JSON fetch andimg-src https://images.pexels.comfor photos. Noscript-srcother than'self'— Samsung Store rejects remote JS.docs/.tzpkgignorelists files that don't need to be in the.wgt. The Tizen CLI does not currently honor it; the GUI does (Project Properties → Tizen Studio → Package).- Tizen detection:
isTizenTV()checkstypeof tizen !== 'undefined' && typeof tizen.power !== 'undefined'. When true: settings UI is hidden, URL params are ignored,loadDefaults()is called withREMOTE_PHOTO_DATA_URLinstead of the relative path. - D-pad remote keys (arrow keys / OK / Play / Back) are wired unconditionally in
attachEventListeners— they're no-ops outside Tizen unless the host (Plash interactive, browser) forwards keyboard events. - Package id (fixed in
config.xml):PxlWallppr.TizenWallpaper.
End-to-end build + install instructions, including the Jellyfin2Samsung sideload variant and troubleshooting, live in docs/DEPLOY-TIZEN.md. The short version: cd docs && tizen package -t wgt -s <profile> -- . then sdb connect <tv-ip> and tizen install -n "Pexel Wallpaper.wgt" -t <device>. The TV must have Developer Mode on with its Host PC IP pointing at the deploying machine — a mismatch presents as sdb connect failing even though TCP port 26101 is open.
Jest with jsdom. Tests import directly from the ESM modules. jest.setup.js provides fetch, TextEncoder, and matchMedia mocks.
- JavaScript: ESLint (recommended + prettier config), Prettier (single quotes, 100 char width, ES5 trailing commas). Browser ES2022, ESM modules. Unused vars prefixed with
_are allowed. - Tests are excluded from ESLint (
ignorePatterns: ['__tests__/**']).
- The app detects its environment (Plash, Lively, browser) via user-agent sniffing and adjusts setup instructions accordingly.
node_modulesand local Node binaries are gitignored via thenode*pattern in.gitignore.- CSS includes dark mode support via
prefers-color-scheme: darkfor the settings form.