Asset manager
Build with a shared asset library without filling your Git repository with large binary files. The loa CLI lets you reuse models, materials, images, and lighting across projects while keeping each application's asset choices in a small, reviewable manifest.
Pin an immutable version so a new upload cannot unexpectedly change your scene. Review asset updates alongside the code that uses them, try a different chair or lighting rig on a feature branch, and return to the previous selection when needed. Teammates and CI can pull the same verified native assets, with a shared cache that avoids downloading identical bytes for every project.
Start loading from the cloud without pulling files first, pull assets for offline work, or bundle them into a self-contained deployment. Mix published LoA assets with direct URLs and live local files as you develop, then publish the assets you want to share and pin. Your code keeps the same asset names as the project grows.
Select assets with your code
Install the CLI, then add an asset from your application's directory. Replace the example with a public asset you can access:
npm install -g @landofassets/cli
loa add acme/furniture/[email protected] --as chair
The CLI writes assets.json and assets-lock.json. Commit both with your code. The manifest says what you want; the lockfile records the resolved versions and native content hashes.
{
"name": "showroom",
"assets": {
}
}
Keys name bindings used by your code. Values contain the full source, even if you use the canonical org/project/asset name as the key.
Choose a source
| Source | Behavior |
|---|---|
Native LoA ref, such as acme/furniture/[email protected] | An immutable version with a verified content hash and shared global cache |
| Direct HTTP(S) URL | Loaded directly or pulled into the project cache, without integrity checks |
Live file: reference | Loaded from its original location; edits stay live and pulling leaves it untouched |
Only native LoA versions guarantee pinned bytes. Publish an asset when you need repeatable consumption; use URLs and local files for inputs that may change. See loa add for source syntax, aliases, and version selection.
Work from the cloud or locally
You can load native assets remotely without downloading them first. To work locally, pull the selected assets:
loa pull
All pulled files live in the project's gitignored asset_cache/. Native files come through the verified global store; direct URL downloads stay project-local. Live files stay at their original locations. The pull reference covers offline requirements, frozen lockfiles, refreshing URL downloads, and cache behavior.
Load assets in an application
The runtime maps binding names to URLs before the first load. Your code can use loa:chair with three.js loaders or obtain a URL directly with assets.url('chair').
Vite and three.js
Install the runtime:
npm install @landofassets/runtime
Add the plugin to vite.config.ts:
import { defineConfig } from 'vite';
import { loa } from '@landofassets/runtime/vite';
export default defineConfig({
plugins: [loa({ mode: 'remote' })],
});
Use remote for cloud loading or local after pulling to serve local files and include them in a production build.
For TypeScript, include the virtual module declaration in your application's environment declarations:
/// <reference types="@landofassets/runtime/virtual" />
Then use the generated map with a loading manager:
import * as THREE from 'three';
import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';
import { createLoaResolver } from '@landofassets/runtime';
import resolution from 'virtual:loa';
const assets = createLoaResolver({ resolution });
const manager = new THREE.LoadingManager();
manager.setURLModifier(assets.urlModifier);
new GLTFLoader(manager).load('loa:chair', (gltf) => scene.add(gltf.scene));
const chairUrl = assets.url('chair');
Without Vite
Use loa resolve to export asset-resolution.json. It prefers locally pulled files where present and remote URLs otherwise. Serve the map with your application, then load it before creating loaders:
import { loadLoaResolver } from '@landofassets/runtime';
const assets = await loadLoaResolver('/asset-resolution.json');
const chairUrl = assets.url('chair');
See the resolve reference for mode overrides, serving local files, and regenerating the map.
Review and change selections
Asset selections travel with code branches and reviews. Use the command references for individual operations:
| Command | Purpose |
|---|---|
loa add | Select an asset or change an existing binding |
loa remove | Remove a binding |
loa outdated | Find newer published versions |
loa update | Update selected versions |
loa publish | Publish an immutable version for consumers to select |
Publishing and selecting are separate actions, so a newly published version can be adopted through a code review. The publish reference covers authentication, versions, and server-side asset validation.
Share assets across workspaces
Large projects can keep an assets.json in each level, area, or package and list their directories in a root manifest:
{
"name": "world",
"assets": {},
"workspaces": ["levels/*"]
}
One root assets-lock.json records the combined selections. Each manifest owns its declarations; the runtime uses one shared binding namespace. See add, remove, and pull for workspace command behavior.
Maintain the shared store
The CLI provides loa store path, loa store status, and loa store prune. Their reference pages describe configuration and maintenance.
See the CLI reference for all commands and the SDK reference for programmatic catalog and publication APIs.