Sviluppatori · Formato del tema
Il formato del tema
Un tema è JSON e CSS. Nessun passaggio di build, nessun framework, nessun server da mandare avanti. La stessa funzione che decide se il suo tema si installa dalla nostra parte gira nella CLI e nell'editor, quindi un controllo pulito lì è un caricamento pulito. Per ogni nodo, componente e fonte dati, veda il riferimento temi.
Due vincoli
Li sappia prima di cominciare
Sono entrambi il motivo per cui il tema di qualcuno che non abbiamo mai incontrato può essere installato su un negozio dal vivo.
- Un tema non porta JavaScript. Nessuno, in nessuna forma. Una sezione sono dati ed è la nostra vetrina a disegnarla, quindi non c'è niente da isolare. Tutto ciò che è interattivo è un componente che lei colloca per nome, e parecchi prendono la disposizione dal suo tema, quindi una fisarmonica nel suo tema ha l'aspetto della sua fisarmonica. Se le serve un comportamento che non è in elenco, ce lo dica: quella è una lacuna dalla nostra parte, ed è così che l'elenco cresce.
- Lo stile è CSS semplice sui nostri token, non Tailwind. Scriva
var(--shop-accent),var(--shop-font-heading),var(--shop-radius). Il suo theme.json imposta i valori predefiniti, e il commerciante può cambiarne qualunque senza toccare il suo CSS.
Struttura
La cartella
È questo che usano lo spazio di lavoro, la CLI e un caricamento zip. Tenere tutto nel solo theme.json funziona lo stesso; le cartelle sono per sua comodità, non un secondo formato.
harbour/ theme.json identity, tokens, theme settings, plugins theme.css styling for the whole theme sections/<name>.json one file per section: its form, its data, its markup, its CSS templates/<page>.json one file per page: which sections, in which order AGENTS.md the performance rules, for coding assistants README.md yours
Nessun altro file viene accettato: niente immagini, font o script nella cartella. Un tema porta al massimo 60 sezioni e 2 MB in tutto.
Identità
theme.json
La testa del tema. La riga $schema le dà completamento e aiuto in linea in VS Code e nella maggior parte degli editor, da uno schema generato dal validatore stesso.
{
"$schema": "https://whizzycommerce.com/schema/theme-v1.json",
"dsl": 1,
"slug": "harbour",
"name": "Harbour",
"version": "1.0.0",
"description": "Big photography and quiet type for homeware shops.",
"author": { "name": "Tide Studio", "url": "https://tide.example", "email": "help@tide.example" },
"docsUrl": "https://tide.example/harbour",
"specs": { "responsive": true, "rtl": false },
"plugins": { "blog": "^2.0.0" },
"tokens": { "colorAccent": "#1f3a5f", "radius": "0" },
"settings": [],
"migrations": {}
}| Campo | Cos'è |
|---|---|
slug | Lettere minuscole, cifre e trattini. È permanente, e fa da prefisso ai tipi di sezione del suo tema. |
version | Semver. Veda Versioni e revisione per cosa può cambiare ogni tipo di versione. |
plugins | I plugin per cui il tema dispone le pagine, con un intervallo di versioni. Veda Plugin più sotto. |
tokens | I suoi valori predefiniti per i design token. |
settings | Scelte valide per tutto il tema che il commerciante fa una volta per negozio. |
migrations | Rinomine di sezioni, impostazioni e token, per i negozi che arrivano da una versione precedente. |
Design
Token e impostazioni
I token sono i colori, i caratteri e le forme del negozio. Le impostazioni sono scelte sulla disposizione. Entrambi hanno i suoi valori predefiniti, e il commerciante può cambiarli tutti e due nella schermata Design del negozio.
| Token | Variabile CSS | Predefinito |
|---|---|---|
colorBg | var(--shop-bg) | #ffffff |
colorFg | var(--shop-fg) | #0f1115 |
colorAccent | var(--shop-accent) | #0b0f19 |
colorMuted | var(--shop-muted) | #6b7280 |
fontHeading | var(--shop-font-heading) | "Inter", system-ui, sans-serif |
fontBody | var(--shop-font-body) | "Inter", system-ui, sans-serif |
fontSizeBody | var(--shop-font-size-body) | 16px |
fontSizeHeading | var(--shop-font-size-heading) | 60px |
Questi sono i primi 8 di 28. Il riferimento li elenca tutti.
"settings": [
{ "key": "homeLayout", "label": "Home layout", "type": "select", "default": "roomy",
"options": [{ "value": "roomy", "label": "Roomy" }, { "value": "compact", "label": "Compact" }] },
{ "key": "showNote", "label": "Show the delivery note", "type": "boolean", "default": true }
]Una sezione legge un'impostazione del tema come { "get": "theme.homeLayout" } e le proprie come { "get": "settings.heading" }. Usi un'impostazione del tema quando la risposta è una per negozio, così il commerciante la cambia una volta invece che in ogni sezione.
Mattoni
Sezioni
Una sezione è quello che un commerciante aggiunge a una pagina. Dichiara un modulo, i dati che le servono, il suo CSS e il suo markup come un albero di nodi di render. Il modulo non lo costruisce mai lei: dichiarare campi e blocchi è quello che ne dà uno al commerciante.
{
"type": "harbour.ticker",
"label": "Ticker",
"category": "layout",
"description": "Short phrases across the page, in the accent colour.",
"fields": [
{ "key": "speed", "label": "Speed", "type": "select", "default": "slow",
"options": [{ "value": "slow", "label": "Slow" }, { "value": "fast", "label": "Fast" }] }
],
"blocks": [{
"type": "phrase", "label": "Phrase", "max": 6,
"fields": [
{ "key": "text", "label": "Text", "type": "text", "default": "Free delivery" }
]
}],
"css": ".ticker-band { display: flex; gap: 3rem; background: var(--shop-accent) }",
"render": [
{ "node": "box", "as": "section", "cls": "ticker-band", "children": [
{ "node": "slot", "children": [
{ "node": "text", "as": "span", "value": { "get": "block.text" } }
]}
]}
]
}- type è sempre
<your slug>.<name>. Il nome del file è la parte dopo il punto. - blocks dà al commerciante un pulsante “Aggiungi frase”, limitato da
max.slotdisegna i suoi figli una volta per blocco, ed è questo che fa sì cheblock.textsignifichi questa frase. - render è un elenco di nodi, di questi tipi: box, text, rich, img, link, each, if, slot, icon, money, component. I valori sono espressioni come
{ "get": "product.title" }o{ "lit": "Sale" }.
Fonti dati
Una sezione dichiara cosa le serve, e la pagina lo recupera prima di disegnare qualsiasi cosa. Due sezioni che chiedono lo stesso elenco costano una query. Un tema non può scrivere una query propria.
"data": [
{ "as": "picks", "source": "collection-products",
"collection": { "get": "settings.collection" }, "limit": 8 }
],
"render": [
{ "node": "box", "cls": "picks-grid", "children": [
{ "node": "each", "in": { "get": "data.picks" }, "as": "item", "limit": 8,
"children": [
{ "node": "component", "use": "product-card", "props": { "product": { "get": "item" } } }
],
"empty": [
{ "node": "text", "as": "p", "value": { "lit": "Nothing to show here yet." } }
] }
]}
]Componenti
I componenti sono le parti interattive e che conoscono il negozio: product-card, shop-logo, shop-menu, cart-link, search-box e altri. Lei li colloca e ci dà stile attorno, con props dove un componente ne accetta. Non può scriverne uno.
Il carrello, la pagina prodotto, la ricerca, l'accesso e le pagine di un plugin arrivano come dati in ambito più piccole parti che fanno una cosa ciascuna, come sheet, cart-remove, product-form, product-gallery, search-form e login-form. Le versioni già pronte sono costruite con le stesse parti, quindi un tema può disporne una qualsiasi in modo diverso: un carrello come popup invece che come cassetto, una scheda d'acquisto con un ordine suo. Il riferimento elenca ogni ambito e ogni parte.
Pagine
Template
Un template è la disposizione iniziale di una pagina: un elenco di sezioni collocate con le loro impostazioni. I commercianti la riordinano dopo.
[
{ "id": "hero", "type": "hero", "settings": { "heading": "Made to last" } },
{ "id": "picks", "type": "harbour.picks", "settings": { "heading": "New in", "limit": 4 } }
]| Identificativo | Pagina |
|---|---|
header | Header |
home | Home |
collection | Category page |
product | Product page |
cart | Cart page |
search | Search results |
login | Sign in page |
register | Create account page |
footer | Footer |
blog | L'elenco degli articoli del blog. Richiede il plugin blog dichiarato. |
blog-post | Un articolo del blog. Richiede il plugin blog dichiarato. |
Un template con qualsiasi altro nome (header, home, collection, product, cart, search, login, register, footer, o le pagine di un plugin dichiarato) viene segnalato quando convalida, invece di installarsi in silenzio e non disegnare niente. Una pagina porta al massimo 40 sezioni.
Dipendenze
Plugin
Alcune pagine appartengono a un plugin, come il blog. Per disporre quelle pagine, dichiari il plugin in theme.json con l'intervallo di versioni contro cui ha costruito.
"plugins": { "blog": "^2.0.0" }- I suoi template possono poi usare le pagine e i tipi di sezione di quel plugin, come
blog.indexeblog.post, e i suoi componenti, comeblog-post-list. - Installare il suo tema installa prima il plugin, così le pagine che ha disposto esistono.
- Gli intervalli hanno le forme
^2.0.0,~2.1.0,>=2.0.0,2.1.0o*. Un invio viene bloccato se il catalogo non ha nessuna versione dentro il suo intervallo. - Se dà stile alle pagine di un plugin soltanto con il CSS, non dichiari niente. Il suo CSS ci arriva già.
Stile
Il CSS, e come viene isolato
Scriva normali selettori di classe. All'installazione il suo CSS viene isolato sul suo tema e ogni nome di classe riceve un prefisso valido per tutto il tema, così il .card del suo tema non può scontrarsi con quello di un altro tema.
.grid, le regole dell'una ristilizzano l'altra, e un invio con una collisione del genere viene bloccato. Dia alle classi il nome della loro sezione: .picks-grid, .lookbook-grid. Le regole pensate per ogni sezione vanno in theme.css, che è condiviso apposta.- Le proprietà vengono confrontate con un elenco. Tutto ciò che viene rifiutato è segnalato quando convalida, mai scartato in silenzio.
url()può puntare soltanto alla nostra CDN dei media. I font arrivano dai token dei font: ne nomini uno di Google lì e viene scaricato per lei, senza nessun@importnel suo CSS.- Il CSS di una sezione è al massimo di 40 kB, e quello dell'intero tema di 200 kB.
Immagini
Loghi e immagini
I commercianti caricano il loro logo, e un logo SVG resta vettoriale. Al caricamento viene filtrato fino al disegno e messo sempre in un tag img, quindi è sicuro su qualsiasi tema.
Collochi il logo del negozio con { "node": "component", "use": "shop-logo" }. Quando il suo design ha bisogno di una seconda versione, come un logo bianco su una barra scura, aggiunga un'impostazione di tema di tipo image e la passi come src:
{ "node": "component", "use": "shop-logo", "props": { "src": { "get": "theme.logoOnDark" } } }Dimensioni con il CSS la scatola in cui sta un'immagine, non l'immagine. Le fotografie della sua demo arrivano dal catalogo di esempio sul negozio del tema, quindi non ne spedisce nessuna.
Velocità
Regole di prestazione
Google misura un negozio su un telefono di fascia media con una rete lenta. Queste regole sono lo stesso testo che la CLI scrive in AGENTS.md, e i controlli di pubblicazione pesano la sua home.
Rules for anyone editing this theme, including an AI assistant. Google measures the shop on a mid-range phone on a slow network, so that is the device to build for.
Pictures
- The picture at the top of the page (hero, first slide) gets
"priority": trueon itsimgnode. It is what Largest Contentful Paint times, and without it the browser waits to load it. Only that one: every other picture stays lazy. - Give every full-width picture a
mobileSrcfield for phones, a crop that works on a narrow screen, so a phone does not download a desktop banner. - Set
sizeson anyimgthat is not full width, for example"(min-width: 768px) 33vw, 50vw"for a three-column grid, so the browser picks a smaller file. - Give the box a picture sits in a fixed shape in CSS (
aspect-ratio), so the page does not jump when it arrives. - Do not put the main picture in a CSS
background-image: the browser finds it late and cannot pick a size for it.
Fonts
- At most two families, heading and body. Each one is a separate download.
- Leave the font tokens at the core stack if the design does not need a web font: that costs nothing at all.
Weight
- Keep
theme.csslean: no unused rules, no copies of the same rule per section. - Above the first screen, place only what is needed there. A long home page is fine; a first screen with a slideshow, a carousel and a video is not.
- Keep
eachlimits realistic. Twenty-four product cards on a home page is twenty-four pictures and a long page to render; eight is usually enough. - Avoid heavy CSS effects on large areas (
backdrop-filter, bigbox-shadow,filter: blur), which are slow to draw on a phone.
Checking
Run https://pagespeed.web.dev on the shop's home page and one product page, on Mobile. Aim for Largest Contentful Paint under 2.5 s and Cumulative Layout Shift under 0.1. Fix the first item Lighthouse lists before anything else.
Lingue
Lo scriva in modo che si possa tradurre
Tutto quello che un commerciante potrebbe voler riscrivere dovrebbe essere un campo con un valore predefinito, non una stringa letterale nel markup.
Un campo compare nell'editor del commerciante e nella sua schermata di traduzione, così il suo titolo in inglese diventa il loro in portoghese. Un valore lit resta bloccato in inglese su ogni negozio che installa il suo tema. Tenga lit per cose che non sono parole, come un nome di classe o un valore di disposizione.