Push to a live site
Goal: change components on a site that editors are already using, without removing something that is on a page.
The quickstart pushed one component to an empty library. A site with real pages on it is a different problem: npx canvas push is a one-way sync, not an upload, and the thing it syncs is your whole component directory against the site’s whole component library.
What you’ll have when you’re done
Section titled “What you’ll have when you’re done”- A project whose
src/components/matches the site, so no push plans a delete you did not intend. - The habit of reading the plan and cancelling a push that does not match it.
- A component pushed to the site disabled, checked in Drupal Canvas, then enabled.
- A known-good commit, and a push that puts the site back on it.
Prerequisites
Section titled “Prerequisites”- A component project connected to your site with working Canvas CLI credentials (Canvas quickstart)
- A site that already has components, and at least one Canvas page built from them
- git, with the component project committed
-
Know what push compares
Section titled “Know what push compares”Before it changes anything,
canvas pushasks the site for its component list and compares that list against yoursrc/components/directory. The comparison is by machine name, and it decides the operation:In src/components/On the site Planned operation yes no createyes yes update: your local source replaces the site’s copy in fullno yes deleteThe last row deletes components you never touched. A component your teammate created in the browser, or one an earlier project shipped, is a
deletethe moment you push from a directory that does not contain it. This is why a partial checkout is dangerous and a--yespush from one is worse.Two behaviors soften it, both worth knowing exactly:
-
Pages are not deleted by absence. Removing a page spec from
pages/and pushing left the site’s page in place, and no page delete appeared in the plan. Only components are removed by being missing. -
An empty component directory deletes nothing. With no discoverable components locally, the CLI skips the component stage rather than treating the site’s whole library as unwanted:
┌ Drupal Canvas push│● No components found. Skipping component and global CSS push.││ Plan│ Pages: 1 update
Global regions go through the same reconcile when the project has a
regions/directory, so give a region you are not pushing the same care as a component. Version pages and regions as code covers what those specs contain. -
-
Reconcile your project with the site before you push
Section titled “Reconcile your project with the site before you push”The safe order is always pull, then push. Pulling brings down everything the site has, so the next push plans no deletes:
Terminal window npx canvas pull --skip-overwrite│ Plan│ Components: 2 pull (1 new, 1 existing)│◇ Pulled components││ Succeeded: alpha-card│ Skipped (already exists): beta-banner│└ Pull completed--skip-overwriteis the flag that makes this safe to run mid-change: without it, pull writes over local files that already exist, including the component you are in the middle of editing. Commit before pulling either way. -
Read the plan, then confirm or cancel
Section titled “Read the plan, then confirm or cancel”There is no
--dry-run. The confirmation prompt is the preview, and it is the only one:Terminal window npx canvas push┌ Drupal Canvas push││ Plan│ Components: 1 create, 2 delete│ Pages: 1 update│◆ Push these changes to https://your-site.example.com?│ ● Yes / ○ No└Answering
Noends the run before any write reaches the site:◇ Push these changes to https://your-site.example.com?│ No└ Operation cancelledNothing was created, updated, or deleted; the plan step only reads. Two limits to read the plan with:
- It counts, it does not name.
2 deletedoes not say which two. To find out, run the pull in step 2 and see which component directories appear that you did not have. - It does not diff. An
updateis planned for every component that exists on both sides, whether the source differs or not, so1 updatetells you nothing about what that update will change.
--yesskips the prompt. That is what CI wants and what your first push against a live site does not. - It counts, it does not name.
-
Push a new component disabled first
Section titled “Push a new component disabled first”canvas scaffoldwritesstatus: falseintocomponent.yml, and the push keeps that flag. The component is created on the site, built the way the site builds it, and disabled, so nothing can place it on a page:src/components/alpha-card/component.yml name: Alpha CardmachineName: alpha-cardstatus: falseTerminal window npx canvas pushUntil you set
status: trueand push again, anything that references the component is rejected, including a page spec of your own:│ Failed│ ✗ Landing (pages/landing.json)│ elements.aaaaaaaa-1111-4111-8111-aaaaaaaaaaaa.type:│ Component "js.alpha-card" is disabled. Set "status: true" in its component.yml to enable it.This is the closest thing to a staging step the CLI has. It does not give you a second site, but it does separate “the push worked against the real site” from “editors can now use this”, which is the part that is hard to take back.
-
Change a component that is already on pages
Section titled “Change a component that is already on pages”An
updatereplaces the site’s stored component wholesale, and that stored component is the same record the browser code editor writes to. So a push overwrites whatever changed on the site since your last pull, silently. A component whose source had been changed on the site came back from the next push with that change gone, and the plan for that push read onlyComponents: 1 update.The update path therefore has one rule: pull before you edit, commit before you push. That commit is what step 7 rolls back to.
Existing props and slots carry their own constraints across an update (a prop’s type cannot change, a slot cannot be renamed without orphaning what editors put in it); those are in the Canvas CLI and schema reference.
-
Delete a component on purpose
Section titled “Delete a component on purpose”Delete the directory from
src/components/, then push. The site, not the CLI, decides whether the delete is allowed:Terminal window rm -rf src/components/alpha-cardnpx canvas push┌ Drupal Canvas push││ Plan│ Components: 1 create, 2 delete│ Pages: 1 update│▲ Pushed components││ Deleted: epsilon-strip│ Created: zeta-strip││ Failed│ ✗ alpha-card│ This code component is in use in a default revision and cannot be deleted.│└ ✗ Push failedRead that transcript carefully, because it answers the two questions that matter most on a live site.
A component an editor has placed cannot be deleted. The site refuses, and the message names which kind of use is blocking it:
in a default revision(it is on a published page),in a Canvas auto-save(someone has an unsaved draft holding it), orin the latest revision(a pending revision holds it). Remove the component from the pages that use it first, in Canvas or in the page specs, then push the delete again.A push is not all-or-nothing. In that same run one component was created and another deleted, and both stuck, even though the run ended
✗ Push failed. The planned page update never ran.✗ Push failedand✗ Push incompleteboth mean some of the plan may already be live, so treat a failed push as a state to inspect, not a change to ignore. (A failure in the local build or lint stage is different: that happens before anything uploads, so nothing reaches the site.) -
Get back to a known-good state
Section titled “Get back to a known-good state”There is no undo command. Recovery is the two directions of the sync you already have.
To put the site back after a bad push, check out the commit whose source was good and push it:
Terminal window git checkout -- src/components/alpha-cardnpx canvas pushThe next
updateoverwrites the site’s copy with the restored source, which is exactly the behavior that made the bad push dangerous, now working for you. The round trip holds: a change pushed to the site was gone from the site again after checking out the previous source and pushing a second time.To recover a component you deleted locally but have not yet pushed, take it back from the site:
Terminal window npx canvas pull --skip-overwriteThat rewrites the component’s directory (
component.yml, the source file, and its CSS) from the site’s copy, and leaves everything else alone. It only works while the component is still on the site: once a push has deleted it there, git is the only copy left, which is the reason for the commit in the prerequisites.
When something goes wrong
Section titled “When something goes wrong”This code component is in use in a default revision and cannot be deleted.
the component you removed from src/components/ is on a published page. The site blocks the delete on purpose, so the pages that use it keep rendering. Either put the directory back (git checkout -- src/components/<name>, or npx canvas pull --skip-overwrite) if the delete was accidental, or remove the component from those pages first, in Canvas or in the page specs under pages/, and push again.
This code component is in use in a Canvas auto-save and cannot be deleted.
same block, different holder. Somebody has unsaved editor changes that still place the component; a draft counts as a use. Ask them to publish or discard, then push again.
This code component is in use in the latest revision and cannot be deleted.
a pending revision that has not been published yet still places the component. Publishing that revision must not render a gap, so the delete is refused until the revision no longer uses it.
The plan shows deletes you did not ask for
your src/components/ does not have everything the site has, and push treats absence as deletion. Cancel at the prompt (nothing has been written yet), run npx canvas pull --skip-overwrite, and look at which directories appeared. Those are the components the plan was about to remove.
Component "js.<name>" is disabled. Set "status: true" in its component.yml to enable it.
a page or region spec places a component that is on the site but not enabled. canvas scaffold writes status: false, and it is easy to push the component and forget the flag. Set status: true in that component’s component.yml and push again.
✗ Push failed or ✗ Push incomplete, and the site changed anyway
expected. The component, asset, page, and region stages run in order and each applies as it goes, so a failure in one stage leaves the earlier ones live. Re-read the run’s Deleted: / Created: / Updated: lines to see what landed, fix the reported failure, and push again; whatever already succeeded plans as an ordinary update the second time and is safe to re-apply.
No components found. Skipping component and global CSS push.
the CLI discovered nothing to build in componentDir. On a live site this is a safe outcome rather than a destructive one (it plans no component deletes), but the push you wanted did not happen. Check you are in the project root, that componentDir in canvas.config.json matches where your components are, and that each directory has both a component.yml and its source file.
A pushed change is not visible on the site
confirm the push reported the component under Updated: and not just in the plan, then reload the page rather than the editor. If the component looks stale in Canvas specifically, the built assets are the thing to re-check: a push uploads the component and the global CSS build together, and a --no-pages-style flag never excludes those.
Next steps
Section titled “Next steps”- Version pages and regions as code: what a page spec is, and how to edit one.
- Render CMS content with content templates: bind component props to entity fields instead of typed-in values.
- Canvas CLI and schema reference: every flag on
pushandpull, and the full component schema.
Was this page helpful?
What went wrong?
Still stuck? Contact Acquia Support (opens in a new tab)