Skip to main content

Theme Development

Use theme pull, theme diff, theme push, and theme watch to sync files between your local machine and a theme installation on your store via the Fork workflow.

info

Before using these commands, run theme authorize to connect the CLI to your store. See Fork workflow for setup instructions.

Pull

Download all theme files from a theme installation to your local working directory:

nuvemshop theme pull

The CLI fetches every file in the installation and writes them to your current directory, preserving the theme's folder structure:

my-theme/
├── blocks/ ← Block templates (.tpl)
├── config/ ← Settings schema and merchant settings
├── layouts/ ← Main HTML shell
├── locales/ ← Translation files
├── sections/ ← Section templates (.tpl)
├── snippets/ ← Shared partials (.tpl)
├── static/ ← CSS, JS, and other assets
├── templates/ ← Page templates (.json)
└── manifest.json ← Generated by the CLI (not part of the theme)

manifest.json

After pulling, the CLI generates a manifest.json file in your working directory with metadata about the installation:

{
"theme": "ipanema",
"theme_version": "1.0.0",
"forked": false,
"revision_token": "<REVISION_TOKEN>",
"installation_id": "4541834"
}

This file is local only — it's never uploaded when you push or watch. It helps you keep track of which installation and revision your local files came from.

Options

OptionDescription
--theme-id <id>Target a specific installation (defaults to the installation linked to this directory in .nuvem)
--publishedUse the store's published theme instead of --theme-id or .nuvem
--token <token>Authentication token (CI use )
-ySkip confirmation prompts
-vEnable verbose output
danger

Pulling overwrites local files. If you have uncommitted changes, commit or stash them before pulling.

Push

Upload your local theme files to the theme installation:

nuvemshop theme push

The CLI reads each local file, determines its format based on the file extension, and uploads it to the installation:

ExtensionUpload format
.jsonParsed and sent as JSON
.tpl, .css, .js, .svgSent as text
Everything elseSent as base64-encoded binary

Incremental push (smart push)

Before uploading, the CLI compares each local file against its remote version and only uploads the ones that changed. Unchanged files are reported as skipped and no request is made for them — this speeds up pushes and reduces API rate-limit consumption.

The CLI also syncs deletions: files that exist on the remote installation but not in your local directory are removed from the installation during push.

To force every file to be uploaded without remote comparison, use --force:

nuvemshop theme push --force

Options

OptionDescription
--theme-id <id>Target a specific installation (defaults to the installation linked to this directory in .nuvem)
--publishedUse the store's published theme instead of --theme-id or .nuvem
--forceUpload all files without remote comparison (skips unchanged-file detection)
--token <token>Authentication token (CI use )
-ySkip confirmation prompts
-vEnable verbose output

What gets uploaded

The CLI uploads all files in your working directory, with these exclusions:

  • Dot-prefixed paths — files and directories starting with . (like .nuvem, .git, .vscode) are always skipped
  • manifest.json — the local manifest is never uploaded
  • Fork-restricted paths — if the installation is not forked, only templates/ and config/settings_data.json can be pushed (see below)

Empty files (zero bytes) are not exclusions — they trigger a per-file upload error, and the overall push reports as failed.

Fork rules

Before pushing, the CLI checks whether the target installation is forked. This determines which files you're allowed to upload:

Non-forked installation — you can only push customization files:

  • templates/** — page templates (.json)
  • config/settings_data.json — merchant settings

Forked installation — you can push any file in the theme.

Files outside the allowed paths are silently skipped. If you need to modify layouts, sections, blocks, or other theme code, fork the installation first.

Diff

Show what a theme push would change — without uploading anything:

nuvemshop theme diff

The CLI compares the files in your local directory against their remote version on the installation and prints the differences grouped by change type: added, modified, and deleted files (files that exist on the remote but not locally, which push would remove).

Theme diff for theme 4541834 (forked) — 3 changes

Added (1)
+ sections/new-banner.tpl 42 lines

Modified (1)
~ config/settings_data.json

Deleted (1)
- snippets/old-badge.tpl

Unchanged: 214

theme diff follows exactly the same rules as theme push — the upload exclusions and fork rules apply identically. Files that push would skip are reported as skipped, not as changes:

  • Skipped (not forked, but has changes) — theme code with local changes on a non-forked installation. Push wouldn't upload these files; fork the installation to be able to push them.
tip

Reformatting a .json file (changing indentation or key order) doesn't count as a change. The CLI compares the JSON's semantic content, not the file's bytes, so running a formatter like Prettier won't produce false diffs.

Detailed diff

With --detailed, the CLI also fetches the remote content of modified and deleted files and prints a git-style unified diff for each one, along with added and removed line counts:

nuvemshop theme diff --detailed
Theme diff for theme 4541834 (forked) — 1 change

Modified (1)
~ sections/header.tpl +3 -1
--- remote/sections/header.tpl
+++ local/sections/header.tpl
@@ -12,7 +12,9 @@
<div class="header__logo">
- {{ store.name }}
+ {% if settings.show_logo %}
+ {{ store.name }}
+ {% endif %}
</div>

Unchanged: 214

Some files have no full textual diff, and the CLI states the reason on the file's own line:

MarkerMeaning
binary, 12.4 KB → 18.1 KBBinary file (images, fonts): only sizes are compared
line endings onlyThe content is identical; only the line endings differ (CRLF vs LF)
diff truncatedThe file exceeds the 500 patch-line-per-file budget; the diff shown is incomplete
remote content unavailableThe API didn't return that file's remote content, so it couldn't be compared line by line

JSON output

Use --json for machine-readable output, useful in CI or scripts:

nuvemshop theme diff --json
nuvemshop theme diff --json --detailed

In JSON mode, stdout holds only the payload — progress messages are suppressed, so you can pipe the result straight into jq:

{
"theme_id": "4541834",
"forked": true,
"detailed": false,
"in_sync": false,
"summary": {
"added": 1,
"modified": 1,
"deleted": 0,
"unchanged": 214,
"skipped_not_forked": 0,
"skipped_push_unsupported": 0,
"read_failures": 0
},
"added": [
{
"path": "sections/new-banner.tpl",
"format": "text",
"lines": 42,
"size_bytes": 1187
}
],
"modified": [{ "path": "config/settings_data.json", "format": "json" }],
"deleted": [],
"skipped_not_forked": []
}

The in_sync field is true only when there are no changes, no files skipped for lack of a fork, and no read failures — that is, when the local directory matches the remote theme. With --detailed, each file entry also carries lines_added, lines_removed, truncated, note, and the unified diff as a string in patch.

Options

OptionDescription
--theme-id <id>Target a specific installation (defaults to the installation linked to this directory in .nuvem)
--publishedUse the store's published theme instead of --theme-id or .nuvem
--detailedInclude a unified diff of what changed inside each file
--jsonMachine-readable JSON output
--token <token>Authentication token (CI use )
-vEnable verbose output
info

theme diff is read-only: it never uploads, deletes, or modifies files — neither remotely nor locally. That's why it asks for no confirmation and takes no -y.

Watch

Watch your local files and automatically push changes on save:

nuvemshop theme watch

Watch mode monitors your working directory for changes. When you save a file, it's uploaded to the installation immediately. When you delete a file locally, it's deleted from the installation too.

The same upload rules and fork restrictions from theme push apply — watch mode won't upload files that push would skip.

Browser reload

By default, the CLI opens a Puppeteer-driven browser window showing the storefront with the ?theme_installation_id=<id> preview parameter, so you see the installation you're working on (not the productive one). After each successful push or delete, the page is automatically reloaded. Use --no-browser to skip this.

tip

The browser feature uses Puppeteer, which may need to download Chromium on first run. Use --no-browser to skip this and rely on manual browser testing instead.

Options

OptionDescription
--theme-id <id>Target a specific installation (defaults to the installation linked to this directory in .nuvem)
--publishedUse the store's published theme instead of --theme-id or .nuvem
--no-browserDon't open or reload a browser window
--token <token>Authentication token (CI use )
-vEnable verbose output

Typical development workflow

A common development cycle looks like this:

  1. Create or clone an installation to work on: nuvemshop theme create --base-theme ipanema --title "My Theme" or nuvemshop theme clone
  2. Pull the installation files (links the directory to that installation): nuvemshop theme pull --theme-id ID
  3. Fork if you need to edit theme code: nuvemshop theme fork
  4. Start watch mode: nuvemshop theme watch
  5. Edit templates, sections, and settings in your editor — changes sync automatically
  6. Preview with the auto-reloading browser, or generate a link: nuvemshop theme preview
  7. Confirm local and remote are in sync before publishing: nuvemshop theme diff. Watch mode only uploads changes it observed while running, so this catches files you edited before starting watch — or while it was stopped. Add --detailed to inspect anything it reports.
  8. Publish when ready: nuvemshop theme publish