Make the hero Moon image configurable (src/alt), backwards-compatible #20

Merged
whitlocktech merged 2 commits from feature/configurable-moon-image into main 2026-07-03 04:45:26 +00:00
Member

Closes #5.

Problem

The Hero Editor's Moon element — a dedicated, first-class element core to the project's identity — always rendered a hardcoded image at /assets/img/hero-moon.png. Only size and glow were configurable; the image itself could not be changed.

Solution

Make only the Moon's image source configurable, without changing anything else about the element. The Moon remains its own element type (not replaced with a generic image element, not merged into another type). Adds optional src and alt props alongside the existing size/glow:

{ "type": "moon", "props": { "src": "/uploads/moons/bloodmoon.png", "size": 120, "glow": 0.65, "alt": "Blood Moon" } }

Implementation details

Two files, no unrelated changes:

  • client/src/components/HeroElement.jsx — the moon render case now uses props.src when present and falls back to the default /assets/img/hero-moon.png when absent. alt comes from props.alt (default '', same as the previous hardcoded value). The size/glow/animation styling is byte-for-byte unchanged.
  • client/src/routes/admin/views/HeroEditor.jsx (MoonPanel) — adds an image upload control, an alt text field, and a "Use default" reset, while keeping the size/glow sliders exactly as before. The upload reuses the existing shared admin upload workflow (api.admin.upload, the same call the Image and Background panels use) — no second upload path, no duplicated upload logic. A successful upload simply sets props.src; "Use default" clears it back to the fallback.

No new element type, no newElement change (a fresh Moon starts with no src and renders the default until an image is chosen).

Backwards compatibility

Fully preserved, zero migration:

  • Old layouts that have only size/glow and no src hit the fallback and render exactly as today.
  • alt defaults to '' — identical to the previous hardcoded alt="".
  • No DB, API, or hero-JSON schema changes. Existing hero_layout / hero_layout_draft values are read and written unchanged.

Testing

  • npm run build (client) succeeds.
  • Live browser verification against the running app: published a temporary layout containing two Moon elements and inspected the rendered DOM:
    • Moon with no src<img src="/assets/img/hero-moon.png" alt=""> (fallback, unchanged behavior).
    • Moon with src<img src="/assets/img/uomysticmoon-main-hero.png" alt="Custom Moon"> (chosen image).
    • Both had an identical glow drop-shadow and width, confirming size/glow/animation are unchanged. Original hero settings were restored afterward.
  • Editor: MoonPanel reuses the already-proven api.admin.upload path (same as the Image/Background panels); the build confirms the JSX compiles.

Acceptance criteria

  • Old layouts (no src) render identically to current behavior, no migration
  • New layouts with src render the chosen image
  • Moon image is editable from the Hero Editor via the existing upload system
  • Glow, size, animation behavior unchanged
  • No DB or API changes

Follow-up: upload warning threshold

The editor showed a soft "over 1 MB may slow the page" confirm before uploads — a client-side nudge only (the server hard-limits at 8 MB), and 1 MB nagged on normal hero images. Raised to 5 MB and consolidated the threshold + message into a single tooLargeToUpload() helper shared by the background, moon, and image upload paths.

Closes #5. ## Problem The Hero Editor's **Moon** element — a dedicated, first-class element core to the project's identity — always rendered a hardcoded image at `/assets/img/hero-moon.png`. Only `size` and `glow` were configurable; the image itself could not be changed. ## Solution Make **only the Moon's image source** configurable, without changing anything else about the element. The Moon remains its own element type (not replaced with a generic image element, not merged into another type). Adds optional `src` and `alt` props alongside the existing `size`/`glow`: ```json { "type": "moon", "props": { "src": "/uploads/moons/bloodmoon.png", "size": 120, "glow": 0.65, "alt": "Blood Moon" } } ``` ## Implementation details Two files, no unrelated changes: - **`client/src/components/HeroElement.jsx`** — the `moon` render case now uses `props.src` when present and falls back to the default `/assets/img/hero-moon.png` when absent. `alt` comes from `props.alt` (default `''`, same as the previous hardcoded value). The size/glow/animation styling is byte-for-byte unchanged. - **`client/src/routes/admin/views/HeroEditor.jsx` (`MoonPanel`)** — adds an image **upload** control, an **alt text** field, and a **"Use default"** reset, while keeping the size/glow sliders exactly as before. The upload **reuses the existing shared admin upload workflow** (`api.admin.upload`, the same call the Image and Background panels use) — no second upload path, no duplicated upload logic. A successful upload simply sets `props.src`; "Use default" clears it back to the fallback. No new element type, no `newElement` change (a fresh Moon starts with no `src` and renders the default until an image is chosen). ## Backwards compatibility Fully preserved, zero migration: - Old layouts that have only `size`/`glow` and **no `src`** hit the fallback and render **exactly as today**. - `alt` defaults to `''` — identical to the previous hardcoded `alt=""`. - **No DB, API, or hero-JSON schema changes.** Existing `hero_layout` / `hero_layout_draft` values are read and written unchanged. ## Testing - `npm run build` (client) succeeds. - Live browser verification against the running app: published a temporary layout containing two Moon elements and inspected the rendered DOM: - Moon with **no `src`** → `<img src="/assets/img/hero-moon.png" alt="">` (fallback, unchanged behavior). - Moon with **`src`** → `<img src="/assets/img/uomysticmoon-main-hero.png" alt="Custom Moon">` (chosen image). - Both had an **identical** glow drop-shadow and width, confirming size/glow/animation are unchanged. Original hero settings were restored afterward. - Editor: `MoonPanel` reuses the already-proven `api.admin.upload` path (same as the Image/Background panels); the build confirms the JSX compiles. ## Acceptance criteria - [x] Old layouts (no `src`) render identically to current behavior, no migration - [x] New layouts with `src` render the chosen image - [x] Moon image is editable from the Hero Editor via the existing upload system - [x] Glow, size, animation behavior unchanged - [x] No DB or API changes --- ## Follow-up: upload warning threshold The editor showed a soft "over 1 MB may slow the page" confirm before uploads — a client-side nudge only (the server hard-limits at 8 MB), and 1 MB nagged on normal hero images. Raised to **5 MB** and consolidated the threshold + message into a single `tooLargeToUpload()` helper shared by the background, moon, and image upload paths.
wtclaude added 1 commit 2026-07-03 04:38:35 +00:00
The Moon stays a dedicated, first-class hero element — only its image
source becomes configurable. Adds optional src/alt props alongside the
existing size/glow.

- HeroElement: the moon renders props.src when present, else falls back to
  the default /assets/img/hero-moon.png. Size, glow, and animation are
  unchanged. alt is now props.alt (default '', same as before).
- HeroEditor MoonPanel: adds an image upload (reusing the existing shared
  api.admin.upload workflow, same as the image/background panels) that sets
  props.src, an alt-text field, and a "Use default" reset. Size/glow
  controls unchanged.

Fully backwards compatible: existing layouts with only size/glow and no
src render exactly as today via the fallback. No DB, API, or hero-JSON
changes; no migration.
wtclaude added 1 commit 2026-07-03 04:42:30 +00:00
The "may slow the page" prompt is only a client-side nudge — the server
hard-limits uploads at 8 MB. 1 MB was arbitrarily low and nagged on
perfectly normal hero images. Bump to 5 MB (still well under the hard cap)
and pull the threshold + message into a single tooLargeToUpload() helper so
the background, moon, and image upload paths stay in sync.
whitlocktech approved these changes 2026-07-03 04:43:29 +00:00
whitlocktech closed this pull request 2026-07-03 04:44:33 +00:00
whitlocktech reopened this pull request 2026-07-03 04:45:13 +00:00
whitlocktech merged commit f305019c54 into main 2026-07-03 04:45:26 +00:00
Sign in to join this conversation.
No description provided.