Theme CLI reference
Reference for the storeos theme commands — init, dev, check and package — their options, store data and connecting to the console.
storeos theme init [dir] [--blank] Create a theme
storeos theme new widget <name> [--page p] Add a widget and put it on a page
storeos theme new snippet <name> Add a snippet
storeos theme dev [dir] [options] Preview with live reload
storeos theme check [dir] Check the theme, the same way upload does
storeos theme package [dir] [--out file.zip] Check and zip the theme for upload[dir] is the theme folder. It defaults to the current folder, except for init, which creates ./my-theme. new works in the current folder. Run storeos theme --help for a summary.
The full command reference is at storeos theme. To install the CLI, see the CLI overview.
init
storeos theme init my-theme # the full starter theme
storeos theme init my-theme --blank # only the required files
storeos theme init . # in the current folderThe folder must not exist yet or must be empty. A .gitignore for zips is added too.
| Option | |
|---|---|
--blank | Only layout/theme.fluid, config/document.json and assets/theme.css, with empty widgets/ and snippets/ folders. The home page starts with a heading and a paragraph |
The full starter theme has a header, footer, hero, featured products, and a widget for every page (product, collection, page, blog, article, search), with snippets and translations. Read it to see how a complete theme fits together.
new
storeos theme new widget promo-banner # on the home page
storeos theme new widget size-guide --page product # on the product page
storeos theme new widget button # restyle a built-in widget
storeos theme new snippet product-cardnew widget writes widgets/<name>.fluid with a heading and a text setting to start from, and adds the widget to a page in config/document.json.
For a built-in widget name such as button or heading, it copies StoreOS's own markup instead, with the props the widget already gets. Change the markup and keep using those props.
Names are lowercase letters, numbers and dashes. An existing file is never overwritten.
| Option | |
|---|---|
--page <page> | The page to add the widget to: home (default), product, collection, page, blog, blog-post or search |
dev
storeos theme dev
storeos theme dev --port 3000 --open
storeos theme dev --data store.jsonServes the theme from your folder with the same engine stores use, so what you see here is what a store renders. Nothing is zipped or uploaded.
| Option | |
|---|---|
--port <n> | Port to listen on. Default 9292; the next free port is used if it's taken |
--host <host> | Default localhost. Use 0.0.0.0 to open the preview from a phone on the same network |
--storefront <url> | Load the real shop, catalog and SEO from a running storefront API, e.g. http://127.0.0.1:4001 |
--data <file> | Your own store data |
--document <file> | A theme document to use instead of config/document.json, e.g. one copied from a store's customizer |
--open | Open the preview in your browser |
--store <store> | Print a direct link to the console customizer for this store. Also the tenant uid for --storefront when the address has no tenant subdomain |
--console <url> | Allow a console on a custom domain (see Console connection) |
Files given with --data and --document are watched too.
Pages
| URL | |
|---|---|
/, /products/:handle, /collections/:handle, /collections/all, /pages/:slug, /blog, /blog/:handle, /search?q= | Your theme's pages, with the same routes as a store |
/__theme/widgets | Every widget in your theme on its own, with its default settings |
/__theme/widgets/<type> | One widget |
Other pages, such as the cart and checkout, show a notice: StoreOS renders them, not the theme.
Saving files
| You save | What happens |
|---|---|
A .css file in assets/ | The stylesheet is swapped in the page without a reload, so scroll position and state are kept |
| Any other theme file | The theme is re-read and checked, then the page reloads |
| A file with an error | The page shows the error with the file and line, and the terminal prints it. Fixing it recovers |
A widget that reads a props.<name> its schema doesn't list | It gets a guessed setting, and the terminal says so |
Tailwind stylesheets are recompiled on every save.
Store data
There is no built-in sample catalog. Until dev has store data, the preview shows a waiting page. Give it data with Connect local theme in the console, with --storefront <url>, or with --data.
To use a JSON file, pass it with --data. It uses the same shapes as the Storefront API. Lists you leave out are empty:
{
"shop": { "name": "My Shop", "currency": "BDT" },
"collections": [{ "_id": "c1", "name": "Shoes", "slug": "shoes" }],
"products": [
{
"_id": "p1",
"title": "Runner",
"handle": "runner",
"price": 2500,
"thumbnail": { "url": "https://example.com/runner.jpg" },
"collections": [{ "_id": "c1", "name": "Shoes", "slug": "shoes" }]
}
],
"pages": [],
"posts": []
}An image is { "url": "…" }, or { "key": "Some label" } for a placeholder with that label.
To see your real store's data without writing JSON, connect the theme to the console or use --storefront.
Console connection
While dev runs, the console customizer can load your theme straight from your computer, with your store's real data:
- In the console: Online store → Themes → Uploaded themes → Connect local theme.
http://localhost:9292is filled in. Change it ifdevprinted another port, then click Connect.
You can open the console before or after starting dev: it connects when the server is up and reconnects if you restart it. The header shows the connection: updates when you save, connecting or dev server stopped.
- Nothing is saved to the store. Save draft and Publish are replaced by Save to files (⌘S / Ctrl+S), which writes the document to
config/document.jsonin the short form. If you starteddevwith--document, that file is written instead. Keys the customizer doesn't edit, such asprerender, are kept. - ⋯ → Save as widget defaults writes the selected widget's settings as the defaults in its
{% schema %}, in the short form. This works for your own widgets, not built-in ones. - ⋯ → Copy JSON copies the document, the selected widget's props or its schema, if you'd rather paste them yourself.
- Reset → Discard changes reloads everything from your
config/document.json. - The terminal prints each file the console writes, e.g.
✎ config/document.json saved from the console. - New and changed widgets show up in the widget library as soon as you save them.
- Only
localhostaddresses can be connected.
Which consoles can connect
The dev server only shares your theme with StoreOS consoles, and only they can save to it: https://console.storeos.dev, any other https://*.storeos.dev address, and consoles running on localhost. It checks the address each request comes from, so you don't need any options. Other websites can't read your theme or write to it. The console can only write config/document.json and the schemas of widget files that already exist.
If you use a console on your own domain, allow it with --console:
storeos theme dev --console https://admin.example.comBrowsers
Use Chrome, Edge or Firefox. Safari blocks an https page from loading http://localhost. Chrome may ask whether the console can access devices on your local network: allow it.
check
storeos theme checkRuns the same checks as upload and prints every problem it finds. Errors (✗) stop an upload:
layout/theme.fluidorconfig/document.jsonis missing- A folder or file type that isn't allowed
- A
.fluidfile that doesn't parse - A
{% schema %}with invalid JSON, a setting without akind, or an unknown kind config/document.jsonuses a widget the theme can't render- A Tailwind stylesheet doesn't compile
Warnings (!) are likely mistakes that still render:
- A setting the markup never uses
- Settings guessed from the markup
- An unknown schema key or page name
- A
{% schema %}in a built-in widget, which is ignored - A built-in widget's markup that ignores the settings merchants change
Where it can, it suggests the fix:
! widgets/card.fluid: unknown {% schema %} key "lable" (did you mean "label"?)
✗ 1 error(s):
- config/document.json: uses widget "crad" but the theme has no widgets/crad.fluid (did you mean "card"?)It exits with code 1 when there are errors, so you can use it in CI. Warnings don't change the exit code. dev prints the same warnings when they change.
package
storeos theme package
storeos theme package --out dist/my-theme-1.2.zipChecks the theme, compiles Tailwind stylesheets and writes a zip, by default <folder name>.zip in the current folder. Only the theme folders (layout, widgets, snippets, assets, config, locales) are included. Hidden files are left out.
| Option | |
|---|---|
--out <file> | Where to write the zip |
Upload it in the console: Online store → Themes → Upload theme.
Troubleshooting
| Problem | Fix |
|---|---|
doesn't look like a theme | Run the command inside the theme folder, or pass the folder: storeos theme dev my-theme |
already exists and isn't empty | init only writes to a new or empty folder |
| This dev server can't save files | Your storeos theme is older than the console. Install the latest one and restart dev |
| The console says Dev server stopped | Start storeos theme dev again. The console reconnects by itself |
| The console can't connect | Check the port dev printed, use Chrome, Edge or Firefox, and allow local network access if asked |
| On macOS, the CLI is stopped as soon as it starts | You copied over the old file. Delete it first, then copy the new one |