Install a theme and load its demo content
A theme is the storefront: what the customer sees. The panel and the store run separately, so changing theme does not touch your products or your orders.
A theme is the storefront: what the customer sees. The panel and the store run separately, so changing theme does not touch your products or your orders.
Installing it
There are two ways.
Uploading its .zip. Panel → Themes → Install theme, and choose the
file. Nothing is installed yet: the package is unpacked into a quarantine
folder and you are shown a report first —
- The signature: signed by whom, unsigned, or "The signature is not valid"
(the package changed after it was published, and it does not install).
Unsigned installs, with a warning; with
THEMES_EXIGIR_FIRMA=1only packages signed by a key on your trusted list do. - What would run: the install, build and start commands. They are chosen by the system from the theme type, not written by the theme.
- The contract and the review: errors and warnings in
theme.json, what blocks installation, what is worth checking, and the domains it talks to.
Only if nothing blocks it can you press Install. If a theme with the same id is already there, you are offered Replace the installed one; your customisation is stored separately and is not lost.
The package has limits, and going over any of them refuses it: 100 MB the
.zip, 400 MB unpacked and 20,000 files. A file that tries to write
outside its folder is refused too.
Copying the folder. Copy the theme folder into themes/. The panel reads
that folder off disk: as soon as it has a valid theme.json, it appears in
Panel → Themes. This way there is no report: you are trusting what you
copied.
If your themes live somewhere else, say so with THEMES_DIR in the .env. It
is read by both the panel and the backend, so both have to point at the same
folder: in Docker it is /app/themes.
Each theme declares in its theme.json which stack it uses (Next, Astro, Vite,
Nuxt…), what pages it brings and what environment variables it needs. That is the
theme contract, and it is what lets themes of
different technologies live in the same catalogue.
Loading its demo content
Only for a freshly installed store. Demo content is for trying a theme on an empty shop, not for dropping sample products into a shop that already sells.
The theme's card has an Add its sample content button. It shows you what it brings before you put it in — how many products, how many categories, and whether the content is valid — and Add to my catalogue imports it.
It is refused (with a 409 and the reason) as soon as the store has a single
product of its own —one that did not come from a demo— or a single order.
And when that happens the store is marked as in use, for good: deleting
those products later does not make it fresh again.
On import:
-
It deletes nothing. Whatever you already had stays.
-
It is idempotent. If a product already exists with the same identifier, it is updated rather than duplicated. You can import twice without worry.
-
It goes to the first sales channel that exists in the store (the oldest one). Not to a channel of the theme's own.
-
It does not give you a publishable key. The key your theme needs is the store's, the one created at install time:
docker compose exec backend cat /app/data/clave-publicable.txtPut it in the theme's
.env(COMMERCE_KEY, orVITE_…/NEXT_PUBLIC_…depending on the stack): without that key its site sees no products, and the error does not say a key is missing.
The import dialog still talks about "a sales channel of its own" and a key to copy. That text is out of date: what happens is what is described here.
Activating it
Activate only sets which theme is the active one: it is what the panel then customises. It does not change the public site, and it does not build or start anything.
Publishing it: what the customer sees
The storefront is a separate application. To put a theme in front of customers, the theme's card has Publish, which opens a dialog with these buttons:
- Publish — installs its dependencies, builds it, starts it on a free port and checks that it responds. Only if it responds does it switch over; if anything fails along the way, what is live keeps serving. A theme sold under licence without a valid one is refused here.
- Try without publishing — the same build, left as a draft. With the
router running, you get a preview link (
?vista=<token>) that works on the public domain and expires in 48 hours. Without the router, you gethttp://localhost:<port>, and that is all. - Roll back to the previous one — puts the previous publication back. It only appears when there is one, and it needs the router.
- Stop — stops a draft that is running and frees its port.
The router
The router is a small proxy that listens on the public port
(THEMES_PUERTO_PUBLICO, 3000 by default) and forwards to whichever version is
published. It is what makes switching happen without downtime, and what
makes drafts and rolling back possible:
cd apps/admin && npm run enrutadorWithout it, publishing has to stop the old process before starting the new one —a few seconds of downtime— and Roll back is refused.
🔴 docker-compose.full.yml does not start the router. None of the compose
files do. If you want it, you run it yourself.
Customising it
Customise opens the editor: colours, fonts, copy and home-page blocks,
according to what the theme declares in its settings.schema.json. It is saved
per store, so updating the theme does not overwrite your configuration.
When something is off
"0 products" on the site → the publishable key is missing from the theme's
.env, or points at a sales channel that is not the one where the products are.
The sample content will not import → the store is no longer fresh: it has products of its own or orders. The panel says which.
"This theme has no sample content." → it has no demo/contenido.json. Not
an error, it just does not ship one.
Roll back is refused → the router is not running.
See also
- Theme contract — what a theme must meet
- Theme security — the risk in installing a third-party one
- Build a theme