diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..5026a048d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,90 @@ +# Skeleton Theme Agent Guide + +A minimal Shopify Liquid theme built on block-first agentic composition. This +file captures the dialect an external coding agent is most likely to miss. Code +is the source of truth. + +## Non-negotiables when editing this theme + +- **No sections:** no `sections/` folder, no `{% section %}`/`{% sections %}` + tags, no JSON templates, no schema `presets`. +- **No Liquid-embedded assets:** no `{% stylesheet %}`, no `{% javascript %}`. + All CSS lives in `assets/critical.css`. +- **Block-first composition:** templates compose page content directly from + blocks, snippets, and inline markup. Do not introduce single-use page + sections. +- **Container-owned layout:** each page region is wrapped in the `container` + block, which owns the outer layout element. +- **Whitespace matters:** include whitespace between an HTML tag name and a + following Liquid delimiter (`
  • : value`). +- The dialect also defines reserved `class`/`attributes` kwargs, but skeleton's + plain-CSS blocks do not declare them (see Blocks below). + +## The partial tag + +```liquid +{% partial 'name' %}...{% endpartial %} +``` + +Partials are named inline regions — not files — that client JavaScript can +fetch and patch for server-backed DOM updates. Partial names are contracts with +that JS. + +**Skeleton intentionally omits partials.** It has no JS-refetched dynamic +region, so introducing a partial would mean introducing client JS that the +minimalism guardrail forbids. Add one only when a genuine dynamic region needs +it. + +## Blocks + +Required shape: +- A `{% doc %}` header with typed params and a `{% schema %}` tag **without + `presets`**. +- Declare only block-specific `@param`s such as `tag`. Do **not** declare the + reserved `class`/`attributes` kwargs as `@param`. +- Render `{{ block.content }}` where the block composes caller-supplied body. +- Keep `{{ block.shopify_attributes }}` on the root element for editor support. + +Skeleton keeps `.theme-check.yml` as a pristine +`extends: theme-check:recommended` with **zero overrides**. Blocks parameterize +via `tag` + `block.settings.*` and rely on `{{ block.shopify_attributes }}` — +no reserved-name workaround is needed. + +Public blocks are usable anywhere; a leading underscore (`_private`) marks +context-specific sub-components. + +Current blocks: `container`, `hello-world`, `text`, `header`, `footer`. + +## Theme map + +``` +blocks/ container, hello-world, text, header, footer +templates/ *.liquid composition roots (no JSON) +layout/ theme.liquid shell composing header/footer blocks +snippets/ internal utilities (css-variables, image, meta-tags) +assets/critical.css all theme CSS +``` diff --git a/README.md b/README.md index eaf59b2c4..1c5df6e1e 100644 --- a/README.md +++ b/README.md @@ -1,160 +1,129 @@ -

    -
    - logo -
    - Shopify Skeleton Theme -

    - -A minimal, carefully structured Shopify theme designed to help you quickly get started. Designed with modularity, maintainability, and Shopify's best practices in mind. - -

    - License - CI -

    - -## Getting started - -### Prerequisites - -Before starting, ensure you have the latest Shopify CLI installed: - -- [Shopify CLI](https://shopify.dev/docs/api/shopify-cli) – helps you download, upload, preview themes, and streamline your workflows - -If you use VS Code: - -- [Shopify Liquid VS Code Extension](https://shopify.dev/docs/storefronts/themes/tools/shopify-liquid-vscode) – provides syntax highlighting, linting, inline documentation, and auto-completion specifically designed for Liquid templates - -### Clone - -Clone this repository using Git or Shopify CLI: - -```bash -git clone git@github.com:Shopify/skeleton-theme.git -# or -shopify theme init -``` - -### Preview - -Preview this theme using Shopify CLI: - -```bash -shopify theme dev -``` - -## Theme architecture - -```bash -. -├── assets # Stores static assets (CSS, JS, images, fonts, etc.) -├── blocks # Reusable, nestable, customizable UI components -├── config # Global theme settings and customization options -├── layout # Top-level wrappers for pages (layout templates) -├── locales # Translation files for theme internationalization -├── sections # Modular full-width page components -├── snippets # Reusable Liquid code or HTML fragments -└── templates # Templates combining sections to define page structures -``` - -To learn more, refer to the [theme architecture documentation](https://shopify.dev/docs/storefronts/themes/architecture). - -### Templates - -[Templates](https://shopify.dev/docs/storefronts/themes/architecture/templates#template-types) control what's rendered on each type of page in a theme. - -The Skeleton Theme scaffolds [JSON templates](https://shopify.dev/docs/storefronts/themes/architecture/templates/json-templates) to make it easy for merchants to customize their store. - -None of the template types are required, and not all of them are included in the Skeleton Theme. Refer to the [template types reference](https://shopify.dev/docs/storefronts/themes/architecture/templates#template-types) for a full list. - -### Sections - -[Sections](https://shopify.dev/docs/storefronts/themes/architecture/sections) are Liquid files that allow you to create reusable modules of content that can be customized by merchants. They can also include blocks which allow merchants to add, remove, and reorder content within a section. - -Sections are made customizable by including a `{% schema %}` in the body. For more information, refer to the [section schema documentation](https://shopify.dev/docs/storefronts/themes/architecture/sections/section-schema). - -### Blocks - -[Blocks](https://shopify.dev/docs/storefronts/themes/architecture/blocks) let developers create flexible layouts by breaking down sections into smaller, reusable pieces of Liquid. Each block has its own set of settings, and can be added, removed, and reordered within a section. - -Blocks are made customizable by including a `{% schema %}` in the body. For more information, refer to the [block schema documentation](https://shopify.dev/docs/storefronts/themes/architecture/blocks/theme-blocks/schema). - -## Schemas - -When developing components defined by schema settings, we recommend these guidelines to simplify your code: - -- **Single property settings**: For settings that correspond to a single CSS property, use CSS variables: - - ```liquid -
    - ... -
    - - {% stylesheet %} - .collection { - gap: var(--gap); - } - {% endstylesheet %} - - {% schema %} - { - "settings": [{ - "type": "range", - "label": "gap", - "id": "gap", - "min": 0, - "max": 100, - "unit": "px", - "default": 0, - }] - } - {% endschema %} - ``` - -- **Multiple property settings**: For settings that control multiple CSS properties, use CSS classes: - - ```liquid -
    - ... -
    - - {% stylesheet %} - .collection--full-width { - /* multiple styles */ - } - .collection--narrow { - /* multiple styles */ - } - {% endstylesheet %} - - {% schema %} - { - "settings": [{ - "type": "select", - "id": "layout", - "label": "layout", - "values": [ - { "value": "collection--full-width", "label": "t:options.full" }, - { "value": "collection--narrow", "label": "t:options.narrow" } - ] - }] - } - {% endschema %} - ``` - -## CSS & JavaScript - -For CSS and JavaScript, we recommend using the [`{% stylesheet %}`](https://shopify.dev/docs/api/liquid/tags#stylesheet) and [`{% javascript %}`](https://shopify.dev/docs/api/liquid/tags/javascript) tags. They can be included multiple times, but the code will only appear once. - -### `critical.css` - -The Skeleton Theme explicitly separates essential CSS necessary for every page into a dedicated `critical.css` file. - -## Contributing - -We're excited for your contributions to the Skeleton Theme! This repository aims to remain as lean, lightweight, and fundamental as possible, and we kindly ask your contributions to align with this intention. - -Visit our [CONTRIBUTING.md](./CONTRIBUTING.md) for a detailed overview of our process, guidelines, and recommendations. - -## License - -Skeleton Theme is open-sourced under the [MIT](./LICENSE.md) License. +

    +
    + logo +
    + Shopify Skeleton Theme +

    + +A minimal Shopify theme built on block-first composition. Templates compose each +page directly from blocks, snippets, and inline markup — no sections, no JSON +templates. It's designed to stay lean and to be edited by coding agents as +readily as by people. + +

    + License + CI +

    + +## Getting started + +### Prerequisites + +Before starting, ensure you have the latest Shopify CLI installed: + +- [Shopify CLI](https://shopify.dev/docs/api/shopify-cli) – helps you download, upload, preview themes, and streamline your workflows + +If you use VS Code: + +- [Shopify Liquid VS Code Extension](https://shopify.dev/docs/storefronts/themes/tools/shopify-liquid-vscode) – provides syntax highlighting, linting, inline documentation, and auto-completion specifically designed for Liquid templates + +### Clone + +Clone this repository using Git or Shopify CLI: + +```bash +git clone git@github.com:Shopify/skeleton-theme.git +# or +shopify theme init +``` + +### Preview + +Preview this theme using Shopify CLI: + +```bash +shopify theme dev +``` + +## Theme architecture + +```bash +. +├── assets # Static assets, including critical.css (all theme CSS) +├── blocks # Reusable, nestable, customizable UI components +├── config # Global theme settings and customization options +├── layout # Top-level page wrappers +├── locales # Translation files for theme internationalization +├── snippets # Reusable Liquid code or HTML fragments +└── templates # Liquid composition roots, one per page type +``` + +To learn more, refer to the [theme architecture documentation](https://shopify.dev/docs/storefronts/themes/architecture). + +## Block-first composition + +Every page is composed from blocks. The composition flows in one direction: + +``` +templates/*.liquid → {% block 'container' %} → blocks / snippets / inline markup +``` + +### Templates + +[Templates](https://shopify.dev/docs/storefronts/themes/architecture/templates#template-types) +control what's rendered on each type of page. In this theme they are Liquid +files (`templates/*.liquid`), not JSON. Each template is a composition root: it +wraps its page content in the `container` block and composes the rest from +blocks and inline markup. + +For example, `templates/index.liquid` composes the `hello-world` block inside a +container: + +```liquid +{% block 'container', tag: 'div' %} + {% block 'hello-world' %}{% endblock %} +{% endblock %} +``` + +### Blocks + +[Blocks](https://shopify.dev/docs/storefronts/themes/architecture/blocks) are +the theme's building units. Each block is a single file in `blocks/`, opens with +a `{% doc %}` header describing its parameters, and ends with a `{% schema %}` +(no `presets`). A block renders caller-supplied content through +`{{ block.content }}` and keeps `{{ block.shopify_attributes }}` on its root +element for theme-editor support. + +The `container` block owns each page's outer layout element; `blocks/hello-world.liquid` +is the theme's starter demo block. `layout/theme.liquid` composes the `header` +and `footer` blocks directly, keeping the layout a thin shell. + +## Non-negotiables + +This theme deliberately excludes the section-based model. When editing it: + +- No `sections/` directory, and no `{% section %}` / `{% sections %}` tags. +- No JSON templates and no schema `presets`. +- No Liquid-embedded assets: keep CSS in `assets/critical.css` rather than + `{% stylesheet %}` / `{% javascript %}` blocks. +- Compose pages from blocks and inline markup, not single-use page sections. + +[`AGENTS.md`](./AGENTS.md) is the source of truth for the theme's dialect and the +full set of rules coding agents follow. + +## CSS + +All theme CSS lives in [`assets/critical.css`](./assets/critical.css), loaded +once from `layout/theme.liquid`. Keeping styles in one file — rather than +embedding them in Liquid — preserves the theme's minimalism and keeps blocks +markup-only. + +## Contributing + +We're excited for your contributions to the Skeleton Theme! This repository aims to remain as lean, lightweight, and fundamental as possible, and we kindly ask your contributions to align with this intention. + +Visit our [CONTRIBUTING.md](./CONTRIBUTING.md) for a detailed overview of our process, guidelines, and recommendations. + +## License + +Skeleton Theme is open-sourced under the [MIT](./LICENSE.md) License. diff --git a/assets/critical.css b/assets/critical.css index cdb1ae1aa..4add24c7c 100644 --- a/assets/critical.css +++ b/assets/critical.css @@ -115,3 +115,187 @@ body { .shopify-section > .full-width { grid-column: 1 / -1; } + +/** Hello world block */ +.welcome { + display: grid; + grid-template-columns: var(--content-grid); + background-color: #f6f6f7; + padding: 72px 0; +} + +.welcome-content { + grid-column: 2; + display: flex; + justify-content: space-between; + align-items: center; + gap: 1rem; + width: 100%; + padding: 0 24px; +} + +.welcome-description { + max-width: 80ch; + line-height: 1.4; + margin-top: 1.5rem; +} + +.icon { + width: 300px; +} + +.highlights { + display: grid; + gap: 2rem; + grid-template-columns: repeat(3, 1fr); + margin-top: 50px; +} + +@media (max-width: 1100px) { + .highlights { + grid-template-columns: 1fr; + } +} + +.highlight { + display: flex; + flex-direction: column; + height: 100%; + padding: 24px; + border-radius: 8px; + background-color: #eef3ff; + color: rgb(92, 95, 98); + line-height: 1.4; +} + +.highlight > * + * { + margin-top: 1rem; +} + +.highlight h3 { + font-size: 1rem; + color: rgb(32, 34, 35); +} + +.highlight-description { + flex: 1 1; +} + +.highlight a { + display: flex; + width: fit-content; + background-color: rgb(250, 251, 251); + box-shadow: rgba(0, 0, 0, 0.2) 0px -3px 0px 0px inset, rgba(255, 255, 255, 0.9) 0px 2px 0px 0px inset; + border: 1px solid rgb(140, 145, 150); + border-radius: 4px; + color: rgb(92, 95, 98); + padding: 3px 10px 5px; + text-decoration: none; +} + +/** Text block */ +.text { + text-align: var(--text-align); +} +.text--title { + font-size: 2rem; + font-weight: 700; +} +.text--subtitle { + font-size: 1.5rem; +} + +/** Collection page */ +.collection-products { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(500px, 1fr)); +} + +/** Collections list page */ +.collections { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(min(var(--collection-card-size), 100%), 1fr)); + gap: var(--grid-gap); +} +.collections--compact { + --collection-card-size: 160px; +} +.collections--full { + --collection-card-size: 280px; +} +.collection-card { + display: flex; + flex-direction: column; + width: 100%; +} + +/** Search page */ +.search-results { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); +} +.search-results .prev, +.search-results .page, +.search-results .next { + grid-column: 1 / -1; +} + +/** Header */ +header { + height: 5rem; + display: flex; + align-items: center; + justify-content: space-between; +} +header a { + position: relative; + text-decoration: none; + color: var(--color-foreground); + display: flex; + align-items: center; + justify-content: center; +} +header a sup { + position: absolute; + left: 100%; + overflow: hidden; + max-width: var(--page-margin); +} +header svg { + width: 2rem; +} +header .header__menu, +header .header__icons { + display: flex; + gap: 1rem; +} + +/** Footer */ +footer { + display: flex; + justify-content: space-between; + margin-top: 2rem; +} +footer a { + text-decoration: none; + color: var(--color-foreground); +} +footer .footer__links, +footer .footer__payment { + display: flex; + gap: 1rem; +} + +/** Image snippet */ +.image { + display: block; + position: relative; + overflow: hidden; + width: 100%; + height: auto; +} + +.image > img { + width: 100%; + height: auto; +} diff --git a/blocks/container.liquid b/blocks/container.liquid new file mode 100644 index 000000000..98fd16839 --- /dev/null +++ b/blocks/container.liquid @@ -0,0 +1,33 @@ +{% doc %} + Wraps composed page content in a semantic HTML element. Every template + composes its page through a container block: the block owns the outer + layout element and renders the composed body via {{ block.content }}. + + @param {string} [tag] - HTML element for the wrapper. Default: 'section'. + + @example Default section wrapper + {% block 'container' %} +

    {{ page.title }}

    + {{ page.content }} + {% endblock %} + + @example Override the wrapper element + {% block 'container', tag: 'div' %} + ... + {% endblock %} +{% enddoc %} + +{%- liquid + assign tag = tag | default: 'section' +-%} + +<{{ tag }} {{ block.shopify_attributes }}> + {{ block.content }} + + +{% schema %} +{ + "name": "Container", + "settings": [] +} +{% endschema %} diff --git a/sections/footer.liquid b/blocks/footer.liquid similarity index 64% rename from sections/footer.liquid rename to blocks/footer.liquid index 66e6f0978..309f43a36 100644 --- a/sections/footer.liquid +++ b/blocks/footer.liquid @@ -1,4 +1,10 @@ -