RuleStack

Configs

Stacks

Compare

Diff

RuleStack

Configs

Stacks

Compare

Diff

Read API

RuleStack

Configs

Stacks

Compare

Diff

Read API

Configs/Cursor rules/Shopify/horizon

Cursor rule

.cursor/rules/blocks.mdc

Development standards and best practices for creating/configuring/styling theme blocks, including static and nested blocks, schema configuration, CSS, and usage examples

Cursor rules

Quality

62/100

Scores the file, not the repository.

Length

1,197 words

27 headings · 22 code blocks

Repository

428

— · pushed 17 days ago

Last changed

3 days ago

First indexed 3 days ago.
Shopify/horizon/.cursor/rules/blocks.mdcRawGitHub
1---
2description: Development standards and best practices for creating/configuring/styling theme blocks, including static and nested blocks, schema configuration, CSS, and usage examples
3globs: blocks/*.liquid
4alwaysApply: false
5---
6 
7# Theme Blocks Development Standards
8 
9Follow [Shopify's theme blocks documentation](mdc:https:/shopify.dev/docs/storefronts/themes/architecture/blocks/theme-blocks/quick-start?framework=liquid.txt).
10 
11## Theme Block Fundamentals
12 
13Theme blocks are reusable components defined at the theme level that can be:
14 
15- Nested under sections and blocks
16- Configured using settings in the theme editor
17- Given presets and added by merchants
18- Used as [static blocks](mdc:https:/shopify.dev/docs/storefronts/themes/architecture/blocks/theme-blocks/static-blocks#statically-vs-dynamically-rendered-theme-blocks) by theme developers
19 
20Blocks render in the editor and storefront when they are referenced in [template files](mdc:.cursor/rules/templates.mdc).
21 
22### Basic Block Structure
23 
24```liquid
25{% doc %}
26 Block description and usage examples
27 
28 @example
29 {% content_for 'block', type: 'block-name', id: 'unique-id' %}
30{% enddoc %}
31 
32<div
33 {{ block.shopify_attributes }}
34 class='block-name'
35>
36 <!-- Block content using block.settings -->
37</div>
38 
39{% stylesheet %}
40 /*
41 Scoped CSS for this block
42 
43 Use BEM structure
44 CSS written in here should be for components that are exclusively in this block. If the CSS will be used elsewhere, it should instead be written in [assets/base.css](mdc:@assets/base.css)
45 */
46{% endstylesheet %}
47 
48{% schema %}
49{
50 "name": "Block Name",
51 "settings": [],
52 "presets": []
53}
54{% endschema %}
55```
56 
57### Static Block Usage
58 
59Static blocks are theme blocks that are rendered directly in Liquid templates by developers, rather than being dynamically added through the theme editor. This allows for predetermined block placement with optional default settings.
60 
61**Basic Static Block Syntax:**
62 
63```liquid
64{% content_for 'block', type: 'text', id: 'header-announcement' %}
65```
66 
67**Example: Product Template with Mixed Static and Dynamic Blocks**
68 
69```liquid
70<!-- templates/product.liquid -->
71<div class='product-page'>
72 {% comment %} Static breadcrumb block {% endcomment %}
73 {% content_for 'block', type: 'breadcrumb', id: 'product-breadcrumb' %}
74 
75 <div class='product-main'>
76 <div class='product-media'>
77 {% comment %} Static product gallery block {% endcomment %}
78 {%
79 content_for 'block', type: 'product-gallery', id: 'main-gallery', settings: {
80 enable_zoom: true,
81 thumbnails_position: "bottom"
82 }
83 %}
84 </div>
85 
86 <div class='product-info'>
87 {% comment %} Static product info blocks {% endcomment %}
88 {% content_for 'block', type: 'product-title', id: 'product-title' %}
89 {% content_for 'block', type: 'product-price', id: 'product-price' %}
90 {% content_for 'block', type: 'product-form', id: 'product-form' %}
91 
92 {% comment %} Dynamic blocks area for additional content {% endcomment %}
93 <div class='product-extra-content'>
94 {% content_for 'blocks' %}
95 </div>
96 </div>
97 </div>
98 
99 {% comment %} Static related products block {% endcomment %}
100 {%
101 content_for 'block', type: 'related-products', id: 'related-products', settings: {
102 heading: "You might also like",
103 limit: 4
104 }
105 %}
106</div>
107```
108 
109**Key Points about Static Blocks:**
110 
111- They have a fixed `id` that makes them identifiable in the theme editor
112- Settings can be overridden in the theme editor despite having defaults
113- They appear in the theme editor as locked blocks that can't be removed or reordered
114- Useful for consistent layout elements that should always be present
115- Can be mixed with dynamic block areas using `{% content_for 'blocks' %}`
116 
117## Schema Configuration
118 
119See [schemas.mdc](mdc:.cursor/rules/schemas.mdc) for rules on schemas
120 
121### Advanced Schema Features
122 
123#### Exclude wrapper
124 
125```json
126{
127 "tag": null // No wrapper - must include {{ block.shopify_attributes }} for proper editor function
128}
129```
130 
131## Block Implementation Patterns
132 
133### Accessing Block Data
134 
135**Block Settings:**
136 
137```liquid
138{{ block.settings.text }}
139{{ block.settings.heading | escape }}
140{{ block.settings.image | image_url: width: 800 }}
141```
142 
143**Block Properties:**
144 
145```liquid
146{{ block.id }} // Unique block identifier {{ block.type }} // Block type name {{ block.shopify_attributes }} // Required
147for theme editor
148```
149 
150**Section Context:**
151 
152```liquid
153{{ section.id }} // Parent section ID
154{{ section.settings.heading | escape }}
155{{ section.settings.image | image_url: width: 800 }}
156```
157 
158## Nested Blocks Implementation
159 
160### Critical Constraint: Single `content_for 'blocks'` Per File
161 
162**IMPORTANT:** There can only be **ONE** `{% content_for 'blocks' %}` call per Liquid file. If you need to use the blocks content in multiple places (e.g., in conditional branches), you must capture it first:
163 
164```liquid
165{% comment %} ✅ CORRECT - Capture once, use multiple times {% endcomment %}
166{% capture blocks_content %}
167 {% content_for 'blocks' %}
168{% endcapture %}
169 
170{% if condition %}
171 <div class='layout-a'>
172 {{ blocks_content }}
173 </div>
174{% else %}
175 <div class='layout-b'>
176 {{ blocks_content }}
177 </div>
178{% endif %}
179```
180 
181```liquid
182{% comment %} ❌ INCORRECT - Multiple content_for calls will cause errors {% endcomment %}
183{% if condition %}
184 <div class='layout-a'>
185 {% content_for 'blocks' %}
186 <!-- First call -->
187 </div>
188{% else %}
189 <div class='layout-b'>
190 {% content_for 'blocks' %}
191 <!-- ERROR: Duplicate entry -->
192 </div>
193{% endif %}
194```
195 
196**Common Error Message:**
197 
198```
199Liquid syntax error: Duplicate entries for 'content_for "blocks"'
200```
201 
202### Rendering Nested Blocks
203 
204```liquid
205<div
206 class='block-container'
207 {{ block.shopify_attributes }}
208>
209 <h2>{{ block.settings.heading | escape }}</h2>
210 
211 <div class='nested-blocks'>
212 {% content_for 'blocks' %}
213 </div>
214</div>
215```
216 
217### Nesting with Layout Control
218 
219```liquid
220<div
221 class='group {{ block.settings.layout_direction }}'
222 style='--gap: {{ block.settings.gap }}px;'
223 {{ block.shopify_attributes }}
224>
225 {% content_for 'blocks' %}
226</div>
227```
228 
229### Presets with Nested Blocks
230 
231```json
232{
233 "presets": [
234 {
235 "name": "t:names.two_column_layout",
236 "category": "Layout",
237 "settings": {
238 "layout_direction": "horizontal"
239 },
240 "blocks": [
241 {
242 "type": "text",
243 "settings": {
244 "text": "Column 1 content"
245 }
246 },
247 {
248 "type": "text",
249 "settings": {
250 "text": "Column 2 content"
251 }
252 }
253 ]
254 }
255 ]
256}
257```
258 
259When blocks are declared as an object instead of an array, include `block_order`:
260 
261```javascript
262blocks: {
263 header: {
264 type: 'group',
265 blocks: {
266 title: { type: 'product-title' },
267 price: { type: 'price' },
268 },
269 block_order: ['title', 'price'],
270 },
271}
272```
273 
274## CSS and Styling
275 
276See [css-standards.mdc](mdc:.cursor/rules/css-standards.mdc) for rules on writing CSS
277 
278### Scoped Styles
279 
280```liquid
281{% stylesheet %}
282 .block-name {
283 padding: var(--block-padding, 1rem);
284 background: var(--block-background, transparent);
285 }
286 
287 .block-name__title {
288 font-size: var(--title-size, 1.5rem);
289 color: var(--title-color, inherit);
290 }
291 
292 .block-name--primary {
293 background-color: var(--color-primary);
294 }
295 
296 .block-name--secondary {
297 background-color: var(--color-secondary);
298 }
299{% endstylesheet %}
300```
301 
302### Dynamic CSS Variables
303 
304```liquid
305<div
306 class="custom-block"
307 style="
308 --block-padding: {{ block.settings.padding }}px;
309 --text-align: {{ block.settings.alignment }};
310 --background: {{ block.settings.background_color }};
311 "
312 {{ block.shopify_attributes }}
313>
314```
315 
316## Block Targeting
317 
318### Section Schema for Theme Blocks
319 
320```json
321{
322 "blocks": [
323 { "type": "@theme" }, // Accept all theme blocks
324 { "type": "@app" } // Accept app blocks
325 ]
326}
327```
328 
329### Restricted Block Targeting
330 
331```json
332{
333 "blocks": [
334 {
335 "type": "text",
336 "name": "Text Content"
337 },
338 {
339 "type": "image",
340 "name": "Image Content"
341 }
342 ]
343}
344```
345 
346## Common Block Patterns
347 
348### Content Block
349 
350```liquid
351<div
352 class='content-block {{ block.settings.style }}'
353 {{ block.shopify_attributes }}
354>
355 {% if block.settings.heading != blank %}
356 <h3 class='content-block__heading'>{{ block.settings.heading | escape }}</h3>
357 {% endif %}
358 
359 {% if block.settings.text != blank %}
360 <div class='content-block__text'>{{ block.settings.text }}</div>
361 {% endif %}
362 
363 {% if block.settings.button_text != blank %}
364 <a
365 href='{{ block.settings.button_url }}'
366 class='content-block__button'
367 >
368 {{ block.settings.button_text | escape }}
369 </a>
370 {% endif %}
371</div>
372```
373 
374### Media Block
375 
376```liquid
377<div
378 class='media-block'
379 {{ block.shopify_attributes }}
380>
381 {% if block.settings.image %}
382 <div class='media-block__image'>
383 {{
384 block.settings.image
385 | image_url: width: 800
386 | image_tag: alt: block.settings.image.alt
387 | default: block.settings.alt_text
388 }}
389 </div>
390 {% endif %}
391 
392 {% if block.settings.video %}
393 <div class='media-block__video'>
394 {{ block.settings.video | video_tag: controls: true }}
395 </div>
396 {% endif %}
397</div>
398```
399 
400### Layout Block (Container)
401 
402```liquid
403<div
404 class='layout-block layout-block--{{ block.settings.layout_type }}'
405 style='
406 --columns: {{ block.settings.columns }};
407 --gap: {{ block.settings.gap }}px;
408 '
409 {{ block.shopify_attributes }}
410>
411 {% content_for 'blocks' %}
412</div>
413```
414 
415## Performance Best Practices
416 
417### Conditional Rendering
418 
419```liquid
420{% liquid
421 assign has_content = false
422 if block.settings.heading != blank or block.settings.text != blank
423 assign has_content = true
424 endif
425%}
426 
427{% if has_content %}
428 <div
429 class='block-content'
430 {{ block.shopify_attributes }}
431 >
432 <!-- Content here -->
433 </div>
434{% endif %}
435```
436 
437## Examples Referenced
438 
439[text.liquid](mdc:.cursor/rules/examples/block-example-text.liquid) - Basic content block from existing project
440[group.liquid](mdc:.cursor/rules/examples/block-example-group.liquid) - Container with nested blocks from existing project
441 

Sections

  • Theme Blocks Development Standards
  • Theme Block Fundamentals
  • Basic Block Structure
  • Static Block Usage
  • Schema Configuration
  • Advanced Schema Features
  • Block Implementation Patterns
  • Accessing Block Data
  • Nested Blocks Implementation
  • Critical Constraint: Single `content_for 'blocks'` Per File
  • Rendering Nested Blocks
  • Nesting with Layout Control
  • Presets with Nested Blocks
  • CSS and Styling
  • Scoped Styles
  • Dynamic CSS Variables
  • Block Targeting
  • Section Schema for Theme Blocks
  • Restricted Block Targeting
  • Common Block Patterns
  • Content Block
  • Media Block
  • Layout Block (Container)
  • Performance Best Practices
  • Conditional Rendering
  • Examples Referenced

What it covers

code-stylearchitecturetypesdatabaseuiperformance

Glob targeting

  • blocks/*.liquid

Format

Cursor rules

The most expressive format here. Many small .mdc files, each with frontmatter declaring when it should load, so a rule about migrations only enters context when a migration is open. Costs the most to maintain and only one editor reads it.

What the corpus says about it

Repository

Owner
Shopify
Language
—
License
—
Archived
no

All configs in this repo

Also in Shopify/horizon

Diff this repo’s formats

One repository carrying more than one format is the comparison this product exists for: does anyone actually write different content in each file, or is one a copy of the other?

The other instruction files in this repository
RepositoryFormatStackCoversScoreChanged
Shopify/horizon.cursor/rules/accordion-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/animation-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/breadcrumb-accessibility.mdc · 428Cursor rulesunclassifiedui36/1003 days ago
Shopify/horizon.cursor/rules/carousel-accessibility.mdc · 428Cursor rulesunclassifiedui32/1003 days ago
Shopify/horizon.cursor/rules/cart-drawer-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/chat-window-accessibility.mdc · 428Cursor rulesunclassifiedstyleui24/1003 days ago
Shopify/horizon.cursor/rules/color-contrast-accessibility.mdc · 428Cursor rulesunclassifiedlint-formatui44/1003 days ago
Shopify/horizon.cursor/rules/color-swatch-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/commit-messages.mdc · 428Cursor rulesunclassifiedsetuplint-formattypesgit62/1003 days ago
Shopify/horizon.cursor/rules/css-standards.mdc · 428Cursor rulesunclassifiedstylearchuiperformance+349/1003 days ago
Shopify/horizon.cursor/rules/disclosure-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/dropdown-navigation-accessibility.mdc · 428Cursor rulesunclassifiedstyleui36/1003 days ago
Shopify/horizon.cursor/rules/flip-card-accessibility.mdc · 428Cursor rulesunclassifiedstyleui36/1003 days ago
Shopify/horizon.cursor/rules/form-accessibility.mdc · 428Cursor rulesunclassifiedui32/1003 days ago
Shopify/horizon.cursor/rules/javascript-standards.mdc · 428Cursor rulesunclassifiedstylearchtypesui+254/1003 days ago
Shopify/horizon.cursor/rules/landmark-accessibility.mdc · 428Cursor rulesunclassifiedui40/1003 days ago
Shopify/horizon.cursor/rules/liquid.mdc · 428Cursor rulesunclassifiedbuildstyletypesdatabase+277/1003 days ago
Shopify/horizon.cursor/rules/locales.mdc · 428Cursor rulesunclassifiedarch49/1003 days ago
Shopify/horizon.cursor/rules/localization.mdc · 428Cursor rulesunclassifiedstyle54/1003 days ago
Shopify/horizon.cursor/rules/mobile-accessibility-standards.mdc · 428Cursor rulesunclassifiedstyleui36/1003 days ago
Diff against .cursor/rules/accordion-accessibility.mdc Diff against .cursor/rules/animation-accessibility.mdc Diff against .cursor/rules/breadcrumb-accessibility.mdc Diff against .cursor/rules/carousel-accessibility.mdc Diff against .cursor/rules/cart-drawer-accessibility.mdc Diff against .cursor/rules/chat-window-accessibility.mdc Diff against .cursor/rules/color-contrast-accessibility.mdc Diff against .cursor/rules/color-swatch-accessibility.mdc Diff against .cursor/rules/commit-messages.mdc Diff against .cursor/rules/css-standards.mdc Diff against .cursor/rules/disclosure-accessibility.mdc Diff against .cursor/rules/dropdown-navigation-accessibility.mdc Diff against .cursor/rules/flip-card-accessibility.mdc Diff against .cursor/rules/form-accessibility.mdc Diff against .cursor/rules/javascript-standards.mdc Diff against .cursor/rules/landmark-accessibility.mdc Diff against .cursor/rules/liquid.mdc Diff against .cursor/rules/locales.mdc Diff against .cursor/rules/localization.mdc Diff against .cursor/rules/mobile-accessibility-standards.mdc
RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack

RuleStack

Built by

Kynth Studio

Directory

Configs
Stacks
Compare formats
Diff two configs
Best AGENTS.md examples

Formats

AGENTS.md
CLAUDE.md
Cursor rules
Copilot instructions

Reference

Read API
Corpus health
Privacy Policy
Terms

RuleStack