deploy-scene
Skill4 starsChanged 9 days agoApache-2.0View on GitHub
Deploy a Decentraland scene to Genesis City (LAND-based). Use when the user wants to deploy or publish to parcels they own, reduce the deployed scene size, upload a large scene, script or cancel a deploy, or hits a DEPLOY_* error. Do NOT use for Worlds deployment (see deploy-worlds).
- Deletes or force-pushes
- Installs packages
In this repository37 other files it gives its agents.
- add-3d-modelsSkill
- add-interactivitySkill
- advanced-inputSkill
- advanced-renderingSkill
- animations-tweensSkill
- audio-analysisSkill
- audio-videoSkill
- authoritative-serverSkill
- avatar-animationsSkill
- build-uiSkill
- camera-controlSkill
- compositesSkill
- create-sceneSkill
- creator-hub-mcpSkill
- dcl-gddSkill
- dcl-prototypeSkill
- deploy-worldsSkill
- fontsSkill
- lighting-environmentSkill
- migrate-sdk6-to-sdk7Skill
- multiplayer-syncSkill
- nft-blockchainSkill
- npcsSkill
- optimize-sceneSkill
- particle-systemSkill
- player-avatarSkill
- player-physicsSkill
- promote-sceneSkill
- report-sdk-issueSkill
- scene-feedbackSkill
- scene-retroSkill
- scene-runtimeSkill
- script-componentsSkill
- sdk-scenesSkill
- smart-wearablesSkill
- unity-explorer-mcpSkill
- wearablesSkill
The file
We split this skill into the rules it gives an agent
5 rules. About 0 are common, 1 is distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 37
Run npx @dcl/sdk-commands start to verify the scene works (add --web to preview in the Bevy Web browser client).
- Distinctive: line 140
Read the square image. Done when every word of the text and the main subject are inside it, the ratio is 16:9 and the file is under 1 MB.
- Very specific: line 215
If a deploy fails with "Scene is too large", checking .dclignore is the first step: working files are often the bulk of the excess, and …
- Very specific: line 222
When an asset silently fails to load or play in preview and .dclignore has !
- Very specific: line 228
After every publish, the content servers compress all .gltf/.glb models to asset bundles — a significantly lighter format.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Deploying to Genesis City
Deploy to specific parcels you own or have permission to deploy to.
Deploy with npx @dcl/sdk-commands deploy (or the Creator Hub's Publish button). It builds the scene, uploads it to IPFS and asks a wallet that owns the parcels (or has deploy permission) to sign.
Pre-Deployment Checklist
Before deploying, verify:
scene.json is valid:
ecs7: trueandruntimeVersion: "7"- Correct
parcelsmatching your LAND (for Genesis City) - Valid
baseparcel main: "bin/index.js"
Discovery metadata is complete — these four fields decide whether anyone finds and enters the scene, and they are frequently left at template defaults. Check each one and fill in what you can infer from the scene itself; ask the user only for what you can't:
display.title— the scene name, shown under the minimap in-world and in the map modaldisplay.description— one or two sentences on what the scene is. Aim for ~140 characters that say what the player does there (verb first, who with, why come back). It is the line on the Places card that earns the tap (Foundation marketing requirements)tags— root-level array, 1-3 Places-dApp categories inferred from the scene's theme. Valid values:{baseDir}/../create-scene/references/scene-json.md→ Tags (scene categories)display.navmapThumbnail— set, and the image passes every check in Thumbnail image below
Code compiles:
npx tsc --noEmit- Scene previews correctly:
Run
npx @dcl/sdk-commands startto verify the scene works (add--webto preview in the Bevy Web browser client). Test with multiple browser tabs to verify multiplayer behavior. Dependencies installed:
npm installAssets are within limits — see the optimize-scene skill for full limit formulas per parcel count (triangles, entities, materials, textures) and the flat 330 m height limit. Keep scene load time under 15 seconds by optimizing assets.
Then do a size pass on what will actually upload, before the deploy rather than after a rejection:
find assets -type f -size +1M -exec ls -lh {} + # the heavy files npx @gltf-transform/cli inspect assets/Models/big.glb # Textures table: each embedded map's resolution and bytesEmbedded 2048 px texture maps are the usual surprise — two generated GLBs carried 17 MB of them in a 34 MB scene. Resize them to 1024 or less (
npx @gltf-transform/cli resize in.glb out.glb --width 1024 --height 1024, or in Blender — see optimize-scene): the converter downscales to 1024 anyway, and the raw file still counts in full. Estimate code size from a production build, not from the project'sbin/index.js: the preview's dev build carries an inline source map and no minification, whiledeployrebuilds with--production(minified, no map), typically a fraction of the size..dclignorecovers all working files — Blender/FBX sources, concept art, spreadsheets, markdown docs, etc. must not be uploaded. See the.dclignoresection below.
Deployment Process
Using CLI
# Build first
npx @dcl/sdk-commands build
# Deploy (will open browser for wallet connection)
npx @dcl/sdk-commands deployScenes of 50 MiB or more upload in 32 MiB batches (@dcl/sdk-commands 7.31.0+), printing Uploaded X MB of Y MB (batch n/N); smaller ones go in one request. The linker page shows the upload progress and can cancel it. Batch rules, every flag, the /api/deploy API for scripting, following or cancelling a deploy, and the DEPLOY_* error codes: {baseDir}/references/deploy-cli.md.
Using Creator Hub
- Open Creator Hub
- Select your scene
- Click "Publish"
- Connect wallet
- Confirm transaction
The link to share after publishing
The success panel shows and copies a web /jump link, which works for players without the desktop client; its Jump In button opens the desktop client separately. Use the same forms in anything you write for players:
| Target | Share link |
| Genesis City scene | https://decentraland.org/jump?position=x,y |
| World | https://decentraland.org/jump?realm=NAME.dcl.eth |
| Desktop client directly | decentraland://?position=x,y&dclenv=<env> (or ?realm=…) |
/jump is canonical — the legacy /play/... paths only 301-redirect to it, so do not generate them.
scene.json for Deployment
{
"ecs7": true,
"runtimeVersion": "7",
"display": {
"title": "My Awesome Scene",
"description": "A description for the marketplace",
"navmapThumbnail": "assets/Images/thumbnail.png"
},
"tags": ["art", "social"],
"scene": {
"parcels": ["0,0", "0,1"],
"base": "0,0"
},
"main": "bin/index.js"
}tags is root-level, not under display. Every field: {baseDir}/../create-scene/references/scene-json.md.
Thumbnail image
display.navmapThumbnail is the image players see in the map modal when they select the scene's parcels, and in the confirmation screen when another scene teleports them there. Always provide one.
Spec:
.pngor.jpg, 16:9 within 1 % (the Creator Hub validates this), recommended 1920x1080 px (1344x756 for a lighter file). Other sizes work as long as they keep 16:9 — anything else is stretched- Central square safe area: parts of the platform show a square crop of the central 1080x1080 px, cutting ≈ 0.219 of the width off each side (x 420–1500 at 1920 wide, x 280–1000 at 1280 wide). Keep text, logos and the main subject inside it
- Under 1 MB (1,048,576 bytes) — the Worlds content server rejects anything larger at deploy time (
Invalid thumbnail: size … exceeds maximum of 1048576 bytes (1MB)), and a plain 1920x1080 PNG can exceed it. Nothing local warns you. For a generated cover (Blender render, image tool), export JPEG at high quality:ffmpeg -i cover.png -q:v 2 cover.jpgcame out around 100 KB at 1344x756. Keep a PNG only if it stays under the cap - Best practice: a gameplay screenshot with a clear, distinctive logo overlaid and minimal text, still readable at phone-card size
- Value is a path inside the project (e.g.
assets/Images/thumbnail.png) or a URL to an externally hosted image — an external host must serve permissive CORS headers - Save a custom cover under its own name (e.g.
assets/Images/cover.png). The Creator Hub overwritesassets/Images/autogenerated-thumbnail.pngwith a viewport capture whenever it auto-generates a thumbnail, including right before a publish
Check before pointing navmapThumbnail at an image, whether you captured, rendered or composed it:
- Byte size and dimensions:
ls -l <path>, thensips -g pixelWidth -g pixelHeight <path>(macOS) ormagick identify -format "%wx%h\n" <path>. Crop the central square and look at that, not at the full frame (a title running edge to edge looks fine in the full frame):
OUT="${TMPDIR:-/tmp}/thumb-square.png" # macOS H=$(sips -g pixelHeight <path> | awk '/pixelHeight/{print $2}'); sips -c $H $H <path> --out "$OUT" # ImageMagick (any OS) H=$(magick identify -format %h <path>); magick <path> -gravity center -crop ${H}x${H}+0+0 +repage "$OUT"- Read the square image. Done when every word of the text and the main subject are inside it, the ratio is 16:9 and the file is under 1 MB. Otherwise recapture or re-render.
Capture it yourself — ask the user if instead of providing an image they prefer you to capture it With the unity-explorer MCP (see the unity-explorer-mcp skill), run the scene in preview, move the camera to frame a shot that shows what the scene is about — composing so the essential content sits in the middle third, inside the central square — and capture a UI-less PNG with the bundled script:
# <skill-dir> is the unity-explorer-mcp skill's base directory
<skill-dir>/scripts/screenshot.sh --world-only --png -w 1920 -o assets/Images/thumbnail.pngLaunching the client windowed at 16:9 (npm run start -- --mcp -- --windowed-mode --resolution 1920x1080) makes the frame 16:9 natively, so no crop is needed. Otherwise normalize it:
# ImageMagick: center-crop to 16:9 and resize, in one step
magick assets/Images/thumbnail.png -resize 1920x1080^ -gravity center -extent 1920x1080 assets/Images/thumbnail.png
# macOS, no extra tooling: -c takes HEIGHT then WIDTH, both centered
sips -g pixelWidth -g pixelHeight assets/Images/thumbnail.png # read the source size first
sips -c 1080 1920 assets/Images/thumbnail.png --out assets/Images/thumbnail.png # center-crop a larger frame
sips -z 1080 1920 assets/Images/thumbnail.png # then resample to exactly 1920x1080Point display.navmapThumbnail at the resulting path. Only if the MCP is unavailable, ask the user for an image rather than shipping the scene without one. Make sure .dclignore doesn't exclude the thumbnail — it must be uploaded with the scene.
Letter case matters. The path in navmapThumbnail must match the folder on disk exactly: the deploy file list preserves on-disk casing and the Catalyst matches case-sensitively, while macOS and Windows resolve either casing locally — so a mismatch publishes as Scene thumbnail '…' must be a file included in the deployment and never shows up in testing. In a Creator Hub project the standard folder is assets/Images/ (capital I), which is also where the Hub writes its own autogenerated capture. ls assets before writing the path, and never keep two folders differing only in case.
Spawn Points
Spawn points: {baseDir}/../create-scene/references/scene-json.md → Spawn Points.
.dclignore — Exclude Files from Upload
The .dclignore file, always at the project root, lists files and patterns that are NOT uploaded to the content server when deploying, and not served by the local preview either (see .dclignore also filters the preview below). Everything in the project folder that isn't matched by .dclignore gets uploaded, and the uploaded total counts against the per-parcel MB limits — so only files the running scene actually needs should be deployed.
Format: one glob pattern per line. The default from scene templates:
.*
package-lock.json
yarn-lock.json
build.json
export
tsconfig.json
tslint.json
node_modules
*.ts
*.tsx
.vscode
Dockerfile
dist
README.md
*.blend
*.fbx
*.zip
*.rar
*.md
srcKeep it up to date as the project grows. Whenever working files exist in the project — Blender or other 3D source files, draft models, concept art, PSDs, spreadsheets, markdown notes, reference photos — add them (or their extensions) to .dclignore so the deployed scene stays as light as possible. When creating or editing a scene, add these patterns proactively; don't wait for the deploy to fail. Common additions:
*.blend
*.blend1
*.fbx
*.psd
*.kra
*.xcf
*.md
*.csv
*.xlsx
drafts
concept-art
referenceIf a deploy fails with "Scene is too large", checking .dclignore is the first step: working files are often the bulk of the excess, and excluding them reduces upload size with zero impact on the scene.
.dclignore also filters the preview
npm run start builds the preview's scene content list from the same publishable-file set as deploy (getProjectPublishableFilesWithHashes in @dcl/sdk-commands, verified in source), so an excluded asset does not exist for the running scene. The client never requests it: no 404, no log line. An excluded _emote.glb makes triggerSceneEmote resolve false and the emote simply does not play (observed twice, 2026-11, with a whitelist-style .dclignore that re-included only some files under assets/animations/).
- Exclude by pattern — working-file extensions and folders, as above — and let every asset folder upload by default. A whitelist (
*plus!re-includes) drops each new asset until someone edits the list. - When an asset silently fails to load or play in preview and
.dclignorehas!lines, grep it for the asset's path before debugging anything else.
Keep these uploaded: bin/index.js, scene.json, assets/ (composites, .glb models, textures, sounds, video), the thumbnail referenced in scene.json, and any file path referenced in code. The default ignores *.ts/src because only the compiled bin/index.js runs.
Post-Publish: Asset Bundle Conversion
After every publish, the content servers compress all .gltf/.glb models to asset bundles — a significantly lighter format. The conversion starts immediately but is queued per platform (Windows, Mac). While it runs, players are deliberately served the last fully-working version of the scene.
- Typical time: seconds. Longer for very large scenes or when the conversion servers are busy.
- A conversion running more than a couple of minutes is a failure signal, not normal queuing — check the status endpoint rather than continuing to wait.
- The Jump In button appears as soon as the scene is playable, once upload and conversion are done.
- Before a live event: publish your final version at least one hour in advance, to leave room for anything unexpected. Avoid republishing while waiting — each publish restarts the queue.
- Check conversion status in a browser:
https://asset-bundle-registry.decentraland.org/entities/status/<pointer>— replace<pointer>with a scene coordinate (e.g.20,-34) or the deployment entity ID. Shows per-platform status underassetBundlesand LOD status underlods. For a World, append?world_name=myname.dcl.eth.https://asset-bundle-registry.decentraland.org/queues/status— lists all scenes currently queued for conversion, per platform.
/detectabschat command: in-world, tints models green (converted) or red (not yet converted).- Reloading the scene is not enough to pick up a new version — reload restarts the scene's code but doesn't fetch newly published content. Any player who already loaded the scene this session keeps seeing the cached version until they fully close and re-enter Decentraland. That includes you: after conversion completes, quit and relaunch, then re-enter via jump link or
/goto.
The desktop preview already runs the same conversion locally, so catch conversion issues before publishing in its AB panel — see the optimize-scene skill ("Local Asset Bundle Preview").
Troubleshooting
| Error | Cause | Solution |
| "You don't have permission to deploy" | Wallet doesn't own the target LAND/parcels | Verify LAND ownership on the marketplace, or get deployment permissions from the LAND owner |
| "Scene is too large" | Assets exceed parcel size limits | First add all working files (Blender/FBX sources, concept art, docs) to .dclignore — see the .dclignore section above. Then check triangle count, file sizes, and texture counts against the limits. See optimize-scene skill |
| Wallet connection fails | Browser popup blocked or MetaMask locked | Allow popups, unlock MetaMask, refresh and try again |
| "Invalid scene.json" | Missing required fields or malformed JSON | Verify ecs7: true, runtimeVersion: "7", valid parcels array, and main: "bin/index.js" |
| Deploy succeeds but scene is empty | main field doesn't point to compiled output | Ensure main is "bin/index.js" and run npx @dcl/sdk-commands build first |
| Catalyst rejection | Content violates Decentraland content policies | Review content guidelines at docs.decentraland.org |
| Scene looks broken right after deploy | Asset bundle conversion not done yet | Type /detectabs in chat — red-tinted models are not yet converted. Check conversion status (see above) and wait |
| Some players see old version, others see new | Per-platform conversion finishes at different times + client caching | Check both windows and mac under assetBundles in the conversion status endpoint. Once both are complete, affected players must fully restart Decentraland |
| Publication stuck on Converting stage | Conversion failed, or the scene is queued behind others | Conversion normally takes seconds, so more than a couple of minutes points at a failure rather than a queue. Check the queue status URL for your entity ID. If not queued, check conversion status — if a platform shows failed, republish. If it fails again, report the bug with the entity ID |
| 3D models missing, black, or untextured after deploy | Conversion still in progress, or textures exceed the conversion cap | /detectabs to check; textures in 3D models are capped to 1024x1024 during conversion |
| Scene looks fine up close but broken from a distance | LOD generation (final publish stage) not done yet | Check the lods values in the conversion status endpoint; LODs don't block close-range testing |
| "Scene thumbnail '…' must be a file included in the deployment" (the file plainly exists) | Letter-case mismatch between display.navmapThumbnail and the folder on disk (e.g. assets/images/ vs assets/Images/) | ls assets and make the path match the folder exactly — see Thumbnail image → Letter case |
| "Invalid thumbnail: size … exceeds maximum of 1048576 bytes" | Thumbnail over 1 MB (a plain 1920x1080 PNG can be) | Export JPEG or shrink to 1344x756 — see Thumbnail image |
DEPLOY_PARTIAL_NOT_SUPPORTED | The server can't take batched uploads and the content it is missing is over 200 MB | Shrink the scene (.dclignore, texture sizes) or deploy to a server that supports batches — {baseDir}/references/deploy-cli.md |
DEPLOY_CANCEL_OUTCOME_UNCERTAIN | A cancel landed mid-upload and the CLI couldn't tell whether the server published it | Check the scene (conversion status URL above) before deploying again |
tsc/deploy build fails on node_modules/@dcl/js-runtime/sdk.d.ts importing a script file that no longer exists | The bundler rewrites that file's ~sdk/script-utils declaration only while the composite still has at least one script; removing the last Creator Hub script asset leaves the old declaration pointing at the deleted .tsx | Delete the declare module '~sdk/script-utils' block at the end of sdk.d.ts (or rm -rf node_modules/@dcl/js-runtime && npm install), then build again. Keeping one script in the scene avoids it |
Genesis City vs Worlds
| Genesis City | Worlds | |
| Requirement | Own LAND parcels | Own DCL NAME or ENS domain |
| Parcel limits | Enforced (entity/triangle budgets per parcel) | Not constrained by LAND |
| Visibility | Shown on the Genesis City map | Listed on Places page (opt-out available) |
| Deploy target | Default Catalyst network | --target-content https://worlds-content-server.decentraland.org |
| Best for | Permanent installations, high-traffic scenes | Testing, personal spaces, events |
To deploy to a World, use deploy-worlds.
Scene Tipping
To let visitors tip the scene creator in MANA, set the root-level creator wallet address in scene.json: {baseDir}/../create-scene/references/scene-json.md → Fields.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

