Docs · Limits & optimising
Technical limits and optimisation
Every visitor's browser downloads and draws what you publish, often on a phone, often with fifty people in the square. These are the limits the site enforces, exactly as its checks apply them, and the free tools that bring a model within them.
The numbers here are read from the site's code when it is built. The editor checks them before your wallet signs, and the server checks them again when your plot arrives. A version published before a limit changed keeps loading.
1. What a plot may publish
A plot's weight is what a visitor downloads as your own files: models, their distant copies, images, plus the plot's signed description. It is counted once per file, however many times you place it.
| Plot | Cells | Publishes (base) | Files | Signed description | NFT display copies | With all extra storage |
|---|---|---|---|---|---|---|
| 16 × 16 m | 1 | 25 MB | 200 | 1 MB | 15 MB | 150 MB (5 add-ons) |
| 32 × 32 m | 4 | 100 MB | 800 | 1 MB | 60 MB | 300 MB (8 add-ons) |
| 48 × 48 m | 9 | 100 MB | 800 | 1 MB | 60 MB | 300 MB (8 add-ons) |
| 80 × 80 m | 25 | 100 MB | 800 | 1.8 MB | 60 MB | 300 MB (8 add-ons) |
- 25 MB and 200 files per 16 m cell, up to a ceiling of 100 MB and 800 files, which a 32 m plot already reaches. Larger plots get the same ceiling: a visitor walking past loads a plot whole, so the town is budgeted per walk, not per square metre.
- The signed description (your scene and file list) may be 72 KB per cell, never less than 1 MB nor more than 1.8 MB. Every box, label and frame is described; merge repeated pieces into one model if you reach it.
- NFTs hung from your wallet do not count, nor do their display copies, which have their own quota (below).
- Your own images larger than 2,048 px on a side, or PNG/JPEG files over 1 MB, are published as 2,048 px WebP when that is smaller. Your original stays on your device.
- Extra storage adds 25 MB add-ons: 150 MB in all on a 16 m plot, 300 MB on larger plots (prices). A phone holds about 100 MB of full plots at once, so the heaviest plots load whole on a phone only when you stand in front of them.
Over the allowance, publishing is blocked. The meter turns amber at 85 % and lists the heaviest files. Fix it by removing or reusing files, compressing textures, or adding storage.
2. Per cell
Each 16 m cell is checked on its own, as if it were a small world.
| Per 16 m cell | Limit |
|---|---|
| Objects (boxes, columns, frames, models…) | 500 |
| Model instances (placed GLBs) | 16 |
| Different model files | 8 |
| Live NFT displays (token references) | 24 |
| Artworks carrying their own file (older path) | 8 |
| Portals | 16 |
| Model triangles, all models together | 500,000 |
| Model collision surfaces | 8,192 |
| Object size, each side | 16 m |
| Lowest bottom / highest top | -0.3 m / 16 m |
| Label, id, group name | 200 / 120 / 80 characters |
- An object must lie wholly inside its cell. A box (wall, floor, slab, step) that crosses a cell border is cut into one piece per cell for you; anything else must sit inside one cell.
- The scene check also caps a cell's original files at 48 MB; on the mainland the plot weight above (25 MB a cell) is the limit you meet first.
- Each live NFT display, frame or object is a separate described object: hundreds of tiny boxes cost more to describe and to draw than one model of them.
3. GLB models
Models are GLB (binary glTF 2.0) with everything embedded: one binary buffer, textures
inside the file. A .gltf with separate .bin and image files, or any
external link, is refused.
| One GLB placed in a plot | Hard limit (refused above) | What the builder aims for |
|---|---|---|
| File size | 20 MB | about 3 MB |
| Triangles | 200,000 | 180,000 |
| Materials | 64 | 24 |
| Draw primitives (mesh parts) | 256 | 240 |
| Nodes | 1,000 | — |
| Embedded images / textures | 64 / 128 | — |
| One embedded image | 8 MB, at most 4,096 px a side | 2,048 px a side |
| Texture pixels, all images | 16.8 megapixels (4,096²) | 12.6 megapixels |
| Vertices per accessor | 1,000,000 | — |
| Points (point clouds) | 1,000,000 | — |
| Animations | 4 clips, 64 channels, translation / rotation / scale only, LINEAR or STEP | — |
| Skins (rigs), morph targets, lights, cameras | Skins, morph targets and lights refused | — |
| Collision surfaces | 4,096 | made for you |
Extensions
Accepted: EXT_meshopt_compression, KHR_mesh_quantization, EXT_texture_webp, KHR_materials_emissive_strength, KHR_materials_unlit, KHR_materials_specular, KHR_materials_ior, KHR_texture_transform. Anything a model requires beyond these is refused, because a
missing decoder would show holes.
- Meshopt and quantization (
EXT_meshopt_compression,KHR_mesh_quantization) are the compression to use. They decode in a small built-in module. - Draco (
KHR_draco_mesh_compression) is accepted only by the builder's own import, which decodes it once and stores meshopt. The SDK,add_modeland published files refuse it: export without Draco. - KTX2 / Basis textures (
KHR_texture_basisu) are refused in your models. Use WebP, PNG or JPEG. (The site uses KTX2 only inside display copies it makes of NFT sculptures.) - Not supported:
EXT_mesh_gpu_instancing(glTF-Transform's--instance, gltfpack's-mi),KHR_meshopt_compression(gltfpack's-cz), sparse accessors, lights (KHR_lights_punctual), morph targets, skins and rigs (avatars have their own profile below). - Material extensions such as specular, IOR, emissive strength, unlit and texture transform are read natively; Blender writes the first two by default, and that is fine.
- Animation: up to 4 clips and 64 channels, moving nodes (translation, rotation, scale) with LINEAR or STEP interpolation. Animated models are decorative: give them invisible collision boxes.
- Geometry: triangles (or points, for point clouds). No node cycles, no node with two parents, at most 128 levels deep.
What the builder's import does for you
The plot editor and the free builder prepare a model on your device as it is imported: they reduce heavy geometry to about 180,000 triangles (trying gradually larger geometric errors, up to 2 %), resize textures to 2,048 px, share compatible materials in atlases, aim for about 3 MB and 24 materials, build a distant copy of up to 30,000 triangles and work out collision surfaces. What still does not fit is held back with a reason. The SDK and AI agents use your file as it is and only warn, so prepare it yourself first.
4. Textures
- Format: WebP, quality about 0.85–0.92 (85–92 on a 0–100 scale). The site itself writes WebP at 0.92, and 0.86 on its second, compact pass. PNG and JPEG are accepted; PNG only when you need exact edges or transparency WebP cannot keep.
- Size: 2,048 px on the longest side at most; 1024 or 512 for small or distant objects. The hard limit is 4,096 px a side and 16.8 megapixels per model in total.
- Powers of two (512, 1024, 2048) are not required by the checks but are recommended: they mip-map cleanly, atlas without waste and compress predictably.
- File size is not GPU memory. Every texture is decoded to raw pixels on the graphics card: 2048 × 2048 is about 16.8 MB, plus a third for mip-maps, whatever its file weighs. Halving the side quarters it.
- Fewer textures, fewer materials. Each material is at least one draw call. One atlas and one material per building is the goal.
5. Making a texture atlas
An atlas puts the textures of many parts into one image, so a building draws as one material.
In Blender (bake)
- Select the parts and join them (Ctrl+J), or keep them separate and bake each to the same image.
- Object Data Properties › UV Maps › +: add a new map called Atlas. Select it (so it is the one being edited) but keep the camera icon on the original map.
- In Edit Mode, select all (A), then U › Smart UV Project (or unwrap by hand with seams for cleaner results). In the UV Editor, UV › Pack Islands with a small margin.
- Image Editor › New: a 2048 × 2048 image (1024 for a small piece).
- In every material of the object, add an Image Texture node with that image, unconnected, and click it so it is the active node.
- Render Properties: engine Cycles. Bake › Bake Type Diffuse, Contributions: only Color (untick Direct and Indirect). Press Bake. Repeat with Normal or Roughness if you need them, each into its own image.
- Save the image. Give the object one new material that uses the baked image through the Atlas map, make Atlas the render map (camera icon) and delete the old map and materials.
- Export (below) and save the texture as WebP.
With glTF-Transform
glTF-Transform does not bake textured materials into one atlas, but palette merges
flat-coloured materials (the usual case for kit-built architecture) into one small palette texture
and one material, and dedup merges identical textures and materials:
gltf-transform dedup model.glb step1.glb
gltf-transform palette step1.glb model-palette.glb
For textured materials, bake in Blender as above.
6. Optimising, step by step
Start with gltf-transform inspect or Check my model to see where the
weight is: usually textures for size, triangles and materials for speed.
Blender (free)
- Merge by Distance: Edit Mode, select all, M › By Distance (Mesh › Merge). Removes duplicate vertices left by imports and modelling.
- Decimate: Modifier Properties › Add Modifier › Generate › Decimate, mode Collapse, lower the Ratio (0.5 halves the triangles) while watching the silhouette; Planar mode simplifies flat walls almost for free. Apply it.
- Delete what nobody sees: hidden faces, the inside of walls, the bottom of things standing on the ground.
- Bake detail into textures instead of geometry (atlas above; Cycles can also bake a high-poly model's normals onto a low-poly one with Selected to Active).
- Export: File › Export › glTF 2.0. Format glTF Binary (.glb); Include Selected Objects, no Punctual Lights, no Cameras; Mesh Apply Modifiers; Materials Export, Images WebP (or Automatic); Compression (Draco) off; Animation off unless the piece moves. Real-world scale: 1 Blender unit = 1 metre.
glTF-Transform CLI (free, Node.js)
npm install --global @gltf-transform/cli
gltf-transform inspect model.glb
One command that usually does it, keeping the result inside the site's rules:
gltf-transform optimize model.glb model-web.glb --compress meshopt --texture-compress webp --texture-size 2048 --instance false
Always pass --instance false: the default writes EXT_mesh_gpu_instancing, which the
site refuses. Never use --compress draco or --texture-compress ktx2. Add
--simplify false if optimize must not touch the geometry.
Or one step at a time:
gltf-transform weld in.glb welded.glb
gltf-transform simplify welded.glb simple.glb --ratio 0.5 --error 0.001
gltf-transform dedup simple.glb dedup.glb
gltf-transform resize dedup.glb sized.glb --width 2048 --height 2048
gltf-transform webp sized.glb webp.glb --quality 90
gltf-transform meshopt webp.glb final.glb
weldmerges identical vertices (simplify needs it first).simplify --ratio 0.5aims for half the triangles;--error 0.001keeps the shape within 0.1 % of the mesh's size. Raise the error for distant or scanned objects.resizecaps PNG and JPEG textures, keeping proportions; run it beforewebp.webp --quality 90re-encodes textures as WebP.meshoptcompresses geometry and animation (and quantizes it).
gltfpack (free, from meshoptimizer)
gltfpack -i model.glb -o model-web.glb -c -tw -si 0.5
-cmeshopt compression;-twWebP textures;-si 0.5simplifies to half the triangles;-knkeeps named nodes (use it when names matter, such as exhibition slots).- Do not use
-tcor-tu(KTX2),-cz(KHR_meshopt_compression) or-mi(instancing): the site refuses them. - The native release binaries handle textures better than the npm package.
Images: cwebp or Squoosh
cwebp -q 90 -resize 2048 0 painting.png -o painting.webp
-resize 2048 0 sets the width and keeps the proportions. In a browser, Squoosh
(squoosh.app) does the same visually: WebP, quality 85–92, Resize to 2048. Nothing is uploaded.
Video and GIF: ffmpeg
You do not need to convert the NFTs you hang: the site makes their display copies itself. ffmpeg is for preparing your own media before you mint it, which makes it lighter for every collector:
# GIF to a small H.264 MP4 (even dimensions, plays everywhere)
ffmpeg -i art.gif -movflags +faststart -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" -c:v libx264 -crf 23 art.mp4
# A heavy video down to 1080p, without sound
ffmpeg -i art.mov -vf "scale=-2:1080" -c:v libx264 -crf 22 -preset slow -pix_fmt yuv420p -movflags +faststart -an art-1080.mp4
# A still for a cover image
ffmpeg -i art.mp4 -frames:v 1 -vf "scale=1536:-2" cover.webp
The site's own tools
- Check my model: drop a GLB and see whether it fits, in your browser.
- Compress model textures (Tools): re-encodes a GLB's textures as WebP (2,048 px, 0.92) and compares a render before and after. Nothing is uploaded.
- SDK:
node third-life-pack.mjs scene.json --checkvalidates a scene the way the site will; the MCP toolvalidatedoes the same for an agent (SDK).
7. NFT display copies
When you publish, your device makes light copies of the heavy NFTs on your plot, signed with it. They never count in your weight; they have their own quota of 15 MB per cell, up to 60 MB.
- Thumbnail: WebP, 256 px. Still: WebP, up to 1,536 px.
- Motion (GIFs and videos): H.264 MP4, at most 1280×720 (720 × 720 square), muted, a loop of the first 30 seconds (the server accepts up to 60). Far away a work shows its still; within about five metres it plays.
- 3D: a display copy up to 24 MB and 180,000 triangles, and a light copy up to 3 MB for distance, made only on a desktop that can prepare the full model.
- If a browser cannot make a copy (Safari lacks some of the encoders), the plot publishes without it and visitors see the work's own display image. The original always opens from the work's panel.
8. Custom avatars: coming
Wearing your own avatar is not open yet. These are the limits the site's avatar check already applies, and the export specification given to the first collection preparing avatars, so you can prepare.
| Avatar | Hard limit | Target |
|---|---|---|
| Triangles | 30,000 | 25,000 |
| File size | 4 MB | 2 MB |
| Materials | 4 | 1, plus 1 for the eyes |
| Bones | 64, one skin | the shared Mixamo skeleton |
| Decoded texture memory | 32 MiB | WebP at 2048, 1024 or 512 |
| Height | 1.2–2.2 m | 1.75 m, metres not centimetres |
| Animations | 16 clips, 1,024 channels, LINEAR or STEP, no morph targets | Walking, Running and Idle in the file (required) |
| Compression | meshopt and quantization; no Draco, no KTX2 | opaque, single-sided |
Required joints, in Mixamo's naming: mixamorig:Hips mixamorig:Spine mixamorig:Spine1 mixamorig:Spine2 mixamorig:Neck mixamorig:Head mixamorig:LeftShoulder mixamorig:LeftArm mixamorig:LeftForeArm mixamorig:LeftHand mixamorig:RightShoulder mixamorig:RightArm mixamorig:RightForeArm mixamorig:RightHand mixamorig:LeftUpLeg mixamorig:LeftLeg mixamorig:LeftFoot mixamorig:LeftToeBase mixamorig:RightUpLeg mixamorig:RightLeg mixamorig:RightFoot mixamorig:RightToeBase.
Sources for the tools
- glTF-Transform CLI: gltf-transform.dev/cli; options as defined in its CLI source (checked 18 October 2026).
- gltfpack: meshoptimizer/gltf/README.md (checked 18 October 2026).
- cwebp: developers.google.com/speed/webp/docs/cwebp. Squoosh: squoosh.app.
- ffmpeg: ffmpeg.org/ffmpeg.html and the H.264 encoding guide.
- Blender manual: glTF 2.0 export, Decimate, UV unwrapping, Cycles baking.