Self-hosting
A live project runs two reference services: a resolver and an effects runner. You run both on infrastructure you own. The resolver holds no signing key.
The resolver
The resolver re-indexes the chain's event logs into a local projection and serves the token API. It is read-only. Its endpoints include:
GET /t/{chainId}/{address}/{tokenId}: ERC-721 token metadata, and.../imagefor the image.GET /c/{chainId}/{address}: ERC-7572 collection metadata.GET /api/project/{address}: the full reconstructed project state, includingabx_provenance.GET /d/{chainId}/{address}: a per-contract dashboard.GET /health.
Run it locally with abx serve. This also runs a chain watcher that polls for new logs, about every
12 seconds, and re-indexes each registered project. Deploy it to a host with
abx deploy-resolver --provider <fly | render | vps>, which writes a self-contained deployment
artifact for that target. The production image installs @artblocks/abx-cli from npm and runs without
a browser.
Because a resolver re-indexes from the chain, moving to a new host is a configuration change. See
The effects runner
A code project's still image is rendered off-chain, so the resolver image stays browser-free and a separate runner does the rendering. The runner uses Playwright and Chromium. It watches the spine, renders new mints and parameter changes, and publishes each render to the resolver.
- Run it locally with
abx effects. Add--onceto sweep every project once and exit. - Host it with
abx deploy-effects --resolver-url <https://your-resolver>. - Render one project's missing stills with
abx render <address>.
Set ABX_EFFECTS_URL on the resolver so its chain watcher notifies the runner as soon as something
changes. A periodic sweep is the fallback.
Storage
The resolver and runner read and serve the source bytes from a storage backend. For a hosted pair, use a shared, addressable backend such as IPFS, Arweave, or S3-compatible cloud, not local disk. See Storage.
Migrating
abx migrate <address> --from <source-resolver-url> --to <dest-resolver-url> moves a project's
off-chain state to a new resolver. It reconstructs the on-chain truth, copies the source resolver's
off-chain values (description, external URL, off-chain traits, image locators), re-pins images to a
durable backend after verifying them against the on-chain hash, and runs a parity check between source
and destination. It does not cut over: you re-point DNS, or the on-chain base URI with set-token-uri
and set-contract-uri, when you are ready. The two resolvers never talk to each other.