Guides · Publishing

Environments

Every space has develop, staging and production, each with its own model and content. What each keeps separate, how promoting moves content and the model between them, and exporting and importing content as a file.

6 min read

Every space has three environments: develop, staging and production. Each holds its own copy of the content model and of the content, so new content types and new content can be built and checked in develop before anyone sees them in production.

What each environment has of its own

Shared by all three: the space's locales, assets, members and Shopify store. An entry keeps the same id in every environment, so references between entries still point at the right entry after they move.

A production site uses a production token and gets production's webhooks. Switch environments with the selector in the dashboard's sidebar. Live is the production environment: the dashboard calls it live, and the API, the CLI and these docs keep production.

Promoting

Promote copies content from the environment you are in to another one: every entry, or the ones you pick. An entry's Promote… button starts with that entry picked.

  1. Choose where to, and whether to bring the content model along (admins and developers). Bring it when the target doesn't have a content type the entries use yet.
  2. Show what would change lists every entry as new, updated or unchanged, which ones it publishes, and which have unpublished edits made in the target that it would replace (a draft that came with an earlier promotion doesn't count). Folders and parent pages the target is missing, and entries that promoted entries reference, are added for you ("Needed by …").
  3. Publish live entries on … too (named after the target, like Publish live entries on staging too) is on to start with. It only publishes what is published where you are, with its published version: drafts stay drafts, and newer unpublished edits arrive as a draft on top. Untick it to bring drafts only: nothing is published in the target, so entries arrive there as drafts and changes for someone to review and publish. An entry already published in the target also keeps its name and place there (parent, slug, order), since those reach the site at once; a new name or place comes with the next promotion that publishes, or by moving it there. Entries not published in the target take the new name and place.
  4. Promote does it all in one go, or nothing at all when anything stands in the way: content the target's model refuses, a path another entry already uses there, a reference to an entry that doesn't exist.

What a promotion does to each entry:

  • its draft replaces the target's draft;
  • if it is published, the same published content is published in the target, sending entry.published webhooks there (unless Publish live entries on … too is off);
  • nothing is ever unpublished in the target;
  • the entry's status carries over: one with unpublished edits stays "changed".

The content model is applied first and never prunes: types that only the target has are kept.

The plan also lists the entries only the target has: ones created there, or deleted where you are promoting from. They are left alone unless you tick them; ticked entries go to the target's trash, restorable for 30 days, and published ones send entry.deleted. A folder can only go with everything in it, and an entry only when nothing staying in the target uses it.

Promoting drafts only needs no publish rights: into an environment where publishing is reviewed, anyone who edits content can, and the entries wait there for review.

Agents promote through POST …/promotion/plan and POST …/promotion/apply in the agent API; "publish": false brings drafts only.

Production is set up by a person

Agents can do most things in every environment, but in production they can't create or revoke API tokens, add or delete webhooks, or change the preview URL or prompt endpoint. Those hand out credentials or send content to new URLs, so someone with the admin or developer role does them in the dashboard.

Export and import

Settings → Export and import has two parts. Export downloads the environment you are editing, Import puts a content export back into it.

Export → Content export downloads one JSON file: the content model, every entry with its draft, published content, place in the tree and slugs per locale, and which assets the content uses. Keep it as a backup, or import it into an environment of the same space. Export → Plain SQL is a zip of plain SQL for another tool, described under taking your content elsewhere; Obelism never imports it back.

Import reads one file: a content export from an Obelism environment ("format": "obelism-content-export", "version": 1), at most 10,000 entries and 32 MB. Not SQL, not a zip, and not another tool's export. Download a template gives the same shape with this environment's content model and one example entry, to fill in or hand to a tool.

Importing a file works like promoting from it: Show what the file would change plans it, entries are created or updated by id, published ones are published, nothing is unpublished, and nothing happens at all when something stands in the way. Entries the environment has but the file doesn't are listed; tick them to move them to the trash, which restores a backup exactly. Tick Include the file's content model to apply its model first.

Assets aren't in the file, only their ids: they belong to the space, so a file restores into the space it came from. Content that uses an asset the space doesn't have is reported, and nothing is imported.

Agents and scripts use GET …/export, POST …/import/plan and POST …/import/apply ({ "file", "includeModel"?, "remove"? }) in the agent API. A management token with the content scope can export and import content (not the model), for scheduled backups.

Taking your content elsewhere

There is no lock-in: Settings → Export and import → Export → Download … as SQL downloads a zip of plain SQL, independent of Obelism:

  • schema.sql creates four tables: content_types, entries, entry_paths and redirects.
  • content_types.sql, entries.sql, entry_paths.sql and redirects.sql hold the rows as INSERT statements, and import.sql has all of them in dependency order inside a transaction.
  • README.md explains the columns and the JSON in them: localized values keyed by locale, rich text as ProseMirror, blocks as _type, references and assets as ids.

This is a way out, not a backup: Obelism doesn't import it back. Assets are files in the Media library, so download the ones your content uses separately; the export names their ids. GET …/export/sql in the agent API answers the same files as { name, content } entries.

On this page

Marks in the margin

  • Note
  • Watch out
  • Updated

Scribes marked doubtful lines in the margin. That practice is called obelism.

Stuck on a step?