3. Development Modes
npm run dev runs installed Vite through Node and shopify theme dev in the current directory. Arguments are forwarded to Vite: npm run dev -- --host 0.0.0.0. A -- separator sends everything after it to shopify theme dev instead, for example vite-shopify-theme dev --host 0.0.0.0 -- --theme 123456789 (through a package script, add the separator your package manager needs before the arguments). Vite starts first, and Shopify CLI starts only after the plugin has written the development snippet, so the first sync includes snippets/vite-tag.liquid. If the snippet is not written within 30 seconds, a warning is printed and Shopify CLI starts anyway.
Editor mode
npm run dev:editor (or vite-shopify-theme dev --editor) gives the same live updates in the Theme Editor as in the local preview, without a tunnel or any external tool. Instead of serving assets from the Vite dev server, it runs vite build --watch and lets Shopify CLI sync the hashed build output to your development theme. Shopify CLI starts after the first successful build, and it runs with --live-reload full-page so the page reloads after every sync. Pass --live-reload (or set SHOPIFY_FLAG_LIVE_RELOAD) to choose another mode.
Choose a mode by where you work:
| Mode | Local preview | Theme Editor | Per-change latency |
|---|---|---|---|
dev (default) | Instant, with HMR | Only through a tunnel and the deprecated devOrigin | None |
dev --editor | About 1-2 seconds, full-page reload | Yes, no tunnel | About 1-2 seconds, plus upload |
vite build, then shopify theme dev | Snapshot | Snapshot | Rebuild by hand |
The default stays dev (HMR); see why editor mode is opt-in.
How it behaves:
- Assets keep content-hashed names. The plugin holds one ownership lock for the whole session and writes the snippet shortly after the assets it references.
- The previous build's assets stay in
assets/for one more build, and an asset is deleted only after two builds in a row no longer produce it. The Shopify CLI upload order is not guaranteed, so a page may briefly render without styles right after a change; a reload fixes it. - A failed build keeps the last working assets and snippet and the session continues after the next fix.
- Stopping the command releases the lock. The snippet stays as the generated build output (it is not restored to a placeholder as in
dev), and the last two builds stay inassets/until the next build removes the older one. - Tailwind classes used only in Liquid files are picked up because Tailwind watches those files.
Terminal output
dev and dev --editor print a short header before anything starts and a line when the session ends. Shopify CLI's own output is not parsed or changed.
vite-shopify-theme 0.7.0 · HMR
versions Vite 8.3.4 · Shopify CLI 4.9.3 · Node 26.12.0
store your-store.myshopify.com (environment: development)versionsnames Vite, Shopify CLI (when the project depends on it), and Node, which helps when you report a problem.storecomes from--store,SHOPIFY_FLAG_STORE, or the selected environment inshopify.theme.toml.- When that explicit folder does not exist yet at the moment Shopify CLI is about to start, a
warnline says so and, if an older@display-studio/vite-plugin-shopify-devtoolsis installed, names the version to update to. themeappears when Shopify CLI is given an explicit folder (--pathafter--, orSHOPIFY_FLAG_PATH), so a generated folder such as the theme mirror of@display-studio/vite-plugin-shopify-devtoolsis visible.- In editor mode an
assetsrow shows that assets are built toassets/and synced by Shopify CLI, with the live-reload mode. - In editor mode, every build prints one line,
[shopify-theme] build ok · 2 entries · 312 ms · snippet written, withsnippet unchangedwhen the generated snippet did not change. A failed build printsbuild failed · keeping the last good output, followed by Vite's own error. These lines also appear under a plainvite build --watch. - In editor mode the header is followed by a hint when
.gitignorelacks the generated-file patterns thatinitwrites, because Tailwind CSS then rebuilds in a loop (see Troubleshooting). - When both processes have stopped,
Stopped.says what was left behind: the restored development snippet, the generated snippet of editor mode, or a remaining lock to clean up.
Vite itself runs at the warn level under dev, so its banner, URLs, and build tables are hidden; warnings and errors still print. Pass your own level (vite-shopify-theme dev --logLevel info) or --raw to see everything Vite prints.
Colors appear only on an interactive terminal. They are off when the output is piped, when CI or NO_COLOR is set, or when TERM is dumb; the text is the same. Add --raw to print only Vite and Shopify CLI output, as before: vite-shopify-theme dev --raw.
Shopify environment
Create shopify.theme.toml in the theme root (keep it out of git; init ignores it):
[environments.development]
store = "your-store.myshopify.com"When this file defines [environments.development], dev runs shopify theme dev --environment development, so Shopify CLI does not ask for a store each time. init writes example.shopify.theme.toml as a template: copy it to shopify.theme.toml and set your store. Pass -e <name> or --environment <name> after --, or set SHOPIFY_FLAG_ENVIRONMENT, to choose another environment; dev then adds nothing.
The command preserves SHOPIFY_FLAG_PATH, forwards termination signals (on SIGINT and SIGTERM the plugin releases the lock, restores the snippet, and closes the Vite server for up to two seconds before it re-raises the signal, so other plugins can remove their temporary files), stops the sibling process when either exits, and propagates failures. On Windows, a shell is used only for the Shopify shim.
devOrigin (an HTTPS origin for a tunnel managed elsewhere, giving HMR inside the Theme Editor) is deprecated and will be removed in 1.0.0; the plugin warns with DEV_ORIGIN_DEPRECATED when it is set. Use dev --editor for a live Theme Editor without a tunnel. During development the snippet contains HMR and reload clients; the previous snippet is restored at shutdown. A live or uncertain lock fails safely.
Shopify CLI flags can be supplied through its documented environment variables. In particular, an existing SHOPIFY_FLAG_PATH is passed through unchanged, which is useful when the command runs from a workspace root. Shopify CLI reads npm's INIT_CWD before the real working directory, so the command sets INIT_CWD to the directory it runs in; a script started from a workspace root or with npm --prefix then still finds the theme and its shopify.theme.toml. Positional arguments after dev belong to Vite; they are not forwarded to Shopify CLI.
The command exits when either child exits and terminates the sibling. Spawn errors and non-zero exits produce a failing command. SIGINT and SIGTERM are forwarded so the plugin can restore the exact pre-development snippet before the processes finish.