THE HUNT← Back to The Hunt
The Hunt / A creative chronicle

The making
of a legend.

From the first spark to the final snowfall. Follow the prompts that shaped this world, and take a little of its magic into your own.

55Prompts
07Chapters
27Art prompts

Original user wording is retained. Private access credentials were removed and local skill paths were replaced with explicit placeholders. Screenshot references are described; private local files are not published. Continuation-only turns, redundant requests, typo-only corrections, browser metadata, and tool logs are omitted. Through the request to create this Prompts page, after the performance-skill refinement.

Chapter 01 / 5 prompts

The first vision

A world of steel, snow, and floating cards.

  1. Build your legend

    Conversation prompt
    Create a web page implementation from the following instructions: [https://diffui.ai/build/Card_Game_Landing_Page.md](https://diffui.ai/build/Card_Game_Landing_Page.md)
    
    Okay, I want you to recreate this landing page in Three.js in a single HTML file. I wanted to use GPT Image 2.5 built-in in Codex to generate the images, the transparent PNGs, the UIs, and the decorations, as well as the backgrounds.
    
    Make sure that you can have beautiful scroll animations that play with the cards and an orbiting 3D camera. We're also going to be using the depth map, normal maps, and roughness maps for the card textures and the images, so that it reflects and has this beautiful shine when you mouse over the cards.
    
    Let's do all of this in Three.js, and let's have scroll animations, orbit animations, and go crazy.
    Read source ↗
  2. A world in separate layers

    Conversation prompt
    - The lights are a little bit too strong. The light flare is a little bit too strong, and the depth mapping should be a little bit more obvious.
    - Make sure that there's no pixelation, and the cars in the background should look better and should also be transparent PNG cards.
    - The top header should be using transparent PNG decorations, as well as the buttons that say "Join the Hunt" and "Enter the Hunt". Those should be transparent PNG icons, as well as Northern Realm, Wild Court, and Ashen Legion.
    - As for the backgrounds, we're going to need multiple layers. It's going to be parallax, so we have the background, the second layer, which is the castle, and the front cliffs that are going to be in front. Those are all separate layers.
  3. Make the page move

    Conversation prompt
    The cards should be above the UI, and there should be a text transition as you scroll, as well as a text transition element by element when in view or during the intro. We're going to have some scroll animations, especially starting with "Choose Your Allegiance." There should be the card animations and depth mapping, rough mapness, and on that card as well, with orbit interactions on mouseover. The footer should have some cards as well, and the section "Your Hand, Your Move" also should have some cards.
  4. Resolution, by design

    Conversation prompt
    [$3d-high-resolution-textures]([local skill path omitted]) [$3d-retina-resolution]([local skill path omitted])
  5. Open the world

    Conversation prompt
    start server
Chapter 02 / 9 prompts

Cards with presence

Depth, reflection, and an inspection worth opening.

  1. Bring a card to the front

    Hero card composition reference

    Conversation prompt
    When I click on the card, it should maximize it, coming from the front, vertically centered and horizontally centered, and should blur the rest of the UI. It should have some more information, and you can play with it and rotate it by dragging.
  2. A controlled orbit

    Silver Hunter rotation reference

    Conversation prompt
    Make sure to rotate it properly so that it doesn't go too far into the rotation, which kind of breaks the UI a little bit here. We need some more shine. I guess we shouldn't rotate too much.
  3. New faces in the deck

    Conversation prompt
    Let's create more cards for wild cards and for the footer. They should be different cards. [$codex-gpt-image-2-5-flare]([local skill path omitted])
  4. A reusable material practice

    Conversation prompt
    We're going to turn the depth maps, normal maps, and roughness maps into a skill for 3D. 3d-depth-maps
  5. Choose the next card

    Collection selection reference

    Conversation prompt
    I should be able to select the other cards to bring those into focus.
  6. Let the card stand alone

    Hero and framed inspector references

    Conversation prompt
    These cards, like I said, should be transitioning into full view without the container. Just the card transitioning into rotating, doing a flip. No container. Also, remove all of the outline because of the keyboard keys. Just remove that CSS setting.
  7. A solid castle, a softer distance

    Collection landscape reference

    Conversation prompt
    The background castle should not be transparent. Should never be transparent But when that is more in focus, then the background image, like the landscape image, should be more blurry.
  8. Clean up the highlights

    War Captain close-up reference

    Conversation prompt
    Make sure that we don't have pixelations and those weird tiny white dots.
  9. Room for cards and words

    Mobile hero reference

    Conversation prompt
    Make sure that the cards don't overlap when they rotate in the hero section, like the silver hunter versus the ancient relic. Make sure to adapt properly on mobile so that the card shadow doesn't overlap with the texts.
Chapter 03 / 14 prompts

A world in layers

Atmosphere, composition, and a sharper horizon.

  1. Weather for the world

    Wide hero composition reference

    Conversation prompt
    Can we change the background a bit? Give me a few choices for the background. We should have: 
    
    - clouds
    - smoke
    - rays of light
    - falling snow
    - particles
    
    in three.js
    
    
    
    Also, when the cards flip in full view, they should only flip once, not twice.
  2. Bring back the glass

    Silver Hunter surface reference

    Conversation prompt
    Before, it was kind of more glass-ish, like there's a glass in front of the character. Now it feels like there's less of that. I'm not sure what you changed. What is the regression? Can you look into it?
  3. More light in the materials

    Conversation prompt
    can we add more lighting to the [$3d-depth-maps]([local skill path omitted])
  4. Give desktop room to breathe

    Desktop card spacing reference

    Conversation prompt
    On desktop, when we have enough space permitted, the cards should be more like before: some of them are bigger, some of them are behind, and so on and so forth. Only on mobile, we need to make sure that they are not overlapping with the text and content.
  5. Three horizons

    Landscape quality reference

    Conversation prompt
    Give me three choices for the background image. I feel like the quality is low compared to the castle. The castle quality is quite good, but the background image in the landscaping image is low quality. Give me some concepts at high resolution, 4k [$codex-gpt-image-2-5-flare]([local skill path omitted])
  6. Choose the third horizon

    Conversation prompt
    go with third one. optimize images
  7. Find the center

    Enter the Hunt button reference

    Conversation prompt
    center the text. horizontally
  8. One card in focus

    Ancient Relic inspection reference

    Conversation prompt
    When opening a card, the existing card should fade out. So that we don't have a copy of both
  9. Return without fading

    Conversation prompt
    When the card goes back, it shouldn't be fading out.
  10. Catch more light

    Ancient Relic material reference

    Conversation prompt
    can we make the depth maps more obvious and shiny/reflecting
  11. A little balanced chaos

    Hero card arrangement reference

    Conversation prompt
    Some of the front cards should definitely be larger. The card should be spread a little bit more, and the composition should be better. Also, the background cards should be composed a little bit better with chaos but balanced.
  12. Push the orbit

    Conversation prompt
    Can we orbit the card angle even more? And make the depth shines a little bit more pronounced.
  13. Give the world an address

    Conversation prompt
    Let's push this to cardgame.mengto.here.now
  14. A quiet arrival

    Conversation prompt
    Let's add a loader at the beginning. Make it minimal and use particles.
Chapter 04 / 6 prompts

The elements awaken

Ice, cinders, leaves, and light inside the portrait.

  1. Wake the magic

    Frost Mage orb and Ancient Relic crystal references

    Conversation prompt
    Can we add some shaders, animations, magic, and ultra-realistic shaders animation to these elements?
  2. Cinders for the captain

    War Captain portrait reference

    Conversation prompt
    For this one, we're going to add Cinder animations shaders.
  3. A northern blizzard

    Silver Hunter portrait reference

    Conversation prompt
    And for this one, we're going to add the snowstorm animation (blizzard animation).
  4. Light through the forest

    Forest Behemoth portrait reference

    Conversation prompt
    For this one, we're going to add the tiny falling leaves animations and also the ray of light animation.
  5. Keep the magic inside

    Conversation prompt
    Make sure all the animations are within the card, like the portrait of the card within the container of the card.
  6. Reveal the effects on inspection

    Conversation prompt
    Can you improve the effects on each card? The effect should only start when you go into the full view of the card. We need to make them ultra-realistic and much more obvious.
Chapter 05 / 11 prompts

Every detail matters

Smaller snow, brighter sparks, and effects that belong.

  1. Separate the frame from the portrait

    Silver Hunter snow and frame reference

    Conversation prompt
    The effects are still not probably part of the card. I think there's some padding there. Secondly, the beveling should not be part of the character. It's separate from the image character, right? It's a separate layer in front. The snow is not realistic at all, so please make it realistic, super realistic: snow, blizzard, and wind.
  2. Give the cinders a reason

    War Captain cinder reference

    Conversation prompt
    All the effects of each card should make sense. Right now, it doesn't make sense. It doesn't look like Cinder is flying using particles and shaders.
  3. Snow for the Frost Mage

    Frost Mage portrait reference

    Conversation prompt
    We should also have snow for this one.
  4. Life around the relic

    Ancient Relic portrait reference

    Conversation prompt
    We should have particles, wisps and falling leaves in this one.
  5. Look again, then refine

    Conversation prompt
    Self-verify until they're perfect.
  6. A loop of refinement

    Conversation prompt
    [$dream-loop]([local skill path omitted])
  7. A reference for fire

    Canvas UI: Blaze — supplied React/WebGL source

    Conversation prompt
    For the Cinder, let's use this one and get inspired by this one.
    Read source ↗
  8. Smaller, more believable sparks

    Conversation prompt
    Make sure that they're tiny, like the blurry one, and make sure that they're more realistic and smaller.
  9. Rays with direction

    Conversation prompt
    for rays of light: [$3d-sky-rays]([local skill path omitted])
  10. Fine snow, no blurred flakes

    Foreground snow reference

    Conversation prompt
    no blurred snow! make front snow smaller
  11. Turn up the cinders

    War Captain detail reference

    Conversation prompt
    make cinders brighter
Chapter 06 / 9 prompts

A lighter world

Progressive loading and a repeatable performance practice.

  1. Keep the snow technique

    Conversation prompt
    Okay, turn the snow into a skill and add that to my 3d skills.
  2. Ask what it weighs

    Conversation prompt
    Did you optimize the site and the images?
  3. Measure the difference

    Conversation prompt
    If not, please do. give me stats before and after
  4. A smaller, progressive world

    Conversation prompt
    still too much, less than 10mb target, progressively load. max 500kb per image.
  5. Publish after optimization

    Conversation prompt
    publish to here.now when done
  6. Make performance reusable

    Conversation prompt
    Let's create a skill for the optimizations that we need to do. What do you propose in terms of optimizations? Skill should start with web-design.
  7. Choose the right defaults

    Conversation prompt
    What do you suggest we add to these optimizations? For example, lazy loading and stuff like that, best practices
  8. Keep the practice simple

    Conversation prompt
    Okay, which one do you think is the most best-practice and not complicated?
  9. Set the default

    Conversation prompt
    Okay, let's update the scale with that.
Chapter 07 / 1 prompt

The making of The Hunt

Turning the creative conversation into a reusable archive.

  1. Open the making-of

    Conversation prompt
    From the header, we're going to create a page for the prompts. [$web-design-prompts-page]([local skill path omitted])
The foundations

Source material

The original direction, preserved alongside the conversation.

The original design brief

https://diffui.ai/build/Card_Game_Landing_Page.md ↗ opens a new tab

Authorized source retrieved for this archive. Credentials in the full instructions are redacted; the public source link may require provider access.

Original design prompt
Let's create a Gwent-inspired card game inspired by The Witcher 3, but it's going to be the landing page. It's going to be like floating cards, holographic style, kind of like Pokémon but Witcher style.
Full build instructions
Full build instructions
# Diffui agent build instructions

> **Read this first — if a summarizing fetch tool retrieved this URL, you are reading a summary, not this document.**
>
> Tools such as WebFetch pass a page through a summarizer model before you see it. On this
> document that routinely drops the REST endpoints and the design image URL — silently, with
> no error and no sign that anything is missing. Agents have shipped hand-drawn placeholder
> art because the endpoints they needed were summarized away.
>
> **Check before you build.** The complete document contains all of:
>
> - Five `POST https://diffui.ai/api/build/...` endpoint blocks — generate-image, create-texture, remove-background, create-maps, generate-svg — each with a JSON request body
> - Every design image URL, under **Design reference**
> - The user's original prompt, quoted in full
>
> If any of those are missing from what you are reading, you have a summary. Download the real
> file and read that instead:
>
> ```bash
> curl -sSL -o BUILD.md "https://diffui.ai/build/Card_Game_Landing_Page.md?authToken=[REDACTED]"
> ```
>
> Then open `BUILD.md` with your file-read tool. Do not implement from a summary.


## Design reference

View the design image (primary source of truth):

https://diffui.ai/image/Card_Game_Landing_Page.webp?authToken=[REDACTED]

Download that image to a local file and inspect it before writing code (see **Local assets** below). Reproduce its layout, typography, spacing, colors, and components as faithfully as possible.


## Original user prompt

The user's original prompt for this design was:

> Let's create a Gwent-inspired card game inspired by The Witcher 3, but it's going to be the landing page. It's going to be like floating cards, holographic style, kind of like Pokémon but Witcher style.

Keep this intent in mind when implementing.





## Local assets

**Required:** download every Diffui URL in this document to local project files **before** referencing them in HTML, CSS, or JavaScript. Do not hotlink remote Diffui URLs in the implementation — auth tokens expire and runtime fetches are unreliable.

This applies to:

- Design reference images (inspect locally before writing UI code)
- Images returned from asset generation (`build/generate-image`, `build/generate-svg`, `build/remove-background`, `build/create-texture`, and `build/create-maps`)
- Any other Diffui image URL in this document

Save downloads under a project folder such as `assets/` and reference those local paths in code.

### Downloading design images

Design renders are visual specifications. **Download each image and inspect it before writing code.** Do not rely on text summaries alone.


Image URLs serve **WebP by default** (good for `<img>` tags in browsers). Many agent **URL-to-markdown fetch tools cannot decode WebP** and may fail even though the URL works with `curl`.

For vision analysis, download PNG — append `&format=png` to the design URL, or use a `.png` filename in the path. Open the downloaded file with your image/read tool and analyze layout, copy, colors, and spacing.

Example (design spec for analysis — not a final asset):

```bash
curl -L -o assets/page.png "https://diffui.ai/image/Page_Name.webp?authToken=[REDACTED]&format=png"
# or
curl -L -o assets/page.png "https://diffui.ai/image/Page_Name.png?authToken=[REDACTED]"
```

Replace `Page_Name` with the slug from each design image URL in this document.

**Note:** Design image URLs are binary assets. URL-fetch-to-markdown tools may fail; download the file instead.


**Do not use design crops as final page assets.** Never crop a hero image, photo, or illustration out of the design reference and place that crop in your HTML/CSS. The design image is a **specification only** — generate real high-resolution assets via `build/generate-image` (see **Generating image assets** below). Cropping the design is not a substitute for generation.

The `&crop=x,y,width,height` query param is for **inspection and intermediate pipelines only** (e.g. measuring a region, or feeding a large illustration into image-to-SVG). It must **not** appear in any `<img src>`, CSS `background-image`, or other shipped asset path.

## Project setup

Inspect the target repository before choosing a stack:

| Situation | What to do |
|-----------|------------|
| **Existing project** | Use the framework, tooling, and patterns already present. Do not introduce a different stack. |
| **Empty repo + linked npm package** (see Brand context) | Scaffold the minimum project that package requires, install it, then implement. Do not default to vanilla HTML/CSS when a brand package is linked. |
| **Empty repo, no linked package** | Use vanilla HTML, CSS, and JavaScript. |

When a linked npm package implies a specific framework (React, Vue, etc.) or tooling (Tailwind, shadcn CLI), scaffold that stack with sensible defaults — e.g. Next.js or Vite for React-based design systems — even if this document does not spell out every init command.

## Implementation guidelines

You are an elite frontend engineer and design-to-code specialist. The design image is the primary source of truth; your code is the translation layer. Do not reinterpret or "improve" the design into something generic — reproduce it faithfully.

Before writing code, analyze the image like a design specification:

- **Layout & structure:** overall grid, section ordering, alignment, column logic, content width.
- **Typography:** extract visible text verbatim; size/weight hierarchy, display vs body contrast, line height, tracking, serif vs sans.
- **Spacing:** section padding, gutters, gaps, card padding, image-to-text distance. Preserve generous spacing; do not compress.
- **Color:** background, panels, accents, button fills, text hierarchy, borders, shadows. Preserve the exact palette you observe; do not substitute generic web colors.
- **Textures & surfaces:** Look for repeating photographic or organic surfaces used as tiled backgrounds — paper grain, linen, concrete, stone, wood grain, fabric weave, film noise, subtle marbling. Note tiling direction if visible: omnidirectional repeat → `both`; stripe or band patterns that repeat on one axis only → `horizontal` or `vertical`. Do **not** generate textures for flat solid fills, simple CSS gradients, hero photos, or illustrations — use CSS or `build/generate-image` instead. Only call `build/create-texture` when a seamless repeating surface is clearly part of the shipped design. Request extra PBR maps (`normal`, `roughness`, etc.) **only** when the user explicitly wants WebGL-style lighting or physically based shading — not for ordinary CSS `background-repeat` tiles.
- **Components:** buttons (shape, radius, fill vs outline, padding, primary/secondary), cards, inputs, badges, dividers, icons.
- **Imagery:** Match the container silhouette, not just the asset. Non-rectangular boundaries are first-class layout — implement with clip/mask, not border-radius. Generate high-res images via `build/generate-image`; generate seamless repeating surfaces via `build/create-texture` when the design calls for them; never ship crops from the design reference as final artwork.

Implementation discipline:

- Preserve layout logic, spacing rhythm, section ordering, text/image balance, typography mood, and component styling.
- Use the actual visible text from the image, not placeholder copy.
- Match colors and spacing to what you observe, not to defaults.
- Do not add nested box-in-box wrappers, decorative pills, fake status labels, or micro-UI clutter not in the image.
- Avoid AI-slop (default purple/blue gradients, glow, glassmorphism, generic card spam) unless the image clearly shows it.
- Keep the first viewport clean and readable; responsive in spirit while keeping the desktop composition faithful.
- Follow the **Project setup** rules above: match an existing repo's stack, scaffold for a linked npm package on an empty repo, or use vanilla HTML/CSS/JS when no package is linked.

Resolve ambiguity in this order: preserve the visible design language, then layout/spacing logic, then component family, then mood/polish — only then fall back to a faithful choice. The final result should look like the same design in the image, translated into real code.

## Generating image assets

When the design needs photos or illustrations (avatars, hero images, product shots, lineup photos, etc.), **generate them via Diffui** — do not use placeholders and **do not crop them out of the design reference**.


**Required for all photographic and illustrative content in the page:**

- Hero banners, scene illustrations, artist photos, product shots, and any other raster imagery → `build/generate-image`
- Use **high** quality + `referenceImageUrl` when recreating a large hero or focal illustration from the design (see **Reference images**).
- Use **medium** quality for lineup photos, avatars, and card imagery.
- If generation fails, **retry** (including waiting longer for high-quality hero requests). Do not fall back to a cropped region of the design image as the shipped asset.

**Endpoint:** `POST https://diffui.ai/api/build/generate-image`

**Headers:** `Content-Type: application/json`

**Body (JSON):**

```json
{
  "authToken": "[REDACTED]",
  "prompt": "A portrait of a man for an avatar",
  "width": 512,
  "height": 512,
  "quality": "medium"
}
```

**Required fields:**

- `authToken` — the same token from this build link (`[REDACTED]`).
- `prompt` — plain-text description of the image (describe what you want; no negative prompts).
- `width` and `height` — **required** on every request. Choose dimensions explicitly for each asset.

**Optional fields:**

- `quality` — `"medium"` (default) or `"high"`. See **Choosing quality** below.
- `referenceImageUrl` — a Diffui image URL to use as a visual reference. **High quality (`"high"` / gpt-image-2) only.** See **Reference images** below.
- `transparentBackground` — `true` to generate the asset with a **native alpha channel** (real transparency, not a removed background). **High quality (`"high"` / gpt-image-2) only.** See **Transparent backgrounds** below.

**Response (JSON):**

```json
{
  "url": "https://diffui.ai/image/generated_example.webp?authToken=[REDACTED]",
  "width": 512,
  "height": 512
}
```

Download the returned `url` to a local file (see **Local assets**), then reference that path in your HTML/CSS. Do not hotlink the remote URL. The auth token expires after seven days; if generation fails with 403, ask the user to re-copy the build link from Diffui.

To inspect a generated asset with a vision tool, download PNG the same way as design images (`&format=png` or a `.png` path suffix).

### Choosing quality

Pick `quality` per asset. **Default to medium** — it is faster, cheaper (1¢), and sufficient for most page assets.

| Use **medium** (default, 1¢) | Use **high** (17¢) |
|------------------------------|---------------------|
| Profile pictures, avatars | Large hero / banner images |
| Product shots, thumbnails | Anything needing ~2K resolution |
| Icons, small decorative images | Illustrations, artistic focal imagery |
| Most page assets | Main visual focus of the page |
| | Any asset needing a transparent background |

**Medium example** (avatar):

```json
{
  "authToken": "[REDACTED]",
  "prompt": "Professional headshot portrait of a woman, neutral background",
  "width": 512,
  "height": 512,
  "quality": "medium"
}
```

**High example** (hero illustration):

```json
{
  "authToken": "[REDACTED]",
  "prompt": "Wide cinematic illustration of a mountain landscape at sunset, painterly style",
  "width": 2048,
  "height": 1536,
  "quality": "high"
}
```

### Transparent backgrounds (high quality only)

Set `transparentBackground: true` when a **new** generated asset should composite over other page elements — the PNG comes back with a **native alpha channel** from gpt-image-2 in the same billed call. Do **not** generate an opaque image and then call `build/remove-background` for new assets; that costs an extra step and produces a worse matte.

**Request transparency when the asset floats over other UI:**

- Hero images or backdrop artwork layered over other elements
- Overlay illustrations and decorative layers
- Isolated products or objects (product on nothing, not product on white)
- Icons, charts, and other assets placed on colored/typographic backgrounds

**Keep it opaque (omit the flag) when:**

- The asset is a full-bleed photo, scene, or filled background
- The image fills its own rectangle and nothing shows through it

Rules: requires `quality: "high"` (400 otherwise) and follows the high-quality (gpt-image-2) size rules. Reference the downloaded asset as PNG (or the served WebP, which also keeps alpha) — never re-encode it to JPEG or flatten it onto a background color.

**Transparent example** (floating product cutout):

```json
{
  "authToken": "[REDACTED]",
  "prompt": "Studio shot of a single red running sneaker, floating at a three-quarter angle",
  "width": 1024,
  "height": 1024,
  "quality": "high",
  "transparentBackground": true
}
```

`build/remove-background` still exists for bitmaps you already have (user uploads, previously generated images) — see **Removing image backgrounds**.

### Reference images (high quality only)

Use `referenceImageUrl` **only** when you need gpt-image-2 to recreate a **standalone background or illustration** that appears inside the design — not the full page screenshot.

**Use a reference image when:**

- The design shows a large hero illustration, scene, or photographic background that must become a real `<img>` or CSS background asset.
- You need a **full-resolution, isolated** version of that artwork (no navigation, buttons, headlines, or other UI chrome).
- A plain-text prompt alone would not preserve the composition, subjects, palette, or graphic details visible in the design.

**Do not use a reference image when:**

- Generating avatars, product shots, icons, thumbnails, or other assets that are **not** copied from a specific region of the design image.
- The asset is simple enough to describe accurately with `prompt` alone.
- You want to regenerate the **entire page** or any layout that includes UI elements — implement those in HTML/CSS from the design reference instead.

Pass a Diffui URL from this document (design image or a previously generated asset). The `authToken` in `referenceImageUrl` must match `authToken` in the request body. `referenceImageUrl` is rejected unless `quality` is `"high"`.

**High example** (isolated hero illustration from the design):

```json
{
  "authToken": "[REDACTED]",
  "prompt": "Recreate only the hero illustration from the reference: saxophonist in black suit and fedora against a New Orleans skyline, yellow sun disc, expressive JAZZ lettering, and purple brushstroke banner — no navigation, buttons, headlines, or page chrome. Match the reference composition, subjects, and color palette.",
  "width": 2048,
  "height": 1536,
  "quality": "high",
  "referenceImageUrl": "https://diffui.ai/image/Card_Game_Landing_Page.webp?authToken=[REDACTED]"
}
```

### Generation timing

- Each image request typically takes **around 60 seconds**; occasionally one can take **up to 3 minutes**.
- Wait for each request to finish before using its returned `url`.
- When you need **multiple assets**, send **separate requests in parallel** whenever you can (concurrent POSTs with different prompts and dimensions). Parallel generation is much faster than generating images one at a time.

### Medium quality (z-image) size rules

Used when `quality` is `"medium"` or omitted. Every `width`/`height` pair must satisfy all of:

| Constraint | Value |
|------------|-------|
| Minimum edge | 512 px |
| Maximum edge | 2048 px |
| Maximum aspect ratio | 3:1 (neither side more than 3× the other) |

**Sizing guidance:**

- **Avatars / icons / small squares:** **512×512**
- **Product shots / cards:** **512×768** or **768×512**
- **Medium landscape panels:** **1024×768**

Invalid dimensions return HTTP 400 with an error message.

### High quality (gpt-image-2) size rules

Used when `quality` is `"high"`. Every `width`/`height` pair must satisfy all of:

| Constraint | Value |
|------------|-------|
| Minimum edge | 16 px |
| Maximum edge | 2048 px |
| Multiple of | 16 |
| Maximum aspect ratio | 3:1 (neither side more than 3× the other) |
| Minimum total pixels | 655,360 |

**Sizing guidance:**

- **Avatars / icons / small squares:** use **816×816** (smallest valid square).
- **Landscape hero / banner:** **2048×1536**
- **Portrait hero:** **1536×2048**
- **Wide thumbnails:** e.g. **1280×512** (must still meet the pixel minimum)

Invalid dimensions return HTTP 400 with an error message. There is no default size — always specify `width` and `height` intentionally for each asset.

## Seamless background textures

When the design uses a **repeating photographic or organic surface** as a background (paper grain, linen, concrete, stone, fabric weave, subtle noise overlay), generate a seamless tile via Diffui — do not approximate with a cropped region from the design reference and do not use `build/generate-image` for textures.

**Generate a texture when:**

- The design shows a surface meant to tile with `background-repeat` (paper, linen, concrete, fabric, stone, film grain, etc.)
- A plain CSS color or gradient cannot faithfully reproduce the visible surface

**Do not generate a texture when:**

- The background is a flat solid color or a simple linear/radial gradient → use CSS
- The surface is glass, blur, or frosted effects → use CSS `backdrop-filter` or similar
- The asset is a hero photo, illustration, or product shot → use `build/generate-image`
- The pattern is a standard UI motif achievable with CSS alone

**Endpoint:** `POST https://diffui.ai/api/build/create-texture`

**Headers:** `Content-Type: application/json`

**Body (JSON):**

```json
{
  "authToken": "[REDACTED]",
  "prompt": "warm off-white paper grain, subtle fiber texture",
  "tilingMode": "both"
}
```

**Required fields:**

- `authToken` — the same token from this build link (`[REDACTED]`).
- `prompt` — describe the surface or material only (what you want the tile to look like).

**Optional fields:**

- `tilingMode` — `"both"` (default), `"horizontal"`, or `"vertical"`. Use `"both"` for omnidirectional repeats. Use `"horizontal"` or `"vertical"` only when the design clearly repeats on one axis (e.g. horizontal wood slats or vertical fabric stripes).
- `maps` — optional array of PBR map types to generate alongside the seamless tile. Allowed values: `"basecolor"`, `"normal"`, `"roughness"`, `"metalness"`, `"height"`. Omit it or pass an empty array to use the Fal model default. **Only request specific maps when the user explicitly wants WebGL-style lighting or physically based shading** — not for standard CSS repeating backgrounds.

Example with a normal map for a lit 3D surface:

```json
{
  "authToken": "[REDACTED]",
  "prompt": "weathered brushed steel, fine directional scratches",
  "tilingMode": "both",
  "maps": ["normal", "roughness"]
}
```

**Response (JSON):**

```json
{
  "url": "https://diffui.ai/image/generated_texture.webp?authToken=[REDACTED]",
  "width": 1024,
  "height": 1024,
  "tilingMode": "both",
  "maps": [
    {
      "type": "normal",
      "url": "https://diffui.ai/image/generated_texture_normal.webp?authToken=[REDACTED]"
    },
    {
      "type": "roughness",
      "url": "https://diffui.ai/image/generated_texture_roughness.webp?authToken=[REDACTED]"
    }
  ]
}
```

When `maps` is omitted, Diffui omits the field from the Fal request so the model uses its default maps. If Fal returns map images, Diffui includes them in the `maps` response array.

Output is always **1024×1024**. Download the returned `url` locally (see **Local assets**), then reference that path in CSS:

| `tilingMode` | CSS `background-repeat` |
|---------------------|--------------------------------|
| `both` | `repeat` |
| `horizontal` | `repeat-x` |
| `vertical` | `repeat-y` |

- Cost: **3¢** per call for the seamless tile alone; **+1¢** per additional PBR map at 1024×1024 (e.g. tile + normal = 4¢).
- Typical workflow: identify the surface during design analysis → generate once → apply as a repeating CSS background. Request extra maps only for WebGL / Three.js materials with real-time lighting.

## Removing image backgrounds

When an **already-sourced** bitmap needs a transparent cutout (a user-provided product photo, an existing profile picture, a previously generated image), remove its background via Diffui. The endpoint accepts either a remote image URL (JSON) or a **local file uploaded directly** (multipart) — use the upload form for user-provided images that only exist on disk.

For **new** assets that need transparency, do not use this endpoint — generate them with native alpha instead (`transparentBackground: true` on `build/generate-image` at high quality; see **Transparent backgrounds**). That is one billed call with a real alpha channel rather than a generate-then-cut-out pipeline.

**Endpoint:** `POST https://diffui.ai/api/build/remove-background`

### Option A — remote image URL (JSON)

**Headers:** `Content-Type: application/json`

**Body (JSON):**

```json
{
  "authToken": "[REDACTED]",
  "imageUrl": "https://diffui.ai/image/generated_example.webp?authToken=[REDACTED]"
}
```

- `imageUrl` — a publicly fetchable image URL. Use a Diffui asset URL from `build/generate-image` (include the `authToken` query param).

### Option B — local file upload (multipart)

Send the file bytes directly as `multipart/form-data` — no hosting required:

```bash
curl -X POST "https://diffui.ai/api/build/remove-background" \
  -F "authToken=[REDACTED]" \
  -F "file=@assets/product-photo.png"
```

- `file` — the image file (PNG, JPEG, or WebP; max 25MB).
- Pass exactly one of `imageUrl` or `file`, not both.

**Required in both forms:**

- `authToken` — the same token from this build link.

**Response (JSON):**

```json
{
  "url": "https://diffui.ai/image/generated_cutout.webp?authToken=[REDACTED]",
  "width": 512,
  "height": 512
}
```

- Cost: **1¢** per call.
- Typical workflow: cut out a user-provided or previously generated bitmap. For new assets, request native transparency at generation time instead (see **Transparent backgrounds**).
- Download the returned `url` locally before using it in code (see **Local assets**).
- The returned image is a transparent PNG served as WebP for display; use `&format=png` when you need the alpha channel for inspection.

## Generating PBR maps from an image

When an existing image needs WebGL-style lighting — normal, height (displacement), roughness, basecolor (albedo), or metalness maps — generate the maps via Diffui. Use this for hero artwork, product cutouts, or any raster that will be lit in a shader. **Only call it when the user explicitly wants physically based lighting or displacement**, not for ordinary flat imagery.

Like remove-background, the input is either a remote URL (JSON) or a **local file uploaded directly** (multipart).

**Endpoint:** `POST https://diffui.ai/api/build/create-maps`

### Option A — remote image URL (JSON)

**Headers:** `Content-Type: application/json`

**Body (JSON):**

```json
{
  "authToken": "[REDACTED]",
  "imageUrl": "https://diffui.ai/image/generated_example.webp?authToken=[REDACTED]",
  "maps": ["normal", "height", "roughness"]
}
```

### Option B — local file upload (multipart)

```bash
curl -X POST "https://diffui.ai/api/build/create-maps" \
  -F "authToken=[REDACTED]" \
  -F "file=@assets/card.png" \
  -F "maps=normal,height,roughness"
```

**Required fields:**

- `authToken` — the same token from this build link.
- Exactly one of `imageUrl` (publicly fetchable URL) or `file` (PNG, JPEG, or WebP; max 25MB).

**Optional fields:**

- `maps` — which maps to predict: `"basecolor"`, `"normal"`, `"roughness"`, `"metalness"`, `"height"`. Omit to generate **all five**. Request only the maps your shader actually samples — cost scales per map.

**Asynchronous response (HTTP 202):**

```json
{"jobId":"...","status":"queued","watchPath":"/api/build/jobs/.../watch?authToken=[REDACTED]"}
```

Save this response. Connect a WebSocket to `watchPath` on the same host (use wss for https).
The server immediately sends a `build_job_snapshot`, then pushes job events with keepalive pings.
On `status: completed`, read the map response from `result`.
On `status: error` / `status: cancelled` or `type: generation_job_error`, report `error`.
Reconnect to the **same watchPath** if the connection drops: the completed result is durable.
Do not poll or submit a new generation to recover a lost connection. Identical requests within the
same build return the same job; map order and duplicate map names do not change its identity.
API-key clients use the returned buildId query and their Authorization header on the WebSocket.
The MCP `build_create_maps` tool handles this stream automatically and returns the final result.

**Completed result (JSON):**

```json
{
  "width": 1024,
  "height": 1536,
  "maps": [
    {
      "type": "normal",
      "url": "https://diffui.ai/image/generated_example_normal.webp?authToken=[REDACTED]"
    },
    {
      "type": "height",
      "url": "https://diffui.ai/image/generated_example_height.webp?authToken=[REDACTED]"
    },
    {
      "type": "roughness",
      "url": "https://diffui.ai/image/generated_example_roughness.webp?authToken=[REDACTED]"
    }
  ]
}
```

Maps match the input image dimensions and share its UV space — sample them with the same coordinates as the source texture.

- Cost: **1¢** base + **1¢ per megapixel per map** (e.g. a 1024×1024 input with all 5 maps = 6¢).
- Download each returned map `url` locally before referencing it (see **Local assets**); use `&format=png` when the shader pipeline needs lossless data.
- Unlike `build/create-texture` (which *generates a new seamless tile* from a text prompt), `build/create-maps` derives maps for an image you already have.

## Generating SVG assets

**Endpoint:** `POST https://diffui.ai/api/build/generate-svg`

**Headers:** `Content-Type: application/json`

Pick the mode by asset type — **do not use image-to-SVG for small UI icons**; vectorizing cropped icon pixels produces poor results. Use **text-to-SVG** for icons instead.

### Custom icons → text-to-SVG only

Use Quiver **text-to-SVG** for **non-standard icons** not available in your project's icon library — for example a ferris wheel for a county fair or a unique pictogram from the design.

**Do not generate SVGs for standard UI icons** (arrows, chevrons, menu, close, search, social logos, etc.). Use the icon pack your project already uses (Lucide, Heroicons, Phosphor, Material Symbols, etc.).

**Do not use image-to-SVG for icons** — even with a tight crop from the design, results are usually unusable. Describe the icon in a `prompt` instead.

**Before generating:** search the icon pack for a close match. Only call `build/generate-svg` when no suitable icon exists.

Describe the icon in `prompt`. Optional `instructions` sets style (flat monochrome, line weight, etc.). **Always set `viewBox`** so the artwork fits the canvas and is not clipped. Use a square viewBox for icons (e.g. 64×64).

```json
{
  "authToken": "[REDACTED]",
  "prompt": "Minimal ferris wheel icon for a county fair app, single-color line art",
  "instructions": "Flat monochrome icon. Draw entirely inside the viewBox with comfortable padding; do not extend past the canvas edges.",
  "viewBox": { "minX": 0, "minY": 0, "width": 64, "height": 64 }
}
```

### Complex illustrations → image-to-SVG only

Use **image-to-SVG** only for **large or complex artwork** that should become a vector illustration — for example a detailed logo mark, badge, or decorative graphic region from the design. **Not for footer icons, toolbar glyphs, or other small UI pictograms.**

1. Download the design as PNG (`&format=png`) and inspect it.
2. Measure the illustration's bounding box in pixels (not a tiny icon crop).
3. Fetch a crop around that region: `&format=png&crop=x,y,width,height` — no labels or neighboring UI unless they are part of the artwork.
4. Pass that URL as `imageUrl`. Use a viewBox that matches the illustration's aspect ratio and scale (e.g. 512×512 for a square logo).

```json
{
  "authToken": "[REDACTED]",
  "imageUrl": "https://diffui.ai/image/Hero.webp?authToken=[REDACTED]&format=png&crop=400,80,640,480",
  "viewBox": { "minX": 0, "minY": 0, "width": 512, "height": 384 }
}
```

**Required fields:**

- `authToken` — the same token from this build link.
- Exactly one of `prompt` (text-to-SVG, **icons only**) or `imageUrl` (image-to-SVG, **illustrations only**).
- `viewBox` — SVG canvas forwarded to Quiver as `attributes.viewBox`. Set `minX` and `minY` to `0` unless you have a reason not to. Artwork must fit entirely inside this box with padding.

**Optional field:**

- `instructions` — text-to-SVG only; style guidance for Quiver. Mention that the icon must stay inside the viewBox.

**Response (JSON):**

```json
{
  "url": "https://diffui.ai/image/generated_example.svg?authToken=[REDACTED]",
  "width": 24,
  "height": 24
}
```

- Cost: **2¢** per SVG.
- Download the returned `url` locally before using it inline or as `<img src>` (see **Local assets**).

Blaze · React / WebGL

Source supplied by the user as inspiration for the cinders. No public source URL was provided.

Read the supplied source
Supplied source document
# Canvas UI: Blaze (React, WebGL)

Fire at the bottom of the page. Sparks, smoke, and heat distortion rise into your content. Look down, it is already burning.

## Install

```sh
npx shadcn@latest add @canvas-ui/blaze-react
```

Or copy the standalone source below into your project as Blaze.tsx.

## Current configuration

The component as configured right now in the docs demo (React syntax; prop values apply to every framework):

```tsx
import { Blaze } from "@/components/canvasui/Blaze";

<Blaze
  height={0.97}
  distortion={0.6}
  distortionScale={0.5}
  speed={1}
  sparks={0.5}
  sparkDensity={1.5}
  sparkSize={1}
  layers={4}
  smoke={0.5}
  glow={1.5}
  sparkColor={[1, 0.4, 0.051]}
  smokeColor={[1, 0.4314, 0.102]}
>
  {/* your content */}
</Blaze>
```

## Props

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| height | number | 0.97 | Height of the blaze zone as a fraction of the screen (0 to 1). |
| distortion | number | 0.6 | Strength of the heat distortion bending the content. |
| distortionScale | number | 0.5 | Scale of the heat distortion noise. Higher means finer ripples. |
| speed | number | 1 | Animation speed multiplier for the whole effect. |
| sparks | number | 0.5 | Brightness of the rising sparks. 0 disables them. |
| sparkDensity | number | 1.5 | How tightly packed the sparks are. Higher also makes them smaller. |
| sparkSize | number | 1 | Size of the individual sparks. |
| layers | number | 4 | Number of spark layers stacked for depth (1 to 10). |
| smoke | number | 0.5 | Intensity of the smoke. 0 disables it. |
| glow | number | 1.5 | Warm ambient glow near the bottom edge. |
| sparkColor | [number, number, number] | [1, 0.4, 0.05] | Spark color as [r, g, b] in 0-1 range. |
| smokeColor | [number, number, number] | [1, 0.43, 0.1] | Smoke and glow color as [r, g, b] in 0-1 range. |
| className | string |  | Classes applied to the wrapper element. |

## Blaze.tsx

```tsx
"use client";

import {
  useEffect,
  useRef,
  useState,
  useSyncExternalStore,
  type ReactNode,
} from "react";

export interface BlazeOptions {
  /** Height of the blaze zone as a fraction of the screen (0 to 1). */
  height?: number;
  /** Strength of the heat distortion bending the content. */
  distortion?: number;
  /** Scale of the heat distortion noise. Higher means finer ripples. */
  distortionScale?: number;
  /** Animation speed multiplier for the whole effect. */
  speed?: number;
  /** Brightness of the rising sparks. 0 disables them. */
  sparks?: number;
  /** How tightly packed the sparks are. Higher also makes them smaller. */
  sparkDensity?: number;
  /** Size of the individual sparks. */
  sparkSize?: number;
  /** Number of spark layers stacked for depth (1 to 10). */
  layers?: number;
  /** Intensity of the smoke. 0 disables it. */
  smoke?: number;
  /** Warm ambient glow near the bottom edge. */
  glow?: number;
  /** Spark color as [r, g, b] in 0-1 range. */
  sparkColor?: [number, number, number];
  /** Smoke and glow color as [r, g, b] in 0-1 range. */
  smokeColor?: [number, number, number];
}

export interface BlazeElements {
  /** Canvas with layoutsubtree that hosts the HTML content. */
  source: HTMLCanvasElement;
  /** The element inside the source canvas that gets captured. */
  content: HTMLElement;
  /** Canvas the WebGL effect renders to. */
  output: HTMLCanvasElement;
}

export interface BlazeInstance {
  /** Update effect options live. */
  setOptions: (options: BlazeOptions) => void;
  /** Re-read canvas size. Call when the element is resized. */
  resize: () => void;
  /** Stop the loop and release all GPU resources. */
  destroy: () => void;
}

const DEFAULTS: Required<BlazeOptions> = {
  height: 0.97,
  distortion: 0.6,
  distortionScale: 0.5,
  speed: 1,
  sparks: 0.5,
  sparkDensity: 1.5,
  sparkSize: 1,
  layers: 4,
  smoke: 0.5,
  glow: 1.5,
  sparkColor: [1, 0.4, 0.05],
  smokeColor: [1, 0.43, 0.1],
};

type PaintableCanvas = HTMLCanvasElement & {
  onpaint?: (() => void) | null;
  requestPaint?: () => void;
};

type ElementImageContext = CanvasRenderingContext2D & {
  drawElementImage?: (element: Element, x: number, y: number) => void;
};

const VERT = `#version 300 es
precision highp float;
layout(location = 0) in vec2 aPos;
out vec2 vUv;
void main () {
  vUv = aPos * 0.5 + 0.5;
  gl_Position = vec4(aPos, 0.0, 1.0);
}`;

const NOISE = `
float hash1_2 (vec2 x) {
  return fract(sin(dot(x, vec2(52.127, 61.2871))) * 521.582);
}

vec2 hash2_2 (vec2 x) {
  return fract(sin(x * mat2(20.52, 24.1994, 70.291, 80.171)) * 492.194);
}

vec2 noise2_2 (vec2 uv) {
  vec2 f = smoothstep(0.0, 1.0, fract(uv));
  vec2 uv00 = floor(uv);
  vec2 v00 = hash2_2(uv00);
  vec2 v01 = hash2_2(uv00 + vec2(0.0, 1.0));
  vec2 v10 = hash2_2(uv00 + vec2(1.0, 0.0));
  vec2 v11 = hash2_2(uv00 + 1.0);
  return mix(mix(v00, v01, f.y), mix(v10, v11, f.y), f.x);
}

vec3 permute (vec3 x) { return mod(((x * 34.0) + 1.0) * x, 289.0); }

float snoise (vec2 v) {
  const vec4 C = vec4(0.211324865405187, 0.366025403784439,
    -0.577350269189626, 0.024390243902439);
  vec2 i = floor(v + dot(v, C.yy));
  vec2 x0 = v - i + dot(i, C.xx);
  vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
  vec4 x12 = x0.xyxy + C.xxzz;
  x12.xy -= i1;
  i = mod(i, 289.0);
  vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
  vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
  m = m * m;
  m = m * m;
  vec3 x = 2.0 * fract(p * C.www) - 1.0;
  vec3 h = abs(x) - 0.5;
  vec3 ox = floor(x + 0.5);
  vec3 a0 = x - ox;
  m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
  vec3 g;
  g.x = a0.x * x0.x + h.x * x0.y;
  g.yz = a0.yz * x12.xz + h.yz * x12.yw;
  return 130.0 * dot(m, g);
}`;

const FIRE_FRAG = `#version 300 es
precision highp float;
in vec2 vUv;
out vec4 outColor;
uniform vec2 uResolution;
uniform float uTime;
uniform float uHeight;
uniform float uSparks;
uniform float uSparkDensity;
uniform float uSparkSize;
uniform int uLayers;
uniform float uSmoke;
uniform float uGlow;
uniform vec3 uSparkColor;
uniform vec3 uSmokeColor;

#define MOVE_DIR vec2(0.0, -1.0)
#define MOVE_SPEED 0.5
${NOISE}

float fbm (vec2 p) {
  float v = 0.0;
  float a = 0.5;
  for (int i = 0; i < 3; i++) {
    v += a * snoise(p);
    p = mat2(1.6, 1.2, -1.2, 1.6) * p + 11.7;
    a *= 0.5;
  }
  return v * 0.5 + 0.5;
}

float smokeField (vec2 p, float t) {
  vec2 rise = vec2(-t * 0.03, -t * 0.22);
  vec2 q = vec2(
    fbm(p + rise),
    fbm(p + rise * 0.85 + vec2(5.2, 1.3)));
  return fbm(p + 0.55 * q + rise);
}

vec2 rotate2 (vec2 point, float deg) {
  float s = sin(deg);
  float c = cos(deg);
  return mat2(s, c, -c, s) * point;
}

vec2 voronoiPoint (vec2 root, float deg) {
  vec2 point = hash2_2(root) - 0.5;
  float s = sin(deg);
  float c = cos(deg);
  point = mat2(s, c, -c, s) * point * 0.66;
  point += root + 0.5;
  return point;
}

vec2 randomAround (vec2 point, vec2 range, vec2 uv) {
  return point + (hash2_2(uv) - 0.5) * range;
}

vec3 fireParticles (vec2 uv, vec2 originalUV) {
  vec3 particles = vec3(0.0);
  vec2 rootUV = floor(uv);
  float deg = uTime * 0.6 * (hash1_2(rootUV) - 0.5) * 2.0;
  vec2 pointUV = voronoiPoint(rootUV, deg);
  float size = 0.002 * uSparkSize;

  vec2 tempUV = uv + vec2(
    snoise(uv * 1.8 + uTime * 0.55),
    snoise(uv * 1.8 - uTime * 0.4 + 7.3)) * 0.06;

  float dist = length(rotate2(tempUV - pointUV, 0.7)
    * randomAround(vec2(0.5, 1.6), vec2(0.25, 0.2), rootUV));
  float distBloom = length(rotate2(tempUV - pointUV, 0.7)
    * randomAround(vec2(0.5, 0.8), vec2(0.3, 0.1), rootUV));

  particles += (1.0 - smoothstep(size * 0.6, size * 3.0, dist)) * uSparkColor * 1.5;
  particles += pow(1.0 - smoothstep(0.0, size * 6.0, distBloom), 3.0) * uSparkColor * 0.8;

  float border = (hash1_2(rootUV) - 0.5) * 2.0;
  float disappear = 1.0 - smoothstep(border, border + 0.5, originalUV.y);
  border = (hash1_2(rootUV + 0.214) - 1.8) * 0.7;
  float appear = smoothstep(border, border + 0.4, originalUV.y);

  return particles * disappear * appear;
}

vec3 layeredParticles (vec2 uv, float sizeMod, float alphaMod, int layers, float smoke) {
  vec3 particles = vec3(0.0);
  float size = 1.0;
  float alpha = 1.0;
  vec2 offset = vec2(0.0);
  for (int i = 0; i < layers; i++) {
    vec2 noiseOffset = (noise2_2(uv * size * 2.0 + 0.5) - 0.5) * 0.15;
    vec2 bokehUV = (uv * size * uSparkDensity + uTime * MOVE_DIR * MOVE_SPEED)
      + offset + noiseOffset;
    particles += fireParticles(bokehUV, uv) * alpha
      * (1.0 - smoothstep(0.0, 1.0, smoke) * (float(i) / float(layers)));
    offset += hash2_2(vec2(alpha, alpha)) * 10.0;
    alpha *= alphaMod;
    size *= sizeMod;
  }
  return particles;
}

void main () {
  vec2 uv = vUv;

  float zone = clamp(uHeight, 0.02, 1.0);
  float fy = uv.y / zone;

  if (fy > 1.0) {
    outColor = vec4(0.0);
    return;
  }

  float aspect = uResolution.x / uResolution.y;
  vec2 fireUv = vec2((uv.x - 0.5) * aspect * 3.2, mix(-0.7, 1.6, fy));

  float smokeIntensity = 0.0;
  if (uSmoke > 0.001) {
    smokeIntensity = smokeField(fireUv * vec2(0.4, 0.55), uTime);
    smokeIntensity = smoothstep(0.42, 1.15, smokeIntensity);
    smokeIntensity *= pow(1.0 - smoothstep(-1.0, 1.6, fireUv.y), 1.5);
  }
  vec3 smoke = smokeIntensity * uSmokeColor * 0.8 * uSmoke;

  vec3 particles = vec3(0.0);
  if (uSparks > 0.001) {
    particles = layeredParticles(fireUv, 1.01, 0.9, uLayers, smokeIntensity) * uSparks;
  }

  float fade = 1.0 - smoothstep(0.55, 1.0, fy);
  vec3 glow = uSmokeColor * 0.05 * uGlow * pow(1.0 - fy, 2.0);
  vec3 fire = (particles + smoke) * fade + glow;

  outColor = vec4(fire, max(fire.r, max(fire.g, fire.b)));
}`;

const FRAG = `#version 300 es
precision highp float;
in vec2 vUv;
out vec4 outColor;
uniform sampler2D uContent;
uniform sampler2D uFire;
uniform float uTime;
uniform float uHeight;
uniform float uDistortion;
uniform float uDistortionScale;
uniform float uMaxX;
uniform float uHasContent;
${NOISE}

float snoiseOctaves (vec2 uv, int octaves, float alpha, float beta, vec2 gamma, float delta) {
  vec2 pos = uv;
  float t = 1.0;
  float s = 1.0;
  vec2 q = gamma;
  float r = 0.0;
  for (int i = 0; i < octaves; i++) {
    r += s * snoise(pos + q);
    pos += t * uv;
    t *= beta;
    s *= alpha;
    q *= delta;
  }
  return r;
}

void main () {
  vec2 uv = vUv;

  if (uv.x > uMaxX) {
    outColor = vec4(0.0);
    return;
  }

  float zone = clamp(uHeight, 0.02, 1.0);
  float fy = uv.y / zone;

  if (uHasContent < 0.5) {
    if (fy > 1.0) {
      outColor = vec4(0.0);
      return;
    }
    vec4 fire = texture(uFire, uv);
    outColor = vec4(fire.rgb, clamp(fire.a * 0.85, 0.0, 1.0));
    return;
  }

  if (fy > 1.0) {
    vec4 c = texture(uContent, vec2(uv.x, 1.0 - uv.y));
    outColor = vec4(c.rgb * c.a, c.a);
    return;
  }

  float heat = uDistortion * pow(1.0 - smoothstep(0.0, 1.0, fy), 1.5);
  vec2 uv1 = uv;
  if (heat > 0.0005) {
    vec2 nUv = uv * 2.0 * uDistortionScale;
    float dx = 0.005 * snoiseOctaves(nUv + uTime * vec2(0.00323, 0.00345),
      4, 0.85, -3.0, uTime * vec2(-0.0323, -0.345), 1.203);
    float dy = 0.0035 * snoiseOctaves(nUv + 3.0 + uTime * vec2(-0.00323, 0.00345),
      4, 0.85, -3.0, uTime * vec2(-0.0323, -0.345), 1.203);
    uv1 = clamp(uv + vec2(dx, dy) * heat, vec2(0.001), vec2(uMaxX - 0.004, 0.999));
  }
  vec4 content = texture(uContent, vec2(uv1.x, 1.0 - uv1.y));

  vec4 fire = texture(uFire, uv);

  float luma = dot(content.rgb, vec3(0.299, 0.587, 0.114)) * content.a;
  vec3 col = content.rgb * content.a * (1.0 - fire.a * luma) + fire.rgb;
  float alpha = clamp(content.a + fire.a, 0.0, 1.0);
  outColor = vec4(col, alpha);
}`;

export function supportsHtmlInCanvas(): boolean {
  if (typeof document === "undefined") return false;
  const probe = document.createElement("canvas") as PaintableCanvas;
  const ctx = probe.getContext("2d") as ElementImageContext | null;
  return Boolean(
    ctx &&
    typeof ctx.drawElementImage === "function" &&
    typeof probe.requestPaint === "function",
  );
}

export function createBlaze(
  elements: BlazeElements,
  options: BlazeOptions = {},
): BlazeInstance | null {
  const config = { ...DEFAULTS, ...options };
  const { source, content, output } = elements;

  const gl = output.getContext("webgl2", {
    alpha: true,
    depth: false,
    stencil: false,
    antialias: false,
    premultipliedAlpha: true,
  });
  if (!gl || gl.isContextLost()) return null;

  const sourceCtx = source.getContext("2d") as ElementImageContext | null;
  const paintable = source as PaintableCanvas;
  const htmlInCanvas = Boolean(
    sourceCtx &&
    typeof sourceCtx.drawElementImage === "function" &&
    typeof paintable.requestPaint === "function",
  );

  let contentDirty = false;
  let wake = () => {};

  if (htmlInCanvas) {
    paintable.onpaint = () => {
      try {
        sourceCtx!.reset();
        sourceCtx!.drawElementImage!(content, 0, 0);
        contentDirty = true;
        wake();
      } catch {}
    };
  }

  function compile(type: number, text: string): WebGLShader {
    const shader = gl!.createShader(type)!;
    gl!.shaderSource(shader, text);
    gl!.compileShader(shader);
    if (!gl!.getShaderParameter(shader, gl!.COMPILE_STATUS)) {
      console.error("Blaze shader error:", gl!.getShaderInfoLog(shader));
    }
    return shader;
  }

  function link(fragText: string) {
    const vertexShader = compile(gl!.VERTEX_SHADER, VERT);
    const fragmentShader = compile(gl!.FRAGMENT_SHADER, fragText);
    const program = gl!.createProgram()!;
    gl!.attachShader(program, vertexShader);
    gl!.attachShader(program, fragmentShader);
    gl!.linkProgram(program);
    const uniforms: Record<string, WebGLUniformLocation> = {};
    const count = gl!.getProgramParameter(program, gl!.ACTIVE_UNIFORMS);
    for (let i = 0; i < count; i++) {
      const info = gl!.getActiveUniform(program, i)!;
      uniforms[info.name] = gl!.getUniformLocation(program, info.name)!;
    }
    return { program, uniforms, vertexShader, fragmentShader };
  }

  const mainPass = link(FRAG);
  const firePass = link(FIRE_FRAG);

  const quad = gl.createBuffer();
  gl.bindBuffer(gl.ARRAY_BUFFER, quad);
  gl.bufferData(
    gl.ARRAY_BUFFER,
    new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]),
    gl.STATIC_DRAW,
  );
  gl.enableVertexAttribArray(0);
  gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 0, 0);

  const contentTexture = gl.createTexture()!;
  gl.bindTexture(gl.TEXTURE_2D, contentTexture);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  gl.texImage2D(
    gl.TEXTURE_2D,
    0,
    gl.RGBA,
    1,
    1,
    0,
    gl.RGBA,
    gl.UNSIGNED_BYTE,
    new Uint8Array([0, 0, 0, 0]),
  );

  let contentMaxX = 1;

  let fireTexture: WebGLTexture | null = null;
  let fireFbo: WebGLFramebuffer | null = null;
  let fireWidth = 0;
  let fireHeight = 0;

  function ensureFireTarget() {
    const width = Math.max(1, Math.floor(output.width / 2));
    const height = Math.max(1, Math.floor(output.height / 2));
    if (fireTexture && width === fireWidth && height === fireHeight) return;
    fireWidth = width;
    fireHeight = height;
    if (fireTexture) gl!.deleteTexture(fireTexture);
    if (fireFbo) gl!.deleteFramebuffer(fireFbo);
    fireTexture = gl!.createTexture()!;
    gl!.bindTexture(gl!.TEXTURE_2D, fireTexture);
    gl!.texParameteri(gl!.TEXTURE_2D, gl!.TEXTURE_MIN_FILTER, gl!.LINEAR);
    gl!.texParameteri(gl!.TEXTURE_2D, gl!.TEXTURE_MAG_FILTER, gl!.LINEAR);
    gl!.texParameteri(gl!.TEXTURE_2D, gl!.TEXTURE_WRAP_S, gl!.CLAMP_TO_EDGE);
    gl!.texParameteri(gl!.TEXTURE_2D, gl!.TEXTURE_WRAP_T, gl!.CLAMP_TO_EDGE);
    gl!.texImage2D(
      gl!.TEXTURE_2D,
      0,
      gl!.RGBA,
      width,
      height,
      0,
      gl!.RGBA,
      gl!.UNSIGNED_BYTE,
      null,
    );
    fireFbo = gl!.createFramebuffer()!;
    gl!.bindFramebuffer(gl!.FRAMEBUFFER, fireFbo);
    gl!.framebufferTexture2D(
      gl!.FRAMEBUFFER,
      gl!.COLOR_ATTACHMENT0,
      gl!.TEXTURE_2D,
      fireTexture,
      0,
    );
    gl!.bindFramebuffer(gl!.FRAMEBUFFER, null);
  }

  function syncCanvasSize() {
    const dpr = Math.min(window.devicePixelRatio || 1, 2);
    const width = Math.max(1, Math.round(output.clientWidth * dpr));
    const height = Math.max(1, Math.round(output.clientHeight * dpr));
    if (output.width !== width || output.height !== height) {
      output.width = width;
      output.height = height;
    }
    contentMaxX = Math.min(
      1,
      Math.max(0.05, content.clientWidth / Math.max(output.clientWidth, 1)),
    );
    if (htmlInCanvas) {
      const cssWidth = Math.max(1, Math.round(source.clientWidth));
      const cssHeight = Math.max(1, Math.round(source.clientHeight));
      if (source.width !== cssWidth * dpr || source.height !== cssHeight * dpr) {
        source.width = cssWidth * dpr;
        source.height = cssHeight * dpr;
      }
      paintable.requestPaint!();
    }
  }

  syncCanvasSize();

  function uploadContent() {
    if (!htmlInCanvas || !contentDirty) return;
    contentDirty = false;
    gl!.bindTexture(gl!.TEXTURE_2D, contentTexture);
    gl!.texImage2D(
      gl!.TEXTURE_2D,
      0,
      gl!.RGBA,
      gl!.RGBA,
      gl!.UNSIGNED_BYTE,
      source,
    );
  }

  let time = 0;

  function render() {
    uploadContent();
    ensureFireTarget();

    gl!.useProgram(firePass.program);
    gl!.uniform2f(firePass.uniforms.uResolution, output.width, output.height);
    gl!.uniform1f(firePass.uniforms.uTime, time);
    gl!.uniform1f(firePass.uniforms.uHeight, config.height);
    gl!.uniform1f(firePass.uniforms.uSparks, config.sparks);
    gl!.uniform1f(
      firePass.uniforms.uSparkDensity,
      Math.max(config.sparkDensity, 0.05),
    );
    gl!.uniform1f(
      firePass.uniforms.uSparkSize,
      Math.max(config.sparkSize, 0.05),
    );
    gl!.uniform1i(
      firePass.uniforms.uLayers,
      Math.min(Math.max(Math.round(config.layers), 1), 10),
    );
    gl!.uniform1f(firePass.uniforms.uSmoke, config.smoke);
    gl!.uniform1f(firePass.uniforms.uGlow, config.glow);
    gl!.uniform3f(
      firePass.uniforms.uSparkColor,
      config.sparkColor[0],
      config.sparkColor[1],
      config.sparkColor[2],
    );
    gl!.uniform3f(
      firePass.uniforms.uSmokeColor,
      config.smokeColor[0],
      config.smokeColor[1],
      config.smokeColor[2],
    );
    gl!.bindFramebuffer(gl!.FRAMEBUFFER, fireFbo);
    gl!.viewport(0, 0, fireWidth, fireHeight);
    gl!.drawArrays(gl!.TRIANGLE_STRIP, 0, 4);

    gl!.useProgram(mainPass.program);
    gl!.activeTexture(gl!.TEXTURE0);
    gl!.bindTexture(gl!.TEXTURE_2D, contentTexture);
    gl!.uniform1i(mainPass.uniforms.uContent, 0);
    gl!.activeTexture(gl!.TEXTURE1);
    gl!.bindTexture(gl!.TEXTURE_2D, fireTexture);
    gl!.uniform1i(mainPass.uniforms.uFire, 1);
    gl!.activeTexture(gl!.TEXTURE0);
    gl!.uniform1f(mainPass.uniforms.uTime, time);
    gl!.uniform1f(mainPass.uniforms.uHeight, config.height);
    gl!.uniform1f(mainPass.uniforms.uDistortion, config.distortion);
    gl!.uniform1f(
      mainPass.uniforms.uDistortionScale,
      Math.max(config.distortionScale, 0.05),
    );
    gl!.uniform1f(mainPass.uniforms.uMaxX, contentMaxX);
    gl!.uniform1f(mainPass.uniforms.uHasContent, htmlInCanvas ? 1 : 0);
    gl!.bindFramebuffer(gl!.FRAMEBUFFER, null);
    gl!.viewport(0, 0, output.width, output.height);
    gl!.drawArrays(gl!.TRIANGLE_STRIP, 0, 4);
  }

  let raf = 0;
  let lastTime = performance.now();
  let destroyed = false;
  let running = false;
  let visible = true;

  const motionQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
  let reducedMotion = motionQuery.matches;

  function frame(now: number) {
    if (destroyed) return;
    if (!visible) {
      running = false;
      return;
    }
    const delta = Math.min((now - lastTime) / 1000, 1 / 30);
    lastTime = now;
    if (!reducedMotion) time += delta * config.speed;
    render();
    if (reducedMotion && !contentDirty) {
      running = false;
      return;
    }
    raf = requestAnimationFrame(frame);
  }

  function start() {
    if (destroyed || running || !visible) return;
    running = true;
    lastTime = performance.now();
    raf = requestAnimationFrame(frame);
  }

  wake = start;
  start();

  function onMotionChange() {
    reducedMotion = motionQuery.matches;
    start();
  }
  motionQuery.addEventListener("change", onMotionChange);

  const observer = new ResizeObserver(() => {
    syncCanvasSize();
    start();
  });
  observer.observe(output);
  observer.observe(content);

  const intersection = new IntersectionObserver((entries) => {
    visible = entries[entries.length - 1]?.isIntersecting ?? true;
    if (visible) start();
  });
  intersection.observe(output);

  return {
    setOptions(next) {
      if (
        !Object.entries(next).some(
          ([key, value]) => config[key as keyof BlazeOptions] !== value,
        )
      )
        return;
      Object.assign(config, next);
      start();
    },
    resize() {
      syncCanvasSize();
      start();
    },
    destroy() {
      destroyed = true;
      cancelAnimationFrame(raf);
      observer.disconnect();
      intersection.disconnect();
      motionQuery.removeEventListener("change", onMotionChange);
      gl!.deleteTexture(contentTexture);
      if (fireTexture) gl!.deleteTexture(fireTexture);
      if (fireFbo) gl!.deleteFramebuffer(fireFbo);
      for (const pass of [mainPass, firePass]) {
        gl!.deleteProgram(pass.program);
        gl!.deleteShader(pass.vertexShader);
        gl!.deleteShader(pass.fragmentShader);
      }
      gl!.deleteBuffer(quad);
      if (htmlInCanvas) paintable.onpaint = null;
    },
  };
}

export interface BlazeProps extends BlazeOptions {
  children: ReactNode;
  className?: string;
  style?: React.CSSProperties;
}

const emptySubscribe = () => () => {};

export function Blaze({ children, className, style, ...options }: BlazeProps) {
  const sourceRef = useRef<HTMLCanvasElement>(null);
  const contentRef = useRef<HTMLDivElement>(null);
  const outputRef = useRef<HTMLCanvasElement>(null);
  const instanceRef = useRef<BlazeInstance | null>(null);
  const [initialOptions] = useState(options);
  const [failed, setFailed] = useState(false);

  const supported = useSyncExternalStore(
    emptySubscribe,
    supportsHtmlInCanvas,
    () => false,
  );
  const native = supported && !failed;

  useEffect(() => {
    const source = sourceRef.current;
    const content = contentRef.current;
    const output = outputRef.current;
    if (!source || !content || !output) return;
    instanceRef.current = createBlaze(
      { source, content, output },
      initialOptions,
    );
    if (native && !instanceRef.current) setFailed(true);
    return () => {
      instanceRef.current?.destroy();
      instanceRef.current = null;
    };
  }, [initialOptions, native]);

  useEffect(() => {
    instanceRef.current?.setOptions(options);
  });

  return (
    <div className={className} style={{ position: "relative", ...style }}>
      <canvas
        ref={sourceRef}
        // @ts-expect-error experimental html-in-canvas attribute
        layoutsubtree="true"
        suppressHydrationWarning
        style={
          native
            ? { position: "absolute", inset: 0, width: "100%", height: "100%" }
            : { display: "none" }
        }
      >
        {native ? (
          <div
            ref={contentRef}
            style={{
              position: "relative",
              width: "100%",
              height: "100%",
              overflow: "auto",
            }}
          >
            {children}
          </div>
        ) : null}
      </canvas>
      {!native ? (
        <div
          ref={contentRef}
          style={{
            position: "relative",
            width: "100%",
            height: "100%",
            overflow: "auto",
          }}
        >
          {children}
        </div>
      ) : null}
      <canvas
        ref={outputRef}
        aria-hidden
        style={{
          position: "absolute",
          inset: 0,
          width: "100%",
          height: "100%",
          pointerEvents: "none",
        }}
      />
    </div>
  );
}


export default Blaze;
```
The atelier / 27 saved prompts

The art of the cards

Saved image-generation prompts, including earlier explorations.

Method: Codex built-in image_gen. Requested model: GPT Image 2.5. Actual model: not exposed by the built-in tool.

Silver HunterProject asset

Original prompt did not produce a deliverable. This revised prompt produced the final card.

Image generation prompt
Create a premium fantasy trading card illustration of an original fictional character called SILVER HUNTER: a noble adult ranger with silver-gray tied-back hair, weathered face, dark leather armor with ornate silver clasps, and a raven-black fur cloak, shown from waist up in three-quarter portrait against a misty blue mountain fortress. It is a collectible card, front-on orthographic flat view, portrait 2:3. Intricate antique-silver and gold carved border with cyan gemstones and a small blue heraldic shield at top left. Title panel at bottom reads exactly SILVER HUNTER, smaller subtitle HUMAN · CHAMPION, stat diamond bottom left reads 4, stat shield bottom right reads 7. Highly detailed hand-painted fantasy illustration with subdued cinematic blue and charcoal palette, elegant realistic engraved card UI. Keep the full card within the canvas, slightly clipped corners, small transparent outer margin. Genuine transparent PNG background outside the card. The card interior is opaque. No extra objects or watermark.
Frost MageProject asset

Image generation prompt
Use case: stylized-concept. Asset: final front-facing texture for a premium dark fantasy collectible card in a Three.js landing page. Generate ONE card, portrait aspect ratio 2:3, perfectly straight orthographic front view with parallel vertical edges, absolutely no tilt or perspective. The card fills 96 percent of canvas with tiny transparent padding. Genuine alpha transparency outside its slightly clipped corners. The physical card itself is opaque. High-end Witcher-inspired painterly realism, incredibly detailed etched antique gold and silver frame, restrained cyan and iridescent gemstone accents, cinematic contrast, exquisite fantasy trading-card interface. Art fills upper 76 percent of the card. Bottom has integrated near-black name plate and stat medallions. Small faction shield at upper left. All text must be sharp and spelled exactly. No watermark, no extra cards, no hands holding card. Subject: a pale enigmatic female frost sorceress wearing a blue hood, black feather and fur shoulders, conjuring a brilliant icy blue magical orb in one hand. Frozen ruins and lightning behind her. Deep violet, ice blue and indigo palette, iridescent silver frame. Top shield purple with silver trident. Exact name: FROST MAGE. Exact type: HUMAN · SPELLCASTER. Bottom left stat 3 in diamond, bottom right stat 5 in shield.
Forest BehemothProject asset

Image generation prompt
Use case: stylized-concept. Asset: final front-facing texture for a premium dark fantasy collectible card in a Three.js landing page. Generate ONE card, portrait aspect ratio 2:3, perfectly straight orthographic front view with parallel vertical edges, absolutely no tilt or perspective. The card fills 96 percent of canvas with tiny transparent padding. Genuine alpha transparency outside its slightly clipped corners. The physical card itself is opaque. High-end Witcher-inspired painterly realism, incredibly detailed etched antique gold and silver frame, restrained cyan and iridescent gemstone accents, cinematic contrast, exquisite fantasy trading-card interface. Art fills upper 76 percent of the card. Bottom has integrated near-black name plate and stat medallions. Small faction shield at upper left. All text must be sharp and spelled exactly. No watermark, no extra cards, no hands holding card. Subject: a towering ancient forest spirit with a fierce elk skull-like wooden face, luminous emerald eyes, massive branching antlers, bark and moss body, twisted roots. Ancient woodland, shafts of morning light. Moss green, deep emerald and antique brass palette. Top shield emerald with leaf crest. Exact name: FOREST BEHEMOTH. Exact type: BEAST. Bottom left stat 6 in diamond, bottom right stat 8 in shield.
War CaptainProject asset

Image generation prompt
Use case: stylized-concept. Asset: final front-facing texture for a premium dark fantasy collectible card in a Three.js landing page. Generate ONE card, portrait aspect ratio 2:3, perfectly straight orthographic front view with parallel vertical edges, absolutely no tilt or perspective. The card fills 96 percent of canvas with tiny transparent padding. Genuine alpha transparency outside its slightly clipped corners. The physical card itself is opaque. High-end Witcher-inspired painterly realism, incredibly detailed etched antique gold and silver frame, restrained cyan and iridescent gemstone accents, cinematic contrast, exquisite fantasy trading-card interface. Art fills upper 76 percent of the card. Bottom has integrated near-black name plate and stat medallions. Small faction shield at upper left. All text must be sharp and spelled exactly. No watermark, no extra cards, no hands holding card. Subject: a stern battle-scarred male war captain with short dark hair and a beard, blackened steel armor and dark fur collar, embers in the air, crimson battle banners behind him. Charcoal, burnt red, bronze and dark crimson palette. Top shield red with silver trident. Exact name: WAR CAPTAIN. Exact type: HUMAN · WARRIOR. Bottom left stat 5 in diamond, bottom right stat 7 in shield.
Ancient RelicProject asset

Image generation prompt
Use case: stylized-concept. Asset: final front-facing texture for a premium dark fantasy collectible card in a Three.js landing page. Generate ONE card, portrait aspect ratio 2:3, perfectly straight orthographic front view with parallel vertical edges, absolutely no tilt or perspective. The card fills 96 percent of canvas with tiny transparent padding. Genuine alpha transparency outside its slightly clipped corners. The physical card itself is opaque. High-end Witcher-inspired painterly realism, incredibly detailed etched antique gold and silver frame, restrained cyan and iridescent gemstone accents, cinematic contrast, exquisite fantasy trading-card interface. Art fills upper 76 percent of the card. Bottom has integrated near-black name plate and stat medallions. Small faction shield at upper left. All text must be sharp and spelled exactly. No watermark, no extra cards, no hands holding card. Subject: a magical ancient golden armillary ring, floating and rotating around an inner bright sapphire crystal above a weathered stone altar in a forgotten dark forest temple, swirling magical pale gold and azure filaments. Deep teal and antique gold palette, very ornate golden frame. Top shield gold with sun symbol. Exact name: ANCIENT RELIC. Exact type: ARTIFACT. Bottom left stat 0 in diamond, bottom right stat 4 in shield.
World BackgroundEarlier exploration

Image generation prompt
Use case: stylized-concept. Asset type: full-bleed background for a dark fantasy card-game landing page, landscape 16:9, high resolution. Create an exquisitely detailed cinematic painted northern fantasy landscape at blue hour: immense jagged obsidian mountains left, a tall Gothic fortress on cliffs on the far right with a few tiny turquoise windows, deep shadowy valley in the middle, low atmospheric fog, layered cliffs in foreground bottom corners, stormy cloudy sky. Rich near-black navy and cold slate, subtle desaturated cyan highlights. The TOP CENTER and entire central area must be quiet, dark atmospheric negative space for headlines and floating trading cards to be overlaid in code. Moody and sophisticated, natural realistic painting, not neon. No cards, no characters, no typography, no UI, no logos. Opaque full canvas landscape.
Hunt CrestProject asset

Image generation prompt
Use case: stylized-concept. Create ONE isolated ornate dark fantasy trident crest as a PNG with genuine alpha transparency, square aspect ratio. An elegant elongated three-pronged heraldic sigil, sharp stylized silver spear prongs with symmetrical angular dark metal wings, polished cyan gemstones and tiny lavender iridescent bevels. High-end fantasy game interface ornament, restrained delicate engraved metal detail. Front facing, centered, self-contained emblem occupying 85 percent of canvas, generous empty space around silhouette. Everything outside the metal and all openings between prongs must be transparent. No painted checkerboard, solid backdrop, scene, floor or rectangular shadow. No text, no letters, no extra objects. Useful as a navigation logo and central interface decoration.
Distant WorldEarlier exploration

An existing project image was supplied as a reference.

Image generation prompt
Create the far background plate for a layered parallax version of this exact dark fantasy landscape. Preserve the cold blue-hour painterly realistic style and beautiful distant jagged mountains on the left, misty valley and clouded sky. REMOVE the entire castle, all man-made towers and the close foreground rocks at the bottom corners. Replace those areas with distant atmospheric mountains and valley fog. No cliffs close to the viewer. Wide 16:9 landscape, maximum native resolution, beautifully sharp fine details in the distant peaks, no pixelation. Keep the central sky quiet dark negative space. Opaque full image. This is only the distant sky and mountain layer, other layers will be separate.
Castle LayerProject asset

An existing project image was supplied as a reference.

Image generation prompt
Extract and recreate the magnificent Gothic castle from the RIGHT of this image as ONE standalone cutout asset on a genuinely transparent PNG background. Castle on its own jagged rocky foundation, front three-quarter view, slender spires, intricate realistic architecture, very small muted cyan windows. Match the image's dark slate blue-hour cinematic painterly realism. Entire castle and rock foundation must be visible, no cropping of spires. Portrait-ish 4:5 composition, maximum sharp native resolution. Genuine alpha outside the silhouette including between spires. No sky, no clouds, no distant mountains, no flat background or shadow rectangle. No glow, no flare, no typography. High quality transparent PNG layer for Three.js parallax.
Cliff LeftProject asset

An existing project image was supplied as a reference.

Image generation prompt
Create ONE isolated foreground cliff cutout matching the near bottom LEFT rocks in this reference fantasy landscape. Wide landscape 3:2. A dark jagged rocky ledge rising on the left and sloping downward toward the right, scant frost and two tiny windswept conifers, intricate sharp natural slate texture and restrained blue-gray moonlight. The bottom edge of the rock meets the bottom canvas edge; left edge meets left canvas edge. Everything above and to the right of the craggy silhouette is genuine PNG alpha transparency. No sky, no distant mountains, no castle, no backdrop, no glow, no text. This is a foreground layer to overlay a separate landscape, dark realistic cinematic painting, maximum native detail.
Cliff RightProject asset

An existing project image was supplied as a reference.

Image generation prompt
Create ONE isolated foreground cliff cutout matching the near bottom RIGHT rocks in this reference fantasy landscape. Wide landscape 3:2. A dark jagged rocky ledge rising on the right and sloping downward toward the left, scant frost and three tiny windswept conifers, intricate sharp natural slate texture and restrained blue-gray moonlight. The bottom edge of the rock meets the bottom canvas edge; right edge meets right canvas edge. Everything above and to the left of the craggy silhouette is genuine PNG alpha transparency. No sky, no distant mountains, no castle, no backdrop, no glow, no text. This is a foreground layer to overlay a separate landscape, dark realistic cinematic painting, maximum native detail.
Card BackProject asset

An existing project image was supplied as a reference.

Image generation prompt
Create ONE exquisite collectible fantasy card BACK using this silver trident crest as the central embossed symbol. Straight orthographic front view, portrait 2:3, precisely parallel edges, no perspective, 1024x1536 or maximum native resolution. Entire card visible with only tiny 3 percent transparent margin. Elaborate engraved silver and antique gold double border with angular clipped corners, restrained cyan gemstones, black-navy embossed leather interior with very subtle filigree. Central crest elegant, no bright white light or flare. Sharp real material detail, refined dark fantasy craftsmanship, consistent premium trading card style. Card interior fully opaque; genuine PNG alpha outside its shaped outer edge. No words, numbers, labels, extra cards, fingers, background, floor, shadow rectangle, glow halo or checkerboard.
Header OrnamentProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE horizontal pointed navigation end ornament, a silver spear diamond on the far left with delicate symmetrical silver filigree wings reaching right into a fine horizontal line. Landscape 3:1 aspect. The ornament should be slender and graceful, occupying the middle 60 percent of the image height. Transparent openings within the metal. Made for a 150px wide header edge ornament that can be mirrored. No solid panel.
Button PrimaryProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE wide horizontal fantasy button frame with pointed chamfered ends and elegantly engraved metal edges. Width-to-height ratio 4:1. Muted dark petrol-teal interior, very fine antique silver double border with tiny cyan diamonds at both ends, almost no glow. Leave the center completely blank and visually quiet for a live HTML label. Occupy 95 percent of canvas width and 85 percent height. Genuine transparency outside the shaped frame. Perfectly front facing, no perspective. The single button is an opaque teal panel inside an ornamental metal border.
Button SecondaryProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE wide horizontal fantasy button OUTLINE frame with pointed chamfered ends and elegantly engraved metal edges. Width-to-height ratio 4:1. Very fine antique silver double border with tiny muted cyan diamonds at both ends, no glow. The entire central rectangular opening must be genuine alpha transparent, as must the exterior of the shape. There is no filled interior. Occupy 95 percent of canvas width and 85 percent height. Perfectly front facing, no perspective. This is a hollow frame to overlay a dark page with live HTML text inside.
Faction NorthernProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE heraldic shield icon for the NORTHERN REALMS faction: a sculpted silver fleur-de-lis on a rich desaturated sapphire blue enamel shield with finely engraved silver rim and a small silver crown on top. Shield perfectly front facing centered square composition, fills 86 percent of canvas, balanced and clearly recognizable at 40px. No background. Noble cold northern kingdom design. Keep metal subdued with readable bevels, no light flare.
Faction WildProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE heraldic shield icon for the WILD COURTS faction: a sculpted brass stag head with branching antlers on a dark forest emerald green enamel shield with finely engraved silver and antique brass rim. Shield perfectly front facing centered square composition, fills 86 percent of canvas, balanced and clearly recognizable at 40px. No background. Ancient woodland kingdom design. Keep metal subdued with readable bevels, no light flare.
Faction AshenProject asset

An existing project image was supplied as a reference.

Image generation prompt
Generate a single production fantasy game UI asset that matches the reference's finely engraved silver metal, restrained cyan gemstones, and dark navy elegance. Genuine transparent PNG alpha background and clean anti-aliased edges. No painted checkerboard, no drop shadow rectangle, no bright glow, no flare, no letters, words or numbers. Maximum native resolution, not a mockup or sprite sheet. ONE heraldic shield icon for the ASHEN LEGION faction: a sculpted three-pronged silver spear sigil on a dark oxblood crimson enamel shield with finely engraved blackened silver rim and small metal wing flourishes. Shield perfectly front facing centered square composition, fills 86 percent of canvas, balanced and clearly recognizable at 40px. No background. Severe warrior kingdom design. Keep metal subdued with readable bevels, no light flare.
Thorn OracleProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Wild Courts collection. Subject: a mysterious adult female forest oracle with a crown of thorn branches, pale olive skin, long silver hair, embroidered deep emerald robes, holding a small luminous jade seed. Misty ancient woodland behind her INSIDE the frame. Violet blossoms and fern details; emerald gems, leaf crest. Exact bottom text: 'THORN ORACLE', second line 'F AE / SEER' rendered as 'FAE / SEER'. Power badge '3', defense badge '6'. Portrait from waist up, readable face.
Moonfang StagProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Wild Courts collection. Subject: an imposing white stag spirit with luminous branching antlers, moss along its shoulders and sapphire eyes, in a moonlit fern forest INSIDE the card. Elegant animal anatomy, silver-blue moonlight, emerald gems and a leaf crest. Exact bottom text: 'MOONFANG STAG', second line 'BEAST / SPIRIT'. Power badge '5', defense badge '7'. Show the majestic head, antlers and upper body.
Briar WardenProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Wild Courts collection. Subject: an adult male woodland sentinel in dark bark armor and moss-covered bronze, antler-like helmet lifted to reveal a rugged face, holding a long thorn spear, autumn leaves and green-gold forest mist INSIDE the window. He is human-shaped, not a tree monster. Emerald gems, leaf crest. Exact bottom text: 'BRIAR WARDEN', second line 'FAE / GUARDIAN'. Power badge '4', defense badge '8'.
Ember PhoenixProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Exclusive closing collection. Subject: a magnificent phoenix with burnished copper and dark crimson feathers, a restrained luminous ember core and unfurled wings, flying above distant obsidian ruins INSIDE the card window. Strong elegant silhouette, no excessive fire bloom. Frame gold and blackened silver, small ruby insets, flame crest. Exact bottom text: 'EMBER PHOENIX', second line 'BEAST / MYTHIC'. Power badge '7', defense badge '5'.
Astral KnightProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Exclusive closing collection. Subject: an adult female celestial knight in polished blue-silver armor, a flowing midnight-blue cloak, silver hair, holding a vertical moonsteel sword, ruined observatory and a starry violet sky INSIDE the card. Rich finely detailed realism, sapphire jewels in silver-gold frame, star crest. Exact bottom text: 'ASTRAL KNIGHT', second line 'HUMAN / CHAMPION'. Power badge '6', defense badge '7'.
Veil WeaverProject asset

Image generation prompt
Create ONE isolated premium dark fantasy trading card as a PNG with genuine alpha transparency. Portrait 2:3, preferably 1024x1536. Straight-on orthographic view, no perspective tilt. Match the supplied reference's exquisite engraved antique-gold frame, jewel inset corners, crisp painted realism, printed bottom nameplate, bottom-left diamond power badge and bottom-right shield defense badge. The COMPLETE card occupies 91% of the canvas with 4% clear transparent padding all around; the ornamental silhouette may extend beyond its rectangular edges. All pixels outside the card MUST be truly transparent, no brown background, no scene behind the object, no painted checkerboard, no outer shadow, no watermark. Inside the card window is a detailed cinematic character illustration. Fine engraved metal, restrained highlights, realistic materials, legible serif lettering. This is a new collectible in the same family, NOT the reference creature. Exclusive closing collection. Subject: an enigmatic adult sorceress with dark hair and pale skin, wearing layered plum and indigo silks with a delicate silver mask over her eyes, weaving thin luminous violet threads between her hands, antique gothic library INSIDE the card window. Jewel-like amethyst accents in antique silver-gold frame, crescent crest. Exact bottom text: 'VEIL WEAVER', second line 'FAE / SPELLCASTER'. Power badge '4', defense badge '5'.
The Frozen ValeEarlier exploration

Returned image: 1672 × 941 pixels; requested 4K was not returned.

Image generation prompt
Create one finished panoramic dark-fantasy landscape background image for a premium collectible-card-game website. Output a native high-resolution 4K image, 3840 x 2160 pixels, 16:9 landscape, PNG. This must be a single independently usable landscape, not a contact sheet. Art direction: exceptionally detailed cinematic realistic environment matte painting, finely articulated geology, believable snow deposits, individual conifer silhouettes, naturally textured water, sophisticated dark navy and blue-gray grading that complements an ornate cold stone Gothic castle. The castle is a SEPARATE existing foreground layer and must NOT be painted into this image. No buildings, castle, towers, architecture, characters, creatures, playing cards, objects in the air, graphic elements, writing, logos, borders, or watermarks. Composition must work behind large ivory serif headline typography and a group of illustrated cards: keep the upper central 45% of the image mostly restrained, dark, spacious sky with subtle cloud gradation; never place a bright focal object behind the upper-center headline. Put the most interesting terrain in the left third and across the lower half. Allow the rightmost quarter to be covered by a separate castle without losing the landscape's visual story. Three spatial layers: highly resolved nearer terrain at the lower-left edge, middle-distance forest and water, distant layered peaks. Crisp real detail across the landscape, no global blur, no low-resolution mush, no noise grain, no oversharpening halos, no painterly smudging. Distance should read through subtle atmospheric color separation rather than a blur filter. Clouds and ground fog should be beautiful but restrained, since animated snow, particles, smoke and light rays will be added separately in Three.js. No baked falling snow or floating white speckles.
CONCEPT ONE — THE FROZEN VALE. An enormous glacial valley beneath an overcast winter dusk. On the far left, sharp black slate mountain needles with exquisite stratified rock faces and snow lodged on ledges; their profile slopes downward toward the open center. A winding steel-blue river travels from the lower-left foreground through dense frost-dusted evergreen forest into a far valley near center-right. Small islands and snowbanks articulate the water. Layer successive alpine ridges with restrained pale silver light low on the horizon. Foreground rock and firs should feel tangible, carved and precise, yet not compete with foreground game cards. The upper half is deep blue storm cloud, soft broad cloud shapes with silver edges confined toward the far-left and low horizon. Emotion: ancient, majestic, wintry, richly immersive. Quiet contrast and neutral moon-silver highlights, no obvious moon, no saturated aurora. Make this the faithful but much higher-detail evolution of a snowy fantasy mountain valley.
The Moonlit ReachEarlier exploration

Returned image: 1672 × 941 pixels; requested 4K was not returned.

Image generation prompt
Create one finished panoramic dark-fantasy landscape background image for a premium collectible-card-game website. Output a native high-resolution 4K image, 3840 x 2160 pixels, 16:9 landscape, PNG. This must be a single independently usable landscape, not a contact sheet. Art direction: exceptionally detailed cinematic realistic environment matte painting, finely articulated geology, believable snow deposits, individual conifer silhouettes, naturally textured water, sophisticated dark navy and blue-gray grading that complements an ornate cold stone Gothic castle. The castle is a SEPARATE existing foreground layer and must NOT be painted into this image. No buildings, castle, towers, architecture, characters, creatures, playing cards, objects in the air, graphic elements, writing, logos, borders, or watermarks. Composition must work behind large ivory serif headline typography and a group of illustrated cards: keep the upper central 45% of the image mostly restrained, dark, spacious sky with subtle cloud gradation; never place a bright focal object behind the upper-center headline. Put the most interesting terrain in the left third and across the lower half. Allow the rightmost quarter to be covered by a separate castle without losing the landscape's visual story. Three spatial layers: highly resolved nearer terrain at the lower-left edge, middle-distance forest and water, distant layered peaks. Crisp real detail across the landscape, no global blur, no low-resolution mush, no noise grain, no oversharpening halos, no painterly smudging. Distance should read through subtle atmospheric color separation rather than a blur filter. Clouds and ground fog should be beautiful but restrained, since animated snow, particles, smoke and light rays will be added separately in Three.js. No baked falling snow or floating white speckles.
CONCEPT TWO — THE MOONLIT REACH. A vast pristine mountain fjord at blue hour, with a slender silver ribbon of moonlit water cutting through dark ridges. The moon itself remains hidden behind clouds near the upper-left edge, outside the quiet center. On the left are steep monumental, snow-veined granite walls with exceptionally intricate cracks and shelves, descending into a tranquil inlet. Small rocky wooded islands and sharply defined spruce silhouettes step across the lower foreground. Beyond, graceful sawtooth peaks rise through thin bands of low mist. Make the fjord broad and elegant, its dark reflective surface visibly textured by gentle ripples and ice along the shores. Midnight cobalt, desaturated petrol blue and pewter silver, tiny restrained pale-cyan accents in ice. Top center is very dark spacious blue clouded sky for the headline; much quieter and more serene than a storm scene. Place a delicate silver opening in clouds near the far-left horizon, never in the top center. Emotion: mysterious, luxurious, quietly magical. There is no architecture anywhere.
The Stormbreak PassProject asset

Returned image: 1672 × 941 pixels; requested 4K was not returned.

Image generation prompt
Create one finished panoramic dark-fantasy landscape background image for a premium collectible-card-game website. Output a native high-resolution 4K image, 3840 x 2160 pixels, 16:9 landscape, PNG. This must be a single independently usable landscape, not a contact sheet. Art direction: exceptionally detailed cinematic realistic environment matte painting, finely articulated geology, believable snow deposits, individual conifer silhouettes, naturally textured water, sophisticated dark navy and blue-gray grading that complements an ornate cold stone Gothic castle. The castle is a SEPARATE existing foreground layer and must NOT be painted into this image. No buildings, castle, towers, architecture, characters, creatures, playing cards, objects in the air, graphic elements, writing, logos, borders, or watermarks. Composition must work behind large ivory serif headline typography and a group of illustrated cards: keep the upper central 45% of the image mostly restrained, dark, spacious sky with subtle cloud gradation; never place a bright focal object behind the upper-center headline. Put the most interesting terrain in the left third and across the lower half. Allow the rightmost quarter to be covered by a separate castle without losing the landscape's visual story. Three spatial layers: highly resolved nearer terrain at the lower-left edge, middle-distance forest and water, distant layered peaks. Crisp real detail across the landscape, no global blur, no low-resolution mush, no noise grain, no oversharpening halos, no painterly smudging. Distance should read through subtle atmospheric color separation rather than a blur filter. Clouds and ground fog should be beautiful but restrained, since animated snow, particles, smoke and light rays will be added separately in Three.js. No baked falling snow or floating white speckles.
CONCEPT THREE — THE STORMBREAK PASS. A dramatic immense alpine mountain pass after a snowstorm, viewed from a dark rocky overlook. Detail-rich jagged basalt cliffs rise on the left, with snow streaming through crevices; a valley of black spruce, winding glacial streams and fragmented snowy terraces opens across the lower middle. The sky has immense carefully structured layers of dark storm cloud, with a narrow break low on the far-left horizon letting muted pale champagne light touch a few distant snowy ridges. Very restrained broad rays behind the distant ridges, never a bright flare and never over the headline. Maintain a predominantly cold navy / slate / dark teal palette that still matches a blue-lit Gothic castle overlay on the right. The near terrain should reveal fine shale strata, wet rock, snow crust and individual trees without procedural grain. Keep the central upper sky dark and calm even though clouds toward the sides feel powerful. Emotion: epic, ominous, adventurous, the moment before a legendary battle. Distinct from a night scene, using subtle late-dusk warm/cold contrast. No structures of any kind.

Every legend starts with a few words.

Enter the world ↗