Skip to content

Data & storage

Two separate concerns live here: how the editor resolves content roots at build time, and how the backend and library service reach physical storage at runtime.

The editor reads five content roots from src/lib/pm-config.js. Each is a build-time process.env.PM_* value (inlined via webpack DefinePlugin) with a default that points upstream. We override the env vars to point at our own subdomains; the defaults stay upstream so the fork remains mergeable.

RootPoints atNotes
PM_API_ROOTapi.patternyard.devBackend API
PM_EXTENSIONS_ROOTextensions.patternyard.devExtension manifests
PM_DOCS_ROOTdocs.patternyard.devHelp links
PM_LIBRARY_ROOTlibrary.patternyard.devCostumes, sounds, backpack
PM_ASSET_CDN_ROOTlibrary.patternyard.devProject assets
PM_HOME_ROOTpatternyard.devLogin bridge + share targets

Only the backend and the library service touch physical storage. The user-facing surfaces never hold storage credentials.

Diagram

library. and the asset CDN have no source repo — they are content services. Rather than bulk-copying gigabytes of community assets up front, the library service uses mirror-on-demand: on a cache miss it proxies the asset from the upstream host and writes it to our Blob store, so subsequent requests are served locally. This gives independence without a multi-GB migration and degrades gracefully. A full bulk mirror can follow later if we want zero upstream dependency.

The backend builds cross-service URLs and links from environment variables rather than hardcoded hosts — see the environment reference:

  • ApiURL, HomeURL, StudioURL — used for redirects, share links, mod-log embeds, and email-verification links.
  • Storage credentials (MONGODB_URI/database URL, REDIS_URL/KV_*, BLOB_READ_WRITE_TOKEN) — live only on the backend project.