Item row (JSON proposal)
How thumbnails get stored
Here every card image is made at load: each model is rendered once into a 256×256 offscreen WebGL canvas with a fixed 3/4 camera, then canvas.toDataURL('image/png'). "Download thumbnails" saves those PNGs.
For the real app, run the same code once per item, server-side: a queued Laravel job starts headless Chromium (Playwright or Browsershot/Puppeteer) on a tiny bake page /bake?item=ID, waits for window.__ready, reads the data URL, and stores it as storage/items/ID.png (or S3). The thumbnail URL goes into the item row; the inventory list then only loads PNGs, and the 3D model loads only when an item is opened.
Re-bake when the model ref or params change (hash them into the filename, e.g. longsword-3f9a.png).
Rendered here with software WebGL, the whole set takes a few seconds; on a normal GPU well under one.