Documentation · Premium
Thèmes en code
Donne à ton site exactement l’allure que tu veux : templates Liquid et feuilles de style, sans JavaScript, avec des réglages et des sections que tu retrouves dans l’éditeur visuel de Stellr.
Principe
Un thème en code décide du rendu de ton site : la mise en page, le HTML de chaque section, les feuilles de style. Le contenu (textes, images, ordre des sections) reste celui que tu édites dans « Mon site » : changer de thème ne fait rien perdre, et l’IA continue de remplir le site.
Un thème s’écrit en Liquid (le langage de templates de Shopify) et en CSS. Il n’a jamais de JavaScript : les quelques interactions utiles (copier l’adresse, onglets) sont fournies par Stellr. Le HTML produit passe par une liste blanche, et la page est servie sous une politique de sécurité stricte : un thème ne peut ni exécuter de script, ni charger quoi que ce soit hors de Stellr.
- Réservé aux serveurs Premium.
- Le thème est rendu côté serveur à chaque visite (avec un cache), puis mis en cache par le CDN.
- Si le thème a une erreur, le site s’affiche avec le rendu Stellr : un thème cassé ne met jamais ton site hors ligne.
- Tout s’enregistre en brouillon ; le bouton « Publier » met le site et le thème en ligne ensemble.
Fichiers d’un thème
| Fichier | Rôle |
|---|---|
layout/theme.liquid | Obligatoire. L’enveloppe de toutes les pages (menu, pied de page) ; doit afficher {{ content_for_layout }}. |
templates/index.liquid | Obligatoire. L’accueil : il parcourt les sections du site. |
templates/boutique.liquid | La boutique (/boutique). Facultatif : sans ce template, la page garde le rendu complet de Stellr (menu et pied de page compris), aux couleurs de « Style ». |
templates/voter.liquid | La page de vote (/voter), même règle. |
templates/produit, compte, merci | Noms réservés aux pages à venir : la page d’achat, le compte du joueur et le remerciement gardent le rendu Stellr. |
sections/<nom>.liquid | Le rendu d’un type de section (sections/hero.liquid pour la bannière), ou une section propre au thème. |
snippets/<nom>.liquid | Des fragments réutilisables, insérés avec {% render %}. |
assets/<nom>.css | Les feuilles de style, chargées sur toutes les pages, dans l’ordre alphabétique. |
config/settings_schema.json | Les réglages du thème, affichés dans « Mon site → Style ». |
Noms en lettres minuscules, chiffres et tirets. Au plus 100 fichiers, 256 Ko par fichier et 2 Mo au total.
Liquid en bref
{{ … }} affiche une valeur ; {% … %} exécute une balise (condition, boucle…). Les valeurs affichées sont échappées automatiquement : un texte saisi dans l’éditeur ne peut jamais injecter de HTML.
{% if server.online %}
<p class="en-ligne">{{ server.players_label }}</p>
{% else %}
<p>{{ server.status_label }}</p>
{% endif %}
{% for item in section.items %}
<h3>{{ item.title | upcase }}</h3>
{% endfor %}Balises disponibles : if, unless, case, for, break, continue, cycle, tablerow, assign, capture, increment, decrement, comment, raw, render, include, liquid, echo (avec elsif, else et when), plus schema pour les sections du thème. Les filtres standard de Liquid sont disponibles (upcase, date, default, size, split, slice…), ainsi que ceux de Stellr ci-dessous. Un filtre inconnu est une erreur.
| Filtre de Stellr | Rôle |
|---|---|
icon | Icône vectorielle de Stellr : {{ 'sword' | icon: 24 | raw }} |
raw | Sortie sans échappement (HTML voulu, toujours filtré par la liste blanche) |
Icônes disponibles pour icon : sword, shield, star, users, trophy, gem, map, bolt, heart, pickaxe, coin, crown, flame, leaf, rocket, castle, chat, copy, check, play, cart, vote, plus.
Un thème ne lit que ses propres fichiers : pas de disque, pas de réseau, pas d’autre serveur. Un rendu trop long (boucles imbriquées) ou trop lourd est arrêté.
Layout et pages
Le layout entoure chaque page. Il reprend généralement les classes de Stellr (stellr.root_class, stellr.root_style) pour garder les couleurs et les polices choisies dans « Style ».
<div class="{{ stellr.root_class }}" style="{{ stellr.root_style }}">
<header class="sb-nav">
<a href="{{ pages.home }}">{{ site.name }}</a>
{%- if site.shop %}<a href="{{ pages.shop }}">Boutique</a>{% endif -%}
</header>
<main>{{ content_for_layout }}</main>
</div>L’accueil parcourt les sections dans l’ordre choisi dans « Mon site ». Chaque section indique le fichier qui la rend (section.template) :
{% for section in sections %}
{% render section.template, section: section %}
{% endfor %}Donne à chaque section l’identifiant de son bloc (id="{{ section.id }}") : les liens d’ancre marchent, et un clic sur la section dans l’aperçu de l’éditeur l’ouvre directement.
Un texte affiché tel quel dans son propre élément (<h2>{{ section.title }}</h2>) se modifie directement dans l’aperçu de l’éditeur. Transformé par un filtre (upcase, truncate) ou mêlé à d’autres éléments, il reste modifiable dans le formulaire.
Boutique : templates/boutique.liquid parcourt shop.sections (catégories non vides, puis les produits sans catégorie), chacune en grille ou en grades comparés (layout : grid ou tiers). Chaque produit a son prix (amount_label, period_label), ses avantages et sa page d’achat (buy_url) ; le paiement reste géré par Stellr. Quand la boutique n’est pas encore ouverte aux achats (shop.available faux), affiche le produit sans lien d’achat. page.cancelled signale le retour d’un paiement annulé.
<h1>Boutique</h1>
{% for category in shop.sections %}
<h2>{{ category.name }}</h2>
{% for product in category.products %}
<h3>{{ product.name }}</h3>
<p>{{ product.amount_label }} {{ product.period_label }}</p>
{% if shop.available %}<a href="{{ product.buy_url }}">Acheter</a>{% endif %}
{% endfor %}
{% endfor %}Votes : templates/voter.liquid affiche les sites de vote (votes.sites) et le classement du mois demandé (votes.ranking, 50 premiers sur cette page), avec les liens vers les mois voisins (previous_url, next_url, nil aux bornes). Les liens de vote peuvent s’ouvrir dans un nouvel onglet (target="_blank").
Le thème de départ contient les deux pages, au même rendu que Stellr : pars de lui pour les adapter.
Données disponibles
Toutes les pages reçoivent les mêmes données, en lecture seule. Aucune donnée personnelle de joueur n’y figure : les pages sont mises en cache pour tous les visiteurs.
siteLe site du serveursite.nameNom du serveursite.titleTitre de la page (référencement)site.descriptionDescription (référencement)site.urlAdresse du sitesite.shopBoutique ouverte (vrai ou faux)site.votesSites de vote déclarés (vrai ou faux)site.logoLogo, ou nilsite.logo.urlAdresse de l’image (médiathèque)site.logo.widthLargeur en pixelssite.logo.heightHauteur en pixels
serverLe serveur de jeu, en directserver.knownStatut connu (plugin ou ping relié)server.onlineEn ligne (vrai ou faux)server.playersJoueurs en ligne, ou nilserver.max_playersPlaces, ou nilserver.status_label« En ligne », « Hors ligne » ou « Statut indisponible »server.players_label« 42 joueurs en ligne », ou nil
stellrRendu Stellr, pour réutiliser sa feuille de stylestellr.root_classClasses de la racine du site (sb-site…)stellr.root_styleVariables CSS des couleurs et des polices, pour style=""stellr.styleStyle choisi dans « Apparence » (buttons, nav, dividers, texture, headings)stellr.colorsCouleurs choisies dans « Apparence » (background, surface, primary, accent…)
settingsRéglages du thème (config/settings_schema.json)pagePage renduepage.handleindex, boutique ou voterpage.cancelledboutique : retour d’un paiement annulé (aucun montant débité)
pagesAdresses des pages de Stellrpages.homeAccueilpages.shopBoutiquepages.voteVoterpages.accountMon compte
sectionsliste Blocs du document, dans l’ordreshopBoutique, sur toutes les pagesshop.availableBoutique ouverte aux achatsshop.urlAdresse de la boutiqueshop.productsliste Produits visiblesshop.products[].idIdentifiant du produitshop.products[].category_idCatégorie, ou nilshop.products[].nameNomshop.products[].descriptionDescriptionshop.products[].taglineAccroche courteshop.products[].featuredMis en avantshop.products[].badgePastille (« Populaire »…), ou nilshop.products[].perksliste Avantagesshop.products[].perks[].textAvantageshop.products[].perks[].tagNEW, IMPROVED ou nil
shop.products[].includes_idProduit inclus (grade inférieur), ou nilshop.products[].includes_nameNom du produit inclus, ou nil : « Tous les avantages de … »shop.products[].image_urlImage, ou nilshop.products[].price_centsPrix en centimesshop.products[].price_labelPrix affiché : « 4,99 € / mois »shop.products[].amount_labelMontant seul : « 4,99 € »shop.products[].period_labelPériode d’un abonnement : « / mois », ou nilshop.products[].billing_intervalAbonnement : WEEK, MONTH, QUARTER, YEAR, ou nil (achat unique)shop.products[].buy_urlPage d’achat du produit
shop.categoriesliste Catégories, avec leurs produitsshop.categories[].idIdentifiantshop.categories[].nameNomshop.categories[].descriptionDescriptionshop.categories[].layoutgrid ou tiersshop.categories[].productsliste Produits de la catégorieshop.categories[].products[].idIdentifiant du produitshop.categories[].products[].category_idCatégorie, ou nilshop.categories[].products[].nameNomshop.categories[].products[].descriptionDescriptionshop.categories[].products[].taglineAccroche courteshop.categories[].products[].featuredMis en avantshop.categories[].products[].badgePastille (« Populaire »…), ou nilshop.categories[].products[].perksliste Avantagesshop.categories[].products[].perks[].textAvantageshop.categories[].products[].perks[].tagNEW, IMPROVED ou nil
shop.categories[].products[].includes_idProduit inclus (grade inférieur), ou nilshop.categories[].products[].includes_nameNom du produit inclus, ou nil : « Tous les avantages de … »shop.categories[].products[].image_urlImage, ou nilshop.categories[].products[].price_centsPrix en centimesshop.categories[].products[].price_labelPrix affiché : « 4,99 € / mois »shop.categories[].products[].amount_labelMontant seul : « 4,99 € »shop.categories[].products[].period_labelPériode d’un abonnement : « / mois », ou nilshop.categories[].products[].billing_intervalAbonnement : WEEK, MONTH, QUARTER, YEAR, ou nil (achat unique)shop.categories[].products[].buy_urlPage d’achat du produit
shop.sectionsliste Sections de la page boutique : catégories non vides, puis les produits sans catégorieshop.sections[].idIdentifiant (autres : produits sans catégorie)shop.sections[].nameTitre : nom de la catégorie, « Autres produits » ou « Boutique »shop.sections[].descriptionDescriptionshop.sections[].layoutgrid ou tiers (grades comparés côte à côte)shop.sections[].productsliste Produits de la sectionshop.sections[].products[].idIdentifiant du produitshop.sections[].products[].category_idCatégorie, ou nilshop.sections[].products[].nameNomshop.sections[].products[].descriptionDescriptionshop.sections[].products[].taglineAccroche courteshop.sections[].products[].featuredMis en avantshop.sections[].products[].badgePastille (« Populaire »…), ou nilshop.sections[].products[].perksliste Avantagesshop.sections[].products[].perks[].textAvantageshop.sections[].products[].perks[].tagNEW, IMPROVED ou nil
shop.sections[].products[].includes_idProduit inclus (grade inférieur), ou nilshop.sections[].products[].includes_nameNom du produit inclus, ou nil : « Tous les avantages de … »shop.sections[].products[].image_urlImage, ou nilshop.sections[].products[].price_centsPrix en centimesshop.sections[].products[].price_labelPrix affiché : « 4,99 € / mois »shop.sections[].products[].amount_labelMontant seul : « 4,99 € »shop.sections[].products[].period_labelPériode d’un abonnement : « / mois », ou nilshop.sections[].products[].billing_intervalAbonnement : WEEK, MONTH, QUARTER, YEAR, ou nil (achat unique)shop.sections[].products[].buy_urlPage d’achat du produitshop.sections[].products[].tierGrades comparés : palier « 01 », « 02 »…, sinon nil
votesVotes, sur toutes les pagesvotes.urlPage de votevotes.sitesliste Sites de votevotes.sites[].nameNom du sitevotes.sites[].urlLien pour voter
votes.rankingClassement du mois (10 premiers, 50 sur la page voter), ou nilvotes.ranking.monthMois (AAAA-MM)votes.ranking.month_label« octobre 2026 »votes.ranking.total_votesVotes du moisvotes.ranking.is_currentMois en cours (le classement repart à zéro chaque mois)votes.ranking.previous_urlvoter : mois précédent, ou nil (premier mois avec des votes)votes.ranking.next_urlvoter : mois suivant, ou nil (mois en cours)votes.ranking.entriesliste Joueursvotes.ranking.entries[].rankRangvotes.ranking.entries[].playerPseudovotes.ranking.entries[].votesVotes
sectionSection rendue (dans sections/*.liquid)section.idIdentifiant du bloc, à mettre en id de la section (ancre)section.typeType du bloc : hero, features, status, cta, discord, join, faq, stats, ou theme (section du thème)section.sectiontheme : nom du fichier de la section (sections/<nom>.liquid)section.settingstheme : réglages de la section, déclarés par son {% schema %}section.templateFichier de la section : {% render section.template, section: section %}section.toneFond de la section : base ou altsection.dividerSéparateur avant la section, ou nilsection.divider.stylewave, pixel ou slantsection.divider.toFond de destination
section.layoutMise en page choisie (selon le type)section.eyebrowSurtitresection.titleTitresection.subtitleSous-titresection.textTexte (cta, discord)section.highlighthero : passage du titre mis en couleursection.title_beforehero : titre avant le passage en couleursection.title_highlighthero : passage en couleur, ou nilsection.title_afterhero : titre après le passage en couleursection.serverAddresshero, join : adresse du serveursection.address_in_actionshero : afficher l’adresse avec les boutonssection.ctahero : bouton principal, ou nilsection.cta.labelTexte du boutonsection.cta.hrefAdresse du lien
section.secondaryCtahero : bouton secondaire, ou nilsection.secondaryCta.labelTexte du boutonsection.secondaryCta.hrefAdresse du lien
section.buttoncta : boutonsection.button.labelTexte du boutonsection.button.hrefAdresse du lien
section.showOnlinehero, stats : afficher les joueurs en lignesection.showLogohero : afficher le logo en grandsection.showPlayerCountstatus : afficher le nombre de joueurssection.backgroundhero : stars, gradient ou plainsection.background_classhero : image, plain, stars ou gradientsection.background_imagehero : image de fond, ou nilsection.background_image.urlAdresse de l’image (médiathèque)section.background_image.widthLargeur en pixelssection.background_image.heightHauteur en pixels
section.illustrationhero : illustration à côté du texte, ou nilsection.illustration.urlAdresse de l’image (médiathèque)section.illustration.widthLargeur en pixelssection.illustration.heightHauteur en pixels
section.inviteUrldiscord : lien d’invitationsection.serverNamejoin : nom du serveur dans Minecraftsection.versionjoin : version de Minecraftsection.itemsliste features : cartes ; faq : questions ; stats : chiffressection.items[].iconfeatures : nom d’icône, pour le filtre iconsection.items[].titlefeatures : titresection.items[].textfeatures : textesection.items[].imagefeatures : image, ou nilsection.items[].image.urlAdresse de l’image (médiathèque)section.items[].image.widthLargeur en pixelssection.items[].image.heightHauteur en pixels
section.items[].numberfeatures : numéro sur deux chiffres (01, 02…)section.items[].questionfaq : questionsection.items[].answerfaq : réponsesection.items[].valuestats : chiffresection.items[].labelstats : libellé
section.platformsliste join : plateformes (Java, Bedrock, consoles)section.platforms[].idjava, bedrock ou consolessection.platforms[].labelNom de la plateformesection.platforms[].detailAppareils concernéssection.platforms[].addressAdresse à saisirsection.platforms[].portPort, ou nilsection.platforms[].stepsÉtapes pour rejoindre (textes)
content_for_layoutContenu de la page (dans layout/theme.liquid)
Réglages du thème
config/settings_schema.json décrit les réglages que le propriétaire voit dans « Mon site → Style ». Leurs valeurs sont dans settings : {{ settings.accent }}, ou dans le CSS.
[
{
"name": "Couleurs",
"settings": [
{ "type": "color", "id": "accent", "label": "Couleur d'accent", "default": "#ff8a3d" },
{ "type": "checkbox", "id": "ombres", "label": "Ombres sous les titres", "default": false },
{ "type": "range", "id": "espacement", "label": "Espace entre les sections", "min": 32, "max": 160, "unit": "px", "default": 88 },
{ "type": "select", "id": "menu", "label": "Menu", "options": [{ "value": "haut", "label": "En haut" }, { "value": "cote", "label": "Sur le côté" }], "default": "haut" },
{ "type": "image", "id": "fond", "label": "Image de fond" }
]
}
]| Type | Valeur | Précisions |
|---|---|---|
text | texte | 500 caractères au plus |
textarea | texte | 2000 caractères au plus |
color | #rrggbb | sélecteur de couleur |
checkbox | vrai ou faux | |
select | une des options | options obligatoire : { "value", "label" } |
range | nombre | min et max obligatoires, step et unit facultatifs |
image | image de la médiathèque | dans le thème : url, width, height, ou nil |
Chaque réglage a un id (lettres minuscules, chiffres et _), un label, et peut avoir un default et une aide info.
Sections propres au thème
Un fichier de sections/ qui déclare un bloc {% schema %} devient une section que le propriétaire peut ajouter, ordonner et régler dans « Mon site → Sections », comme celles de Stellr. Ses valeurs sont dans section.settings.
{% schema %}
{
"name": "Compte à rebours",
"settings": [
{ "type": "text", "id": "titre", "label": "Titre", "default": "Nouvelle saison" },
{ "type": "text", "id": "date", "label": "Date (AAAA-MM-JJ)" },
{ "type": "checkbox", "id": "en_ligne", "label": "Seulement quand le serveur est en ligne" }
]
}
{% endschema %}
{%- unless section.settings.en_ligne and server.online != true -%}
<section class="sb-block sb-tone--{{ section.tone }}" id="{{ section.id }}">
<div class="sb-container">
<h2>{{ section.settings.titre }}</h2>
<p>Le {{ section.settings.date | date: "%d/%m/%Y" }}</p>
</div>
</section>
{%- endunless -%}- Le schéma prend les mêmes types de réglages que
settings_schema.json, avec unnameobligatoire. - Le premier
{% schema %}du fichier est lu, même dans un commentaire : n’écris pas cette balise dans un commentaire. - Si tu renommes ou supprimes le fichier, la section n’est plus affichée (le reste du site l’est) et l’éditeur le signale.
Interactions fournies par Stellr
Sans JavaScript dans le thème, deux interactions sont activées par des attributs :
<button type="button" data-stellr-copy="{{ section.serverAddress }}">
<code>{{ section.serverAddress }}</code>
<span data-stellr-copy-label>Copier</span>
</button><div data-stellr-tabs>
<button type="button" role="tab" data-stellr-tab="java" aria-selected="true">Java</button>
<button type="button" role="tab" data-stellr-tab="bedrock" aria-selected="false">Bedrock</button>
<div data-stellr-panel="java">…</div>
<div data-stellr-panel="bedrock" hidden>…</div>
</div>Les onglets se changent au clic et au clavier (flèches, Début, Fin). Sans script, le premier panneau reste affiché.
Feuilles de style
Les fichiers assets/*.css sont chargés après la feuille de style de Stellr (classes sb-*) : il suffit de surcharger ce qui change. Ils passent aussi par Liquid, pour utiliser les réglages :
.sb-site .sb-block { padding-block: {{ settings.espacement }}px; }
{% if settings.ombres %}
.sb-site h1, .sb-site h2 { text-shadow: 0 4px 0 rgb(0 0 0 / 35%); }
{% endif %}- Pour écrire
{{ou{%dans le CSS, entoure-les de{% raw %}…{% endraw %}. - Les feuilles ne peuvent rien charger hors de Stellr : polices Google Fonts et images de la médiathèque seulement.
- Les couleurs et polices choisies dans « Style » sont des variables CSS sur la racine (
stellr.root_style). - Garde
stellr.root_classsur la racine du layout : les pages que Stellr affiche lui-même (boutique, compte, vote) en ont besoin. Mais la feuille de base contient.sb-site section { max-width: 1100px; margin: 0 auto; padding: 64px 24px; }: toute balisesectionde ton thème est bridée à 1 100 px et centrée, fond compris. Annule cette règle pour tes sections, par exemple.sb-site section.ma-section { max-width: none; margin: 0; padding: 0; }, pour avoir des bandes pleine largeur. - Navigation flottante (
position: stickyoufixedpar-dessus la page) : elle ne doit pas réserver de bande au-dessus de la première section, sinon le fond de la page apparaît derrière elle. Fais remonter la première section sous la navigation, avec la même précision que la règle ci-dessus :.sb-site section.mon-hero { margin-top: -72px; padding-top: 150px; }(hauteur de la navigation, puis assez d’espace pour dégager le contenu).
Ce que la liste blanche garde
Le HTML produit est filtré : ce qui n’est pas dans la liste est retiré, sans erreur. Jamais de script, iframe, object, embed, form (pour l’instant), link, meta, ni d’attribut d’événement (onclick…).
Balises gardées : a, abbr, article, aside, b, blockquote, br, button, caption, cite, code, dd, del, details, div, dl, dt, em, figcaption, figure, footer, h1, h2, h3, h4, h5, h6, header, hr, i, img, ins, kbd, li, main, mark, nav, ol, p, picture, pre, q, s, section, small, span, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, time, tr, u, ul, svg, path, g, circle, ellipse, rect, line, polyline, polygon.
| Balise | Attributs gardés |
|---|---|
| toutes | class, id, role, title, hidden, style, lang, dir, tabindex, aria-*, data-* |
a | href, target, rel |
img | src, alt, width, height, loading, decoding |
button | type, disabled |
details | open |
td | colspan, rowspan |
th | colspan, rowspan, scope |
time | datetime |
ol | start, reversed |
svg | viewbox, viewBox, width, height, fill, stroke, stroke-width, stroke-linecap, stroke-linejoin, d, cx, cy, r, rx, ry, x, y, x1, y1, x2, y2, points, transform, opacity, focusable, xmlns |
- Liens :
http,https,mailtoou relatifs. Un lientarget="_blank"reçoitrel="noopener noreferrer"; seulsnofollow,ugcetsponsoredsont gardés dureldu thème. - Images : de la médiathèque du serveur, des produits de la boutique, ou relatives ; les autres perdent leur adresse.
- Icônes SVG : seulement des formes simples (pas de
use,imageniforeignObject).