---
applyTo: "src/assets/src/presentations/slate/drybones/**"
applyTo: "special-projects/drybones/**"
---

# DryBones LoRA — Fine-Tuned Image Generation Model

## Overview

A FLUX LoRA fine-tuned on the DryBones logo and wordmark, enabling consistent brand-accurate asset generation. The model recognises the trigger word **`DRYBNS`** to reproduce the skull-and-crossbones mark and wordmark in any scene context.

**Model endpoint:** `fal-ai/flux-lora-fast-training`  
**Trigger word:** `DRYBNS`  
**is_style:** `false` (subject/logo, not a style)  
**Training steps:** 1000

---

## Trained Model Record

| Field | Value |
|-------|-------|
| Training job ID | `2b5858b5-c5fe-41f5-b3a2-14f4b5694883` |
| Submitted | 2026-03-03 |
| Dataset zip | `https://v3b.fal.media/files/b/0a90b8cc/D5gezf6Nki2gsT_nDX3Lc_drybones-lora-dataset.zip` |
| LoRA weights URL | `https://v3b.fal.media/files/b/0a90b90b/GA5c8kemyYWVjmSJOgOVW_pytorch_lora_weights.safetensors` |
| Config URL | `https://v3b.fal.media/files/b/0a90b90b/a5sJ6MfSigtbmG84rHDeI_config.json` |
| Weights size | 85.6 MB (safetensors) |

**Retrieve LoRA URL after training completes:**
```bash
FAL_KEY="your-key-here"
curl -s "https://queue.fal.run/fal-ai/flux-lora-fast-training/requests/2b5858b5-c5fe-41f5-b3a2-14f4b5694883" \
  -H "Authorization: Key $FAL_KEY" | python3 -m json.tool
# The "diffusers_lora_file" -> "url" field contains the weights URL.
# Save it here: _______________
```

---

## Training Dataset

**Source:** SVG logo/wordmark files only. No generated images.  
**Location:** `src/assets/src/presentations/slate/drybones/drybones-logo-*.svg`  
**20 rendered PNG variants:**

| # | Source SVG | Background | Notes |
|---|------------|------------|-------|
| 01–05 | `drybones-logo-white-gold.svg` | Black / charcoal / dark gray | Canonical variant, multiple bg shades + square crop |
| 06–07 | `drybones-logo-charcoal-gold.svg` | Black / charcoal | Secondary variant |
| 08–09 | `drybones-logo-all-gold.svg` | Black | All-gold variant |
| 10 | `drybones-logo-gold-charcoal.svg` | White | Reversed for light contexts |
| 11 | `drybones-logo-gold-white.svg` | Light gray | Light context variant |
| 12–16 | `drybones-logo-mark.svg` | Black / charcoal / gold / white | Isolated icon at 400px and 600px |
| 17–18 | White-gold + all-gold | Black | Hero scale (1400×700) |
| 19–20 | White-gold + charcoal-gold | Same bg as logo | Tight-cropped wordmark |

Each image has a paired `.txt` caption file with the `DRYBNS` trigger word.

**Re-create the dataset:**
```bash
TMPDIR="${TMPDIR:-/tmp}"
WORK=$TMPDIR/drybones-lora-dataset
DECK=src/assets/src/presentations/slate/drybones
mkdir -p $WORK

render_on_bg() {
  local svg=$1 bg=$2 out=$3 pad=${4:-80}
  rsvg-convert -w 800 "$svg" -o $WORK/_tmp.png
  read w h < <(identify -format "%w %h" $WORK/_tmp.png)
  convert -size $((w+pad*2))x$((h+pad*2)) xc:"$bg" \
    $WORK/_tmp.png -gravity Center -composite -quality 95 "$WORK/${out}.jpg"
}

render_on_bg_sq() {
  local svg=$1 bg=$2 out=$3 size=${4:-800}
  rsvg-convert -w $size "$svg" -o $WORK/_tmp.png
  read w h < <(identify -format "%w %h" $WORK/_tmp.png)
  local canvas=$(( (size>h?size:h) + 160 ))
  convert -size ${canvas}x${canvas} xc:"$bg" \
    $WORK/_tmp.png -gravity Center -composite -quality 95 "$WORK/${out}.jpg"
}

# [run the full render block from the training session]
```

---

## Generating Images with the LoRA

### Via fal.ai FLUX Dev + LoRA endpoint

```bash
FAL_KEY="your-key-here"
LORA_URL="https://v3b.fal.media/files/b/0a90b90b/GA5c8kemyYWVjmSJOgOVW_pytorch_lora_weights.safetensors"

curl -s -X POST "https://queue.fal.run/fal-ai/flux-lora" \
  -H "Authorization: Key $FAL_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"prompt\": \"DRYBNS esports logo on a gaming mousepad, dark charcoal surface, dramatic lighting\",
    \"loras\": [{
      \"path\": \"$LORA_URL\",
      \"scale\": 1.0
    }],
    \"image_size\": \"landscape_16_9\",
    \"num_inference_steps\": 28,
    \"guidance_scale\": 3.5,
    \"num_images\": 1,
    \"enable_safety_checker\": false
  }" | python3 -m json.tool
```

### Prompt formula

```
DRYBNS [placement/context], Mediterranean [subject description], [scene], [lighting], [atmosphere]
```

**Rules:**
- Always start with `DRYBNS` — this fires the trigger word
- Describe people as Mediterranean: dark hair, olive skin, Southern European/MENA features
- No logo composite on top needed — the LoRA bakes branding into surfaces (mousepads, jerseys, screens, banners)
- Do NOT composite the SVG logo on top of LoRA outputs — the branding is in the generation

**Storyboard prompt examples (used in production 2026-03-03):**

| Slide | Prompt |
|-------|--------|
| cover | `DRYBNS esports player, Mediterranean young man dark hair olive skin, sitting at pro gaming station, DRYBNS logo mousepad and jersey visible, RGB lit desk, dramatic cinematic lighting, dark background, photorealistic 4K` |
| question | `Mediterranean young man dark hair olive skin, esports player alone at gaming desk, DRYBNS jersey, single monitor glow in dark room, contemplative expression, moody cinematic, photorealistic 4K` |
| world | `Massive esports arena, DRYBNS branding on giant LED screens and stage banners, Mediterranean players on illuminated stage, packed crowd, epic wide cinematic shot, fog and lights, photorealistic 4K` |
| window | `Esports player silhouette seen through practice room glass, DRYBNS decal on window, Mediterranean features visible in backlight, dark corridor POV, moody cinematic, photorealistic 4K` |
| journey | `Mediterranean esports team players in DRYBNS jerseys traveling, airport terminal, laptops and phones out, intense focused expressions, gear bags with DRYBNS logo, documentary cinematic style, photorealistic 4K` |
| weight | `Mediterranean young man, exhausted esports player head in hands at gaming station, DRYBNS jersey, teammate hand on shoulder in dark background, monitor still glowing, emotional cinematic moment, photorealistic 4K` |
| tension | `Extreme close-up of olive-skin hands on DRYBNS branded mechanical keyboard, fingers in motion during intense match, RGB backlit keys, dramatic side lighting, dark background, macro cinematic, photorealistic 4K` |
| close | `Esports team victory on stage, five Mediterranean players in DRYBNS jerseys raising fists, confetti, arena crowd roaring, DRYBNS logo on backdrop, epic cinematic celebration, photorealistic 4K` |
| comp-dts | `Documentary film crew filming Mediterranean esports players at event, cinema cameras, DRYBNS branding on venue walls and screens, dramatic production lighting, behind-the-scenes cinematic, photorealistic 4K` |

**Strength tuning:**
- `scale: 1.0` — strong, accurate logo
- `scale: 0.8` — slightly blended into scene
- `scale: 0.6` — subtle brand presence

### Via Copilot (fal tools)

The `fal-generate_image` tool doesn't natively accept LoRA paths. Use bash + curl as above, or use the fal Python SDK:

```python
import fal_client, os

os.environ["FAL_KEY"] = "your-key"
LORA_URL = "https://v3b.fal.media/files/b/0a90b90b/GA5c8kemyYWVjmSJOgOVW_pytorch_lora_weights.safetensors"

result = fal_client.subscribe("fal-ai/flux-lora", arguments={
    "prompt": "DRYBNS esports logo on a gaming mousepad, dark scene, cinematic",
    "loras": [{"path": LORA_URL, "scale": 1.0}],
    "image_size": "landscape_16_9",
    "num_inference_steps": 28,
})
print(result["images"][0]["url"])
```

---

## Retraining (when to do it)

Retrain if:
- The logo/mark design changes significantly
- The LoRA URL expires (fal storage TTL)
- Brand color palette shifts

**Steps to retrain:**
1. Update SVGs in `src/assets/src/presentations/slate/drybones/`
2. Re-run the render script above to regenerate PNGs + captions
3. Re-package and upload: `python3 -c "import zipfile, glob; ..."` → `fal-upload_file`
4. Resubmit training job with same params, new `images_data_url`
5. Update this document with new job ID and LoRA URL

---

## Polling Training Status

```bash
FAL_KEY="your-key-here"
REQUEST_ID="2b5858b5-c5fe-41f5-b3a2-14f4b5694883"

# Check status
curl -s "https://queue.fal.run/fal-ai/flux-lora-fast-training/requests/$REQUEST_ID/status" \
  -H "Authorization: Key $FAL_KEY" | python3 -m json.tool

# Get result when COMPLETED
curl -s "https://queue.fal.run/fal-ai/flux-lora-fast-training/requests/$REQUEST_ID" \
  -H "Authorization: Key $FAL_KEY" | python3 -m json.tool
# Look for: .diffusers_lora_file.url
```

Status values: `IN_QUEUE` → `IN_PROGRESS` → `COMPLETED`

---

## Integration with Deck Background Workflow

Once LoRA is trained, the correct workflow for deck backgrounds is:

1. **Generate** a scene image with `fal-generate_image` (gamer + esports context, no branding)
2. **Regenerate with LoRA** via `fal-ai/flux-lora` + the DRYBNS LoRA at scale 0.8–1.0, using the generated image as `image_url` (img2img) — this inserts the actual logo into scene surfaces
3. **Composite** the real SVG logo on top via ImageMagick for pixel-perfect accuracy
4. Copy resulting JPGs to `src/assets/src/presentations/slate/drybones/drybones-storyboard-*.jpg`
5. Rebuild: `cd src/assets && make slate-drybones-deck`
