Content server specifically for Decentraland Worlds (named scenes). Enables deployment and retrieval of world scenes that are identified by DCL names rather than parcel coordinates. Supports global portable experiences and single-scene loading.
This server interacts with DCL Names (ENS) for ownership validation, LiveKit for communications, and AWS S3 for content storage in order to provide users with the ability to deploy and manage isolated 3D scenes outside of Genesis City.
- Worlds Content Server
- World Deployment: Deploy and manage 3D scenes linked to Decentraland NAMEs (ENS or DCL domains)
- Access Control: Configure granular permissions for deployment, access, and streaming (allow-list, unrestricted, shared-secret, NFT ownership)
- Content Storage: Store and retrieve scene assets via IPFS-compatible content addressing using
@dcl/catalyst-storage(disk or S3) - Addressable URNs: Support for global portable experiences and single-scene loading via addressable URN format
- Ownership Validation: Validates that deployer wallet owns the DCL name specified in scene.json
- Live Data: Real-time information about active worlds and connected users
- Communications Service: Built-in communications adapter integration (LiveKit, WebRTC)
- Catalyst: Uses similar entity storage patterns and validation logic
- DCL Names/ENS: Validates ownership of DCL names for deployment authorization
- LiveKit: Optional communications adapter for multi-user experiences
- AWS SNS: Publishes deployment notifications
- PostgreSQL: Database for world metadata, permissions, and blocked wallets
- NATS: Message broker for internal event handling
- AWS S3 (optional): Cloud storage backend via
@dcl/catalyst-storage - Local Disk Storage (default): File system storage via
@dcl/catalyst-storage
The API is fully documented using the OpenAPI standard. Its schema is located at docs/openapi.yaml.
See docs/database-schema.md for detailed schema, column definitions, and relationships.
The service uses node-pg-migrate for database migrations. These migrations are located in src/migrations/. The service automatically runs the migrations when starting up.
Migrations are created by running the create command:
yarn migrate create name-of-the-migrationThis will result in the creation of a migration file inside of the src/migrations/ directory. This migration file MUST contain the migration set up and rollback procedures.
If required, these migrations can be run manually.
To run them manually:
yarn migrate upTo rollback them manually:
yarn migrate downBefore running this service, ensure you have the following installed:
- Node.js: Version 22.x or higher (LTS recommended)
- Yarn: Version 1.22.x or higher
- Docker: For containerized deployment and local development dependencies
- PostgreSQL: Version 14+ (or use Docker Compose)
- Clone the repository:
git clone https://github.com/decentraland/worlds-content-server.git
cd worlds-content-server- Install dependencies:
yarn install- Build the project:
yarn buildThe service uses environment variables for configuration. Copy the example file and adjust as needed:
cp .env.default .envSee .env.default for available configuration options.
In order to successfully run this server, external dependencies such as databases, message brokers, and storage must be provided.
To do so, this repository provides you with a docker-compose.yml file for that purpose. In order to get the environment set up, run:
docker-compose up -dThis will start:
- PostgreSQL database on port
5450 - NATS message broker on port
4222
To run the service in development mode:
yarn devThis will:
- Watch for file changes
- Automatically rebuild TypeScript
- Restart the server on changes
For production deployment, use the Docker image:
docker pull quay.io/decentraland/worlds-content-server
docker run --name wcs -p 3000:3000 \
--env COMMS_ADAPTER=livekit \
--env LIVEKIT_HOST=<your livekit url> \
--env LIVEKIT_API_KEY=<your api key> \
--env LIVEKIT_API_SECRET=<your secret> \
quay.io/decentraland/worlds-content-serverFor a deployment to be accepted by this server, the wallet deploying must own a DCL name. The scene must specify the name of the world in scene.json, and that DCL name must be owned by the wallet signing the deployment.
For more details on deploying scenes, please check out the documentation.
Once your signer address owns a DCL name, you can deploy to this server using the CLI tool:
# cd into your scene
cd my-scene
# then deploy
export DCL_PRIVATE_KEY=0x....
dcl deploy --target-content https://worlds-content-server.decentraland.orgUpon successful deployment, the latest version of the CLI should print some helpful information about how to preview the scene along with the addressable URN of the deployment.
A deployment in Decentraland can live anywhere as long as it complies with the format. To consistently identify deployments and their location in servers, the concept of addressable URN is introduced.
Let a valid deployment URN be:
urn:decentraland:entity:bafkreihpipyhrt75xyquwrynrtjadwb373xfosy7a5rhlh5vogjajye3im
That deployment will be downloaded from the configured content server by default. But for testing purposes, a baseUrl query parameter can be added: ?baseUrl=https://worlds-content-server.decentraland.org/contents/ yielding a full URN like this:
urn:decentraland:entity:bafkreihpipyhrt75xyquwrynrtjadwb373xfosy7a5rhlh5vogjajye3im?=&baseUrl=https://worlds-content-server.decentraland.org/contents/
There are two ways to use addressable URNs:
-
Global Portable Experiences: Generate experiences for all users (e.g., event calendars)
- Test by adding
GLOBAL_PX=<urn>query parameter to the explorer - Example:
https://play.decentraland.zone/?GLOBAL_PX=urn:decentraland:entity:...?=&baseUrl=https://worlds-content-server.decentraland.org/contents/
- Test by adding
-
Single Scene Loading: Load a specific scene instead of the full Genesis City
- Test by adding
SPACE=<urn>query parameter - Example:
https://play.decentraland.zone/?SPACE=urn:decentraland:entity:...?=&baseUrl=https://worlds-content-server.decentraland.org/contents/
- Test by adding
Portable experiences and single scenes (spaces) can be used at the same time to generate dynamic experiences.
This service includes comprehensive test coverage with both unit and integration tests.
Run all tests with coverage:
yarn testRun tests in watch mode:
yarn test --watchRun only unit tests:
yarn test test/unitRun only integration tests:
yarn test test/integration- Unit Tests (
test/unit/): Test individual components and functions in isolation - Integration Tests (
test/integration/): Test the complete request/response cycle
For detailed testing guidelines and standards, refer to our Testing Standards documentation.
For detailed AI Agent context, see docs/ai-agent-context.md.