Skip to content

UI Inventory Page

OneSeventyFour edited this page May 14, 2026 · 1 revision

UI: Inventory page

Where you manage your pyro stock — every cake, shell, fountain, fuse, and shell pack. Anything that can show up on a timeline starts here as an inventory row.

📷 Screenshot placeholder: the Inventory list with several types of items, search bar at top, edit form on the right.

Layout

Two-column:

  • Left — searchable, filterable list of inventory items.
  • Right — editor for the selected item (or "new item" form).

Item types

The type field is a free-form string, but the UI's create/edit forms understand a fixed set:

Type What it is Notable fields
SHELL Single aerial shell. duration, lift_delay, color.
CAKE_FOUNTAIN Ground fountain. duration. Often has a YouTube link for shot-timing analysis.
CAKE_200G 200-gram cake (multiple aerial shots from one tube assembly). duration, metadata.shells[] for individual shot info.
CAKE_500G 500-gram cake. Same.
FUSE Fuse cord (reference inventory used by racks). burn_rate (seconds per foot).
SHELL_PACK Pack of multiple shells of the same type. metadata.shells[] lists each shell.
(anything else) Custom types are stored verbatim. Free-form.

The metadata JSON column is where type-specific fields live (e.g. shells: [{ size, count, color }] for packs and cakes).

Adding items

Three paths:

1. Manual add

Click + Add item. Fill the form: name, type, duration, lift delay, color, available count, optional YouTube link, optional unit cost.

2. Add from library (catalog)

Click Add from library to open ImportCatalogModal. Loads /api/catalog, which serves /data/catalog.json (the cached crawl from backyard-hero.com/catalog.json).

If the catalog is stale or empty, the modal can trigger a refresh — POSTs /api/catalog/refresh, which spawns pythings/inv_crawl/crawl_catalog.py in the background. The modal polls progress (GET /api/catalog/refresh) and re-renders when the crawl finishes.

Filter by brand, type, color. Click Import on each row you want — creates an inventory row with source = 'catalog'.

3. Auto-parse shell descriptions

Click Parse shell descriptions. Paste a list of human-readable shell descriptions (e.g. from a wholesaler's invoice or a forum recommendation). The form POSTs to /api/inventory/parse-shell-descriptions which calls OpenAI (via OPENAI_API_KEY) to turn the text into structured shell rows: name, size, color, effect, duration estimate. Review and import.

YouTube firing profiles

If an item has a youtube_link and an optional youtube_link_start_sec, the system can analyze the audio of the video to extract per-shot timestamps. This is what the firing profile is.

The flow:

  1. From the inventory list, click Generate firing profile on an item with a YouTube link.
  2. POSTs /api/inventory/[id]/reprocess-profile.
  3. The Next.js handler spawns pythings/fp_gen/process_firing_profiles.py. The script:
    • Uses yt-dlp to download the video's best audio track.
    • Uses ffmpeg to trim from youtube_link_start_sec and convert to WAV.
    • Uses librosa for RMS envelope analysis and scipy.signal.find_peaks for shot detection.
    • Writes results to inventoryFiringProfile.shot_timestamps as [[start_ms, end_ms, "#hexcolor"], ...].
  4. The UI auto-updates once the profile is saved.

There's also a Reprocess all button to batch-regenerate all profiles for items that have YouTube links.

You can manually edit a profile in the ShotProfileModal — load the YouTube IFrame API for visual playback, drag shot windows around, fix detection misses.

The firing profile is what makes the timeline preview accurate for cakes — instead of one solid bar from t to t+duration, you see each individual shot at its real time. Critical for music synchronization.

Editing items

Click an item in the list. Edit any field, click Save. Changes propagate everywhere immediately.

Deleting an item:

  • DELETEs from /api/inventory/[id].
  • The handler also deletes the matching inventoryFiringProfile row (FK CASCADE).
  • Items in shows or racks that reference the deleted item render as "deleted item" with the original name preserved on the timeline. Best practice: replace references first, then delete.

Shell packs

A shell pack is one inventory row with type = SHELL_PACK and metadata.shells = [{...}, {...}]. The ShellPackEditor provides a small grid for editing each shell within the pack (size, color, effect, count).

In the show editor, when you place a shell pack, you reference (packId, shellIndex) rather than just an inventory id, so the timeline can color each individual shell correctly.

Implementation

  • host/byh_app/backyardhero/src/components/inventory/InventoryManager.jsx — main page.
  • host/byh_app/backyardhero/src/components/inventory/InventoryList.jsx — list/search.
  • host/byh_app/backyardhero/src/components/inventory/ImportCatalogModal.jsx — catalog import.
  • host/byh_app/backyardhero/src/components/inventory/ShellPackEditor.jsx — shell pack composition.
  • host/byh_app/backyardhero/src/components/inventory/ShotProfileModal.jsx — firing profile editor.
  • host/pythings/inv_crawl/crawl_catalog.py — the catalog fetch.
  • host/pythings/fp_gen/process_firing_profiles.py — YouTube → firing profile.

Clone this wiki locally