Straight from the Chain
The site renders cats from on-chain data at request time. The browser never fetches a pre-baked CDN image for the core gallery or wallet views.
Render pipeline
- The app calls
tokenURI(uint256 upegId, uint256 seed)on theRENDERERcontract0x2fE5bf2aB284bc71B261Ea6d32aaadfcA987Eeb8. - The returned
data:application/json;base64,...payload is decoded, then the embeddedimagefield is decoded into raw SVG. - Any embedded PNG fragments inside the SVG are upscaled with nearest-neighbor resampling so pixel edges stay crisp.
- The SVG is rasterized with
@resvg/resvg-js. - The PNG is resized with
sharpusingkernel: "nearest"for pixel-preserving output.
Cat render endpoint
GET /api/cat-render?id=<upegId>&seed=<seed>
GET /api/cat-render?id=<upegId>&seed=<seed>&thumb=1
| Query param | Required | Meaning |
|---|---|---|
id | Yes | Unsigned integer cat ID |
seed | Yes | Unsigned integer seed returned by OwnerUpegsPage |
thumb | No | Set to 1 for gallery thumbnails |
Behavior:
- Default output is a
456x336PNG. thumb=1returns a285x210PNG.- Invalid
idorseedreturns400. - The route is rate-limited to 60 requests per minute per IP.
- Successful responses are cached as
public, max-age=31536000, immutable.
Showcase data
GET /api/showcase-cats
This endpoint feeds the homepage "Straight from the Chain" section. It returns eight { id, seed } pairs.
Current behavior:
- The route first tries
OwnerUpegsPageagainst a known holder address. - If that live read fails or returns too few cats, it falls back to a hardcoded static pool.
- Responses are cached with
max-age=120andstale-while-revalidate=600.
Why the seed matters
The app treats (id, seed) as the full render key. Given the same pair, the site will always resolve the same on-chain art output.