Wiggly / Format Lab /

fortnite-filter

agent-ready
v1.0.0

Fortnite Filter

Turn one portrait into a realistic, cinematic Fortnite-style 3D character image.

One portrait in. One inspected 3:4 JPG out.

Download runnable kit

Two real Replicate proofs

Compare resemblance, pose retention, cinematic 3D styling, and output consistency across distinct portraits.

Input for Full-body pose proofOutput for Full-body pose proof
google/nano-banana-2

Full-body pose proof

  • Identity and seated pose remain recognizable
  • Visible hands, tattoos, watch, and clothing survive
  • The silhouette has cinematic 3D volume
  • It passed automatic and recorded visual inspection
Input for Economy close-portrait proofOutput for Economy close-portrait proof
google/nano-banana-2-lite

Economy close-portrait proof

  • Identity, gaze, head angle, hair, and outfit remain recognizable
  • The sunset city composition carries through
  • The economy route still produces a polished 3D finish
  • It passed automatic and recorded visual inspection
Original @skaigenerated Fortnite Filter example

Gathered source

The exact prompt stays packaged

Transform the exact photo into a Fortnite-style character with a realistic, cinematic 3D look. Keep the subject's pose, expression, and features, reinterpreting them with stylized Fortnite proportions: a clean silhouette, detailed hands and face, voluminous yet polished hair, and slightly glossy materials. The clothing should feature realistic textures but a Fortnite-inspired design. Use warm lighting with the game's signature golden rim light, soft shadows, and realistic depth of field. Add soft airborne particles (dust/light) to enhance the atmosphere. Avoid a flat cartoon style; prioritize volume, AAA-quality textures, and a photographic look.

Source guide: @skaigenerated · model shown: Nano Banana Pro

The official run

Prepare -> Validate -> Transform -> Inspect

  1. 1. prepare
    free

    A local run with one copied input image and selected model route.

  2. 2. validate
    free

    Decoded dimensions, type, byte size, and SHA-256 stored before spending.

  3. 3. transform
    paid

    One 3:4 JPG from the selected official Replicate model.

    Explicit approval required

  4. 4. inspect
    free

    Automatic media checks plus a recorded visual review.

    Explicit approval required

Model routes

  • Economy: Nano Banana 2 Lite
  • Default: Nano Banana 2
  • Premium/source guide: Nano Banana Pro

What prevents waste

  • The portrait validates before spending.
  • Paid generation needs an explicit flag.
  • The prediction ID is saved before polling.
  • Interrupted jobs resume instead of duplicating.
  • Three attempts is the hard cap.

Repo files

Agent instructions SKILL.md
---
name: wiggly-fortnite-filter
description: Turn one portrait into a realistic cinematic Fortnite-style 3D character image through Replicate.
---

# Fortnite Filter

Use the official runner. Do not call Replicate separately, rewrite the prompt, or create a second render path.

## Conversation

Ask one short question at a time. Start with:

> Which photo should I turn into a Fortnite-style character?

Use Nano Banana 2 by default. Offer Nano Banana 2 Lite when the user wants the lowest price, or Nano Banana Pro when they explicitly want the source guide's premium model.

## Workflow

1. Run `npm run format:fortnite-filter -- check --format=fortnite-filter`.
2. Initialize a run with one image.
3. Validate locally.
4. Show the model route and estimate.
5. Only run the paid transform with explicit user approval.
6. If polling is interrupted, use `resume`; never create a duplicate prediction.
7. Inspect the actual output with an image-viewing tool.
8. Record specific review notes and finalize only after the image passes.

```bash
npm run format:fortnite-filter -- init --format=fortnite-filter --run=<id> --input=<path>
npm run format:fortnite-filter -- validate --format=fortnite-filter --run=<id>
npm run format:fortnite-filter -- estimate --format=fortnite-filter --run=<id>
npm run format:fortnite-filter -- render --format=fortnite-filter --run=<id> --approve-paid
npm run format:fortnite-filter -- inspect --format=fortnite-filter --run=<id>
npm run format:fortnite-filter -- inspect --format=fortnite-filter --run=<id> --visual-pass --review-notes="<specific observations>"
npm run format:fortnite-filter -- finalize --format=fortnite-filter --run=<id> --approve-final
```

Select another route during `init`:

```bash
--model=nano-banana-2-lite
--model=nano-banana-pro
```

## Hard rules

- Exactly one input image and one final image per run.
- Keep the packaged prompt exact.
- Validate before any paid call.
- Require `--approve-paid`.
- Persist and resume the same Replicate prediction ID.
- Never exceed three paid attempts in one run.
- Save the provider output locally immediately.
- Require automatic checks, visual review, notes, and `--approve-final`.
- Never print, store, or commit `REPLICATE_API_TOKEN`.
Replicate BYOK requirements requirements.json
{
  "runtime": {
    "node": ">=22",
    "commands": [
      "npm"
    ]
  },
  "providers": [
    {
      "name": "Replicate",
      "purpose": "Run the selected official Google Nano Banana image model.",
      "models": [
        "google/nano-banana-2-lite",
        "google/nano-banana-2",
        "google/nano-banana-pro"
      ]
    }
  ],
  "environment": [
    {
      "name": "REPLICATE_API_TOKEN",
      "requiredFor": [
        "render",
        "resume"
      ],
      "secret": true
    }
  ],
  "notes": [
    "check, init, validate, estimate, inspect, finalize, and smoke are local.",
    "render makes exactly one Replicate prediction per attempt after --approve-paid.",
    "The runner persists the prediction ID before polling and can resume the same job.",
    "Maximum paid attempts per run: 3."
  ]
}
Input contract and model routing inputs.json
{
  "required": [
    {
      "id": "portrait",
      "type": "image",
      "count": 1,
      "formats": [
        "jpg",
        "png",
        "webp"
      ],
      "minimumWidth": 512,
      "minimumHeight": 512,
      "maximumBytes": 26214400,
      "question": "Which photo should I turn into a Fortnite-style character?"
    }
  ],
  "defaults": {
    "model": "nano-banana-2",
    "aspectRatio": "3:4",
    "outputFormat": "jpg",
    "resolution": "1K"
  },
  "modelRoutes": {
    "economy": "google/nano-banana-2-lite",
    "default": "google/nano-banana-2",
    "premium": "google/nano-banana-pro"
  }
}
Paid-call and resume contract pipeline.json
{
  "progress": "Prepare -> Validate -> Transform -> Inspect",
  "attemptCap": 3,
  "stages": [
    {
      "id": "prepare",
      "output": "A local run with one copied input image and selected model route.",
      "paid": false,
      "approvalRequired": false
    },
    {
      "id": "validate",
      "output": "Decoded dimensions, type, byte size, and SHA-256 stored before spending.",
      "paid": false,
      "approvalRequired": false
    },
    {
      "id": "transform",
      "output": "One 3:4 JPG from the selected official Replicate model.",
      "paid": true,
      "approvalRequired": true
    },
    {
      "id": "inspect",
      "output": "Automatic media checks plus a recorded visual review.",
      "paid": false,
      "approvalRequired": true
    }
  ]
}
Exact gathered prompt prompts/transform.txt
Transform the exact photo into a Fortnite-style character with a realistic, cinematic 3D look. Keep the subject's pose, expression, and features, reinterpreting them with stylized Fortnite proportions: a clean silhouette, detailed hands and face, voluminous yet polished hair, and slightly glossy materials. The clothing should feature realistic textures but a Fortnite-inspired design. Use warm lighting with the game's signature golden rim light, soft shadows, and realistic depth of field. Add soft airborne particles (dust/light) to enhance the atmosphere. Avoid a flat cartoon style; prioritize volume, AAA-quality textures, and a photographic look.
Automatic and visual gates quality.json
{
  "automatic": [
    "The output decodes as JPEG or PNG",
    "The output is at least 768x1024",
    "The output aspect ratio is 3:4 within 0.015",
    "The output is at least 50 KB",
    "The output SHA-256 is recorded"
  ],
  "manualReview": [
    "The subject remains recognizably the same person",
    "The original pose and expression are preserved",
    "Face, eyes, hands, and fingers do not contain obvious artifacts",
    "The silhouette and hair read clearly",
    "The result has cinematic 3D volume rather than a flat cartoon look",
    "Warm rim light, soft shadows, depth of field, and subtle particles support the look",
    "No accidental text, watermarks, duplicate limbs, or broken clothing"
  ],
  "finalizationGate": [
    "All automatic checks pass",
    "A human or viewing agent inspected the actual output",
    "Review notes are stored",
    "The --approve-final flag is present"
  ],
  "reject": [
    "The subject is no longer recognizable",
    "The pose or expression changes substantially",
    "Visible face, hand, limb, or clothing artifacts",
    "Flat 2D cartoon treatment",
    "Malformed, undersized, or wrong-aspect output"
  ]
}
Prediction provenance proofs.json
{
  "generatedAt": "2026-07-29",
  "provider": "Replicate",
  "promptPath": "prompts/transform.txt",
  "proofs": [
    {
      "id": "proof-seated-man",
      "inputPath": "fixtures/trevor-chris-hutchinson-man.jpg",
      "outputPath": "goldens/nano-banana-2-seated-man.jpg",
      "qualityReportPath": "goldens/nano-banana-2-seated-man.quality.json",
      "model": "google/nano-banana-2",
      "predictionId": "9v21s663tdrmr0cznh9rh31qc0",
      "attemptsUsed": 1,
      "status": "finalized",
      "sha256": "ce90f7f01df202cc29a0ef3c9fc6d571ee53acb15e4e70f28911feb914bba49d"
    },
    {
      "id": "proof-sunset-woman",
      "inputPath": "fixtures/rao-qingwei-woman.jpg",
      "outputPath": "goldens/nano-banana-2-lite-sunset-woman.jpg",
      "qualityReportPath": "goldens/nano-banana-2-lite-sunset-woman.quality.json",
      "model": "google/nano-banana-2-lite",
      "predictionId": "zkwhk22bvhrmr0cznha91n4aa4",
      "attemptsUsed": 1,
      "status": "finalized",
      "sha256": "8f1939f82f113f062ec288a574259e10cbdb1bf090d8680f8017214f4afb80db"
    }
  ]
}