PageScene's top-right preview card now first-classes video alongside
images.
- **New query params**: `?image=<media_token>` and
`?video=<media_token>`. `?image=` is an exact alias for the existing
`?output=` (and `?demo=`), which keep working for legacy/shared links.
- **Toggle when both are set**: a small sliding pill in the card header
switches between the video and image side. Video shows first. The whole
pill is one click target - tap anywhere on it to flip.
- **Video gets native controls**: `<video autoplay muted loop
playsInline controls>`. Wrapper click-to-expand suppresses clicks that
land on the control bar so play/pause doesn't fullscreen the card.
- **Prompt caption follows the active side**: the line under the preview
shows whichever asset (video or image) is currently displayed.
- **Promptbox 3D auto-prefill still uses the image's prompt** only.
Video-only links skip prefill.
- Internal URL builders (splash modal `pickExample`, "See other demo
scenes" overlay) now produce `?image=` URLs. External links with
`?output=` continue to resolve via the parser fallback.
Add an `aboveStackSlot` prop to PromptBox3D rendered as the first
child of its `bottom-4 flex-col` stack, and thread a
`promptboxAboveStackSlot` prop through Stage3D / Stage3DBody. The lib
now owns the vertical math, so the webapp's button never overlaps the
prompt input regardless of textarea height — replaces the host-side
ResizeObserver/MutationObserver positioning that was unreliable in
production builds.
…s scenes
Adds an inline overlay above the promptbox in /edit-3d (visible only
when `?output=` is in the URL) for swapping to another curated example
scene. The grid reuses SceneSplashCard + EXAMPLE_SCENES and filters out
the current scene. Position tracks the promptbox stack via Resize- and
MutationObserver so the pill sits 12px above it at any height.
Also resets the lib's camera Zustand state (cameras, selectedCameraId,
focalLengthDragging) on every sceneToken change. save_manager.load-
FromJson only emits CamerasReplacedEvent when scene_json carries a
`cameras` field, so navigating from a scene whose JSON had cameras (e.g.
60mm) into one that omits them left the prior cameras array in the store
and the per-frame tick kept applying its FOV to the new viewport.
OnboardingHelper: nudge the WASD/Look chip up to bottom-72 and drop its
background tint so it stacks cleanly above the new pill.
feature: add high-res image preview modal to prompt box
- Added click-to-preview functionality for reference and end frame
images in `ImagePromptRow`.
- Updated `RefImage` interface to include `fullUrl` for fetching
high-resolution library images.
- Populated `fullUrl` for library selections in `create-image` and
`create-video` pages.
- Configured the preview modal to tightly wrap the image so the close
button anchors correctly to the corner.
- Updated the image uploading indicator to use the standardized
`spinner-third` icon.
- Adds a new **Referrals** page in both the marketing site and the
webapp, gated by the new `referrals` feature flag
- Users can share two kinds of invite links:
- Their username link (`?u={username}`) - works out of the box
- Up to 5 custom codes (`?r={code}`) they can create and delete
themselves
- Site: link lives in the profile dropdown (desktop + mobile)
- Webapp: link lives in the sidebar under a new "Invite" section
- Users without the flag see nothing - no menu entry, and direct visits
redirect home
- added make video button to the create image page gallery card action
button row and the lightbox modal
- clicking it will redirect to the create video page and insert the
image as a reference automatically
- Lightbox now shows full media metadata: Aspect Ratio, Resolution,
Size, Duration, Audio, and Created (with timestamp).
- Added Author header at the top so the close button no longer overlaps
the Prompt copy button.
- Extracted aspect ratio / resolution / duration formatters into
`@storyteller/common` so the website and desktop app share them.
Customers occasionally saw "0 Credits" with no signal that the fetch had
failed silently. Add a status badge on the coin (slow/failed/ recovered,
hidden in the happy path), a 60s background refresh, and gate the
initial fetch on AUTH_STATUS.LOGGED_IN to remove the 1s setTimeout
band-aid that was racing intermediate auth states.
Only the submit button triggers generation by default. The "Enter to
generate" toggle (available in both app and website settings top right
nav) still allows opting into Enter-to-submit.