Audience: consultant. You will be asked this on a call, and the answer has to be immediate.
The one sentence
There are two separate things that move, and they move independently: the CODE (the platform image) and the CONFIG (this client’s app — pages, schema, terms, report templates).
Almost every confusion about “why isn’t my change live” is these two being mistaken for one.
The two pipelines
CONFIG — what you author CODE — what we build
┌──────────────────────────────┐ ┌──────────────────────────────┐
│ edit a page in the builder │ │ a change in the TTP codebase │
│ ↓ autosave │ │ ↓ │
│ draft (dev) │ │ publish a numbered IMAGE │
│ ↓ publish │ │ ↓ │
│ snapshot → staging → prod │ │ upgrade the client's app │
│ ↓ deploy │ │ ↓ │
│ the client's app │ │ the client's app │
└──────────────────────────────┘ └──────────────────────────────┘
A deploy ships config. An upgrade ships code. Doing one does not do the other.
Step by step, and what each step actually does
1. Edit
Every keystroke autosaves to a draft over a live connection. The pill in the top bar tells you where your work is:
| Pill | Means |
|---|---|
| Draft saved — publish to make it live | The server has your draft. Safe to close the laptop; nobody else sees it yet. |
| Saving… | In flight. |
| Offline — not saved yet | Your browser has it and the server does not. Do not close the tab. |
| Not saved — the server refused this page: … | Something on the page is not finishable yet, so the server will not store it. The sentence after the colon names the exact field. Fix that, and saving resumes on your next edit — nothing you typed in between is lost. |
⚠️ “Draft saved” does not mean the client can see it. It means the draft is safe. Nothing reaches the client until a deploy.
⚠️ The red one matters. The server checks a page before storing it, and when it declines one it says so in its own words rather than leaving a green “Draft saved” over discarded edits. If you see it, you have not lost anything: your browser still holds every edit, and the moment the page is storable again the whole lot is saved at once.
2. Publish
Captures the current draft as an immutable snapshot and promotes it towards an environment:
dev → staging → prod. A promotion to production halts for approval by design.
⚠️ A page marked as an ARGUMENT has to be one before it ships. An argument page makes a case — a claim, the two to four reasons it is true, one lead exhibit, and every other exhibit placed under the reason it supports. One that is missing any of that is refused at every step that could put it in front of a reader: Publish, capturing a version, Deploy, and promotion. The refusal names the page, what is missing and what to do. Pages not marked as arguments ship exactly as before, and wording (a claim that reads like a label) is only ever pointed out, never refused.
⚠️ Publishing to staging does not put anything in front of the client. The deploy ships the last production snapshot — so a publish that stopped at staging means the deploy ships the previous release, successfully, with a healthy app and your page simply absent.
3. Approve
A human confirms the staging→production promotion. Gated on pipeline.approve.
4. Deploy
Takes the latest production snapshot and reconciles it into the client’s app.
| Ships with a deploy | Does NOT ship |
|---|---|
| Pages, widgets, layout | The platform code |
| Schema — entities and fields | Records (a client’s data lives only in their app) |
| Navigation, terms, definitions, the reporting timezone | Credentials (see below) |
| Report templates, rules, escalation chains | Installed custom widgets (see below) |
| Connection definitions | Outbound webhooks (see below) |
| Inbound webhook endpoints |
5. Upgrade
Moves the client’s app onto a new platform image. This is what carries renderer fixes, new widget types, the app shell, and anything else in the codebase.
⚙️ An upgrade has a pre-flight that refuses on blockers, rolls back automatically if it fails, restores the previous config, and re-confirms the app is answering afterwards.
The questions you will actually be asked
“I changed a page — when does the client see it?” After you publish it to production and deploy. Two steps, both yours.
“You fixed a bug last week. Why is it not in my app?” Because a code fix travels in an image, and this app is still running the previous one. It needs an upgrade, not a deploy.
“Can you undo it?” An app version, yes — release history has a one-click rollback per environment, with a safety check first. ⚠️ A single page, not yet by clicking — the capability exists on the API and has no button. Say so plainly rather than promising it.
“What is actually live right now?” Release history, per environment: the version, when it shipped, and a live badge. ⚠️ It does not yet show you a diff of what changed between two versions.
“I put a marketplace widget on a page and the app says ‘Widget not installed’.” Because the page ships and the widget’s INSTALL does not — it lives in a tenant table that no snapshot covers, and there is no deploy path for it yet. The studio renders it perfectly, which is what makes this one easy to miss. The publish dialog names every page carrying one before you ship, so you should never learn this from the client. Until the deploy path exists, keep custom widgets off pages a client will open.
“Can my client’s app push events to their ERP?” Not from the studio today. Outbound webhook subscriptions are authored at firm level (Platform ▸ Outbound Webhooks) and no deploy carries them to a client app — the subscription table is in no snapshot and no harvest. If a client’s app must push events out, the subscription has to be created on that app. Shipping it needs a decision about the signing secret, because the receiving system is the one holding it. Inbound endpoints are the opposite: they DO ship, with a fresh secret per deployment, so callers must be re-pointed.
“Where are my API keys?” Not in our studio. A connection’s definition ships with the deploy; the secret never does, because each app encrypts under its own key so that a staging app cannot read production’s credentials. Today a client administrator enters the key in their own app.
What this design costs you, honestly
⚠️ Two steps to get a change live, and nothing on screen tells you the end-to-end truth — “published to staging; production still runs v12”. Watch for it.
⚠️ A deploy verifies the app ANSWERS, not that it RENDERS. A server returning healthy HTML with a broken front end passes the health check. Open the app after a deploy to see it render.
⚠️ Config and code drift. An app can run last month’s image with today’s pages. That is normal and supported — but when something looks wrong, “which image is it on?” is the first question, not the last.