Appearance
Getting started
Scaffold a minimal theme, preview it on a development site, and validate it with the CLI.
1. Create the files
A theme is a folder of Liquid and config. A minimal theme:
my-theme/
theme.json
layout/
theme.liquid
views/
index.liquid
config/
settings_schema.json
menu.json
locales/
en.json
assets/
css/
app.csstheme.json is the manifest that identifies your theme on the platform. The same contract is used everywhere: CLI publishing and private zip uploads both read the theme's slug, name, and version from it:
json
{
"slug": "my-theme",
"name": "My Theme",
"version": "1.0.0",
"description": "A minimal starter theme."
}layout/theme.liquid is the shell every page renders into, via content_for_layout. This is the one file that's actually required; importing a package without it fails:
liquid
<!doctype html>
<html lang="{{ locale }}">
<head>
<meta charset="utf-8">
<title>{{ page_title }}</title>
<link rel="stylesheet" href="/assets/css/app.css">
{% if settings.base_color %}
<style>:root { --brand: {{ settings.base_color }}; }</style>
{% endif %}
</head>
<body>
<nav>
{% for item in menu %}
<a href="{{ item.url }}">{{ item.translation_key | t: fallback: item.label }}</a>
{% endfor %}
</nav>
<main>{{ content_for_layout }}</main>
</body>
</html>views/index.liquid is the home page:
liquid
<h1>{{ 'nav.home' | t }}</h1>
{% for unit_type in unit_types %}
<article>
<h2>{{ unit_type.name }}</h2>
<a href="/accommodations/{{ unit_type.slug }}">{{ 'unit.details' | t }}</a>
</article>
{% endfor %}config/settings_schema.json declares the host-configurable settings (sections of fields; see Theme settings):
json
[
{
"name": "General",
"fields": [
{ "id": "base_color", "type": "color_picker", "label": "Brand color", "default": "#4f46e5" },
{ "id": "show_footer", "type": "radio", "boolean": true, "label": "Show footer", "default": true }
]
}
]config/menu.json (navigation) rounds out the config; a config/blocks.json
config/pages.jsonpair seeds page-builder blocks on the home page and CMS pages, andconfig/settings_data.jsonis accepted too. All of them are optional; missing ones are validation warnings, not errors. See the reference layout.
locales/en.json supplies the strings your views read through the t filter:
json
{
"nav": { "home": "Home" },
"unit": { "details": "Details" }
}assets/css/app.css:
css
body { font-family: system-ui, sans-serif; }2. Preview on a development site
Zip the contents so layout/ sits at the archive root:
bash
cd my-theme
zip -r ../my-theme.zip .In a development site, go to Themes → Manage themes → Upload theme and upload the .zip. The theme's slug, name, and version come from theme.json. Activate it, then open the storefront. Use the in-browser code editor to tweak views and assets, and the theme settings page to see your settings_schema.json rendered as a form.
3. Validate with the CLI
When you're aiming for the marketplace, install the Stayblox CLI and validate from the theme directory:
bash
npm install -g @stayblox/cli
stayblox login
stayblox theme validateThe report tells you exactly what the marketplace requires (structure, valid config JSON, any graphql/*.graphql operations you shipped) before you ever publish. When it passes, stayblox theme push publishes a private draft and stayblox theme push --submit sends it for review; see Publishing.
Next
- What's available in views → Templating
- Make it configurable → Theme settings
- Package layout & rules → Theme structure
- Publish it → Publishing · Stayblox CLI