Features / Model

Type packs and inheritance

Maintain schemas once, use them in several sites. Three layers — repo, packs, site override — merged per field, not replaced per file.

Type packs page: a pack named editorial with two schemas, shared across spaces
Type packs page: a pack named editorial with two schemas, shared across spaces

Twenty client sites all need a blog post, an event and a person. Either you copy the schemas twenty times and maintain them twenty times, or you put them in a pack once and subscribe each site to it. RustyCMS does the latter — and still lets every site deviate where it has to.

Three layers

1. Repo defaults                    ./types/
2. Type packs (in subscription order)  <content>/_types/<pack>/
3. Site override (highest priority)    <content>/<site>/types/

Every site sees the sum of all three. A pack is maintained once; every subscribing site gets the change immediately — no copying, no deploy.

// <content>/site-a/.rustycms.json5
{
  locales: ["de", "en"],
  types: ["core", "press", "events"],
}

Merged per field, not replaced

This is where most inheritance models fall down: an override that wants to change one field has to copy the whole schema — and freezes everything else in the process. RustyCMS merges per field. A site override names only what differs: an extra field, a different label, a stricter pattern. Everything else keeps coming from the pack, and a new pack field shows up in sites whose override doesn’t know about it.

Boolean flags are OR-merged — an override can switch required on, but never silently off. Field order is preserved; missing entries are appended.

Manage without file access

Packs and subscriptions go through the API and the admin UI: create a pack, put a schema in it, subscribe a site, reorder. Every write rebuilds the cascade for all sites and invalidates the cache. If you’d rather edit files: the watcher covers _types/ too, a direct edit has the same effect.

curl -X PUT /api/environments/site-a/type-packs \
  -H "X-API-Key: $KEY" -d '{"packs":["core","press"]}'

# Check the resolved schema — the way the site sees it
curl /api/collections/press_release?_environment=site-a

Deliberately left out

No “pack A inherits from pack B”, no pack dependencies, no conditional schemas, no loading from remote URLs. Three layers and one clear merge can be explained. A graph of packs cannot.

Want to see this on your own project?

Tell me briefly what you're planning. I'll show the admin UI on a real installation and say honestly whether it fits.

Request early access