Host your own asset library

Have your own models? Run the Holodeck Asset Library — a single Python file — next to them, and the Playground agent, the Unity client and MCP can search and place your assets exactly like the built-in library.

  • One file, Python 3.10+ standard library only — no installs: holodeck_library.py
  • Indexes GLB / glTF / FBX / OBJ models and PNG / JPG / TGA textures
  • Reads real sizes from GLB / OBJ, Unity .meta GUIDs, sidecar thumbnails
  • CORS-enabled file serving (browsers and Unity load files directly), optional Bearer token
  • Docker files and full README: clients/asset-library/ in the Holodeck repo

Quickstart

curl -O https://arx.dev/docs/download/holodeck_library.py
python3 holodeck_library.py serve --root ./my-assets --name "My Studio" --port 8787 --token change-me
# browse http://localhost:8787 · API at http://localhost:8787/api/v1/assets

Organise your folder

my-assets/                      ← --root
  NaturePack/                   ← every top-level folder is a pack
    pack.json                   ← optional
    Models/
      SM_Env_Tree_01.glb
      SM_Env_Tree_01.png        ← sidecar thumbnail (same name), or NaturePack/Thumbnails/…
      SM_Env_Tree_01.glb.meta   ← optional Unity .meta → unity_guid
    Textures/Nature_Atlas.png

Asset paths look like @my-studio/NaturePack/Models/SM_Env_Tree_01.glb — the same shape as Holodeck’s own @synty/PolygonTown/…, so vendor locks work the same way.

pack.json (all optional):

Key Meaning
atlas Texture applied to models with no embedded textures (Synty-style palette atlas). Textured GLBs keep their own.
unit_scale Metres per file unit. Default 1.0; Synty FBX/GLB exports are centimetres → 0.01.
tags Extra tags on every asset in the pack.

Textured, metre-scale GLBs need no configuration at all.

Connect it to Holodeck

On a Holodeck deployment (web + worker), set:

PLAYGROUND_ASSET_API_BASE=https://assets.example.com
PLAYGROUND_ASSET_API_TOKEN=change-me

The Playground then builds from your library. Lock programs to @my-studio or a single pack with the Assets ▾ menu.

Deploy

Put it behind any TLS proxy and tell it its public URL so file links are absolute:

python3 holodeck_library.py serve --host 0.0.0.0 --port 8787 --token change-me --base-url https://assets.example.com
assets.example.com {          # Caddyfile
  reverse_proxy 127.0.0.1:8787
}

Files are public by default (so browsers can load them); --private-files requires the token there too. The index lives in <root>/.holodeck-index.json and refreshes itself as files change.

The API contract

Want to write your own server (in Node, Go, inside your asset manager…)? Implement these and Holodeck will treat it as a library. All JSON; Authorization: Bearer <token> if you use tokens.

Endpoint Returns
GET /api/v1/assets?q=&kind=&per=&page= { "assets": [Asset], "meta": { "current_page", "total_pages", "total_count", "per_page" } } — q: every word must match name/path/tags; an @scope/Pack token restricts to that path prefix. kind=prefab may return [].
GET /api/v1/assets/:id?viewer=1 Asset + "viewer": { "id", "name", "kind": "model", "glb_url", "model_url", "format", "unit_scale", "materials": [{ "texture_url" }], "material", "thumbnail_url" }
GET /api/v1/packs { "packs": [{ "key": "@scope/Pack", "name", "scope", "counts": { "model": n } }] }
files any absolute URLs, served with Access-Control-Allow-Origin: *

Asset: id (4–20 letters/digits), name, kind (model / prefab / texture), path, tags, unity_guid (or null), url, filename, thumbnail_url, and meta: { "has_geometry", "glb_url", "unit_scale", "stats": { "size_m": { "x", "y", "z" }, "triangles" } }.

Prefabs are optional: a library that has them returns kind: "prefab" and, in viewer, a prefab_tree plus prefab_parts — see the Playground API.