Skip to content

Shopify Liquid and API expert. From theme to integrations.

Online Store 2.0 themes, metaobjects, Admin GraphQL API, webhooks: I've been building on Shopify since 2019. Here's how I work, with concrete code.

How I code on Shopify

Code others can pick up

Split sections, documented snippets, conventions shared across the team: another developer can find their way without me.

The right tool in the right place

Liquid for rendering, metaobjects for editable content, APIs for business data: every need has its place, without unnecessary apps.

Built for performance

Server-side rendering, light JavaScript, partial updates through the Section Rendering API instead of full reloads.

What I master

Liquid and Online Store 2.0
Sections, blocks and schemas the marketing team can configure on its own in the theme editor.
Metafields and metaobjects
Structured content and enriched product data, without third-party apps.
Ajax and Section Rendering API
Cart, filters and variants updated without reloading the page.
Admin GraphQL API
Catalogue, stock and order sync with your tools.
Webhooks
React in real time to orders, customers and stock, with signature verification.
Custom apps
When the need goes beyond the theme: private apps and dedicated connectors.

Concrete examples

A configurable section

An Online Store 2.0 section: the collection and the number of products are set in the theme editor, with an empty state.

{% 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 %}

An FAQ driven by metaobjects

Content is managed in the Shopify admin; the theme simply displays it.

{% assign faqs = shop.metaobjects.faq.values %}

{% for faq in faqs %}
  <details>
    <summary>{{ faq.question.value }}</summary>
    {{ faq.answer | metafield_tag }}
  </details>
{% endfor %}

A cart updated without a reload

Adding to cart returns the updated cart drawer HTML directly, in a single request.

// 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"];

Syncing a catalogue

Products changed since the last sync, page by page, to feed an ERP or a 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
        }
      }
    }
  }
}

Securing a webhook

Each webhook is checked against its HMAC signature before processing, with a constant-time comparison.

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);
}

How I work

  1. 01

    Read what exists

    Theme, apps, data: we start from what's in place before writing a line.

  2. 02

    Build cleanly

    Branches, code reviews and shared conventions, on a development theme separate from the live store.

  3. 03

    Ship and document

    A checked launch, and what you need to know to keep evolving the code.

Frequently asked questions

Do you work on existing themes?

Yes, that's the most common case: marketplace or custom theme, we start from what exists and evolve it cleanly.

Can you connect Shopify to our ERP?

Yes, through the Admin GraphQL API and webhooks: catalogue, stock, orders and customers synced one way or both ways.

Do we need an app for every feature?

No. Many needs can be handled in the theme with Liquid and metaobjects, without extra subscriptions or third-party scripts slowing the store down.

Will the code stay maintainable after you?

That's the goal: shared conventions, documented components and Git history, so another developer can take over.

A full project rather than a technical need? Freelance Shopify developer

A technical need on Shopify?

Theme, integration, API or app: describe what you need and I'll get back to you.

Tell me what you need ↗