Du code qu'on peut reprendre
Sections découpées, snippets documentés, conventions communes à toute l'équipe : un autre développeur s'y retrouve sans moi.
Thèmes Online Store 2.0, metaobjects, API Admin GraphQL, webhooks : je développe sur Shopify depuis 2019. Voici comment je travaille, avec du code concret.
Sections découpées, snippets documentés, conventions communes à toute l'équipe : un autre développeur s'y retrouve sans moi.
Liquid pour le rendu, metaobjects pour le contenu éditable, API pour les données métier : chaque besoin trouve sa place, sans app superflue.
Rendu côté serveur, JavaScript léger, mises à jour partielles via la Section Rendering API plutôt que des rechargements complets.
Une section Online Store 2.0 : la collection et le nombre de produits se règlent dans l'éditeur de thème, et l'état vide est prévu.
{% liquid
assign collection = section.settings.collection
assign limit = section.settings.limit | default: 4
%}
<div class="product-grid">
{% for product in collection.products limit: limit %}
{% render 'product-card', product: product %}
{% else %}
<p>{{ 'sections.featured_collection.empty' | t }}</p>
{% endfor %}
</div>
{% schema %}
{
"name": "Featured collection",
"settings": [
{ "type": "collection", "id": "collection", "label": "Collection" },
{ "type": "range", "id": "limit", "label": "Products", "min": 2, "max": 12, "step": 1, "default": 4 }
],
"presets": [{ "name": "Featured collection" }]
}
{% endschema %}Le contenu se gère dans l'admin Shopify ; le thème se contente de l'afficher.
{% assign faqs = shop.metaobjects.faq.values %}
{% for faq in faqs %}
<details>
<summary>{{ faq.question.value }}</summary>
{{ faq.answer | metafield_tag }}
</details>
{% endfor %}L'ajout au panier renvoie directement le HTML à jour du tiroir panier, en une seule requête.
// Bundled section rendering: the cart drawer HTML comes back with the add-to-cart response
const response = await fetch(`${window.Shopify.routes.root}cart/add.js`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
items: [{ id: variantId, quantity: 1 }],
sections: "cart-drawer",
}),
});
const { sections } = await response.json();
document.querySelector("#shopify-section-cart-drawer").outerHTML = sections["cart-drawer"];Les produits modifiés depuis la dernière synchronisation, page par page, pour alimenter un ERP ou un PIM.
query ProductsUpdatedSince($cursor: String, $since: String!) {
products(first: 100, after: $cursor, query: $since) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
handle
updatedAt
variants(first: 50) {
nodes {
sku
inventoryQuantity
}
}
}
}
}Chaque webhook est vérifié avec sa signature HMAC avant d'être traité, avec une comparaison à temps constant.
import crypto from "node:crypto";
// rawBody must be the untouched request body, before any JSON parsing
export function isValidWebhook(rawBody, hmacHeader, secret) {
const digest = crypto.createHmac("sha256", secret).update(rawBody, "utf8").digest("base64");
const expected = Buffer.from(digest);
const received = Buffer.from(hmacHeader ?? "");
return expected.length === received.length && crypto.timingSafeEqual(expected, received);
}01
Thème, apps, données : on part de ce qui est en place avant d'écrire une ligne.
02
Branches, revues de code et conventions partagées, sur un thème de développement séparé de la boutique en ligne.
03
Mise en ligne vérifiée, et ce qu'il faut savoir pour faire évoluer le code ensuite.
Oui, c'est le cas le plus fréquent : thème du marché ou sur mesure, on part de l'existant et on le fait évoluer proprement.
Oui, via l'API Admin GraphQL et les webhooks : catalogue, stocks, commandes et clients synchronisés, dans un sens ou dans les deux.
Non. Beaucoup de besoins se règlent dans le thème avec Liquid et les metaobjects, sans abonnement supplémentaire ni script tiers qui ralentit la boutique.
C'est le but : conventions communes, composants documentés et historique Git, pour qu'un autre développeur puisse reprendre.
Thème, intégration, API ou app : décrivez le besoin, je reviens vers vous.