@spree/docs 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/README.md +54 -0
  2. package/dist/api-reference/platform/authentication.md +38 -0
  3. package/dist/api-reference/store-api/authentication.md +188 -0
  4. package/dist/api-reference/store-api/errors.md +277 -0
  5. package/dist/api-reference/store-api/idempotency.md +129 -0
  6. package/dist/api-reference/store-api/introduction.md +34 -0
  7. package/dist/api-reference/store-api/localization.md +279 -0
  8. package/dist/api-reference/store-api/metadata.md +160 -0
  9. package/dist/api-reference/store-api/monetary-amounts.md +65 -0
  10. package/dist/api-reference/store-api/querying.md +399 -0
  11. package/dist/api-reference/store-api/rate-limitting.md +103 -0
  12. package/dist/api-reference/store-api/relations.md +185 -0
  13. package/dist/api-reference/storefront/authentication.md +88 -0
  14. package/dist/api-reference/tutorials/adyen-integration-guide-for-android.md +165 -0
  15. package/dist/api-reference/tutorials/adyen-integration-guide-for-ios.md +194 -0
  16. package/dist/api-reference/tutorials/quick-checkout-with-stripe.md +248 -0
  17. package/dist/api-reference/v2/fetching-multiple-resources.md +26 -0
  18. package/dist/api-reference/v2/filtering-and-sorting.md +53 -0
  19. package/dist/api-reference/v2/introduction.md +22 -0
  20. package/dist/api-reference/v2/pagination.md +37 -0
  21. package/dist/api-reference/webhooks-events.md +883 -0
  22. package/dist/developer/admin/admin.md +205 -0
  23. package/dist/developer/admin/authentication.md +59 -0
  24. package/dist/developer/admin/components.md +711 -0
  25. package/dist/developer/admin/custom-css.md +243 -0
  26. package/dist/developer/admin/custom-javascript.md +116 -0
  27. package/dist/developer/admin/extending-ui.md +1964 -0
  28. package/dist/developer/admin/form-builder.md +444 -0
  29. package/dist/developer/admin/helper-methods.md +531 -0
  30. package/dist/developer/admin/navigation.md +805 -0
  31. package/dist/developer/admin/tables.md +491 -0
  32. package/dist/developer/advanced/adding_spree_to_rails_app.md +106 -0
  33. package/dist/developer/cli/quickstart.md +137 -0
  34. package/dist/developer/contributing/creating-an-extension.md +258 -0
  35. package/dist/developer/contributing/developing-spree.md +339 -0
  36. package/dist/developer/contributing/quickstart.md +32 -0
  37. package/dist/developer/contributing/updating-extensions.md +67 -0
  38. package/dist/developer/core-concepts/addresses.md +265 -0
  39. package/dist/developer/core-concepts/adjustments.md +107 -0
  40. package/dist/developer/core-concepts/architecture.md +177 -0
  41. package/dist/developer/core-concepts/calculators.md +323 -0
  42. package/dist/developer/core-concepts/customers.md +230 -0
  43. package/dist/developer/core-concepts/events.md +624 -0
  44. package/dist/developer/core-concepts/imports-exports.md +698 -0
  45. package/dist/developer/core-concepts/inventory.md +191 -0
  46. package/dist/developer/core-concepts/markets.md +250 -0
  47. package/dist/developer/core-concepts/media.md +167 -0
  48. package/dist/developer/core-concepts/metafields.md +187 -0
  49. package/dist/developer/core-concepts/orders.md +328 -0
  50. package/dist/developer/core-concepts/payments.md +710 -0
  51. package/dist/developer/core-concepts/pricing.md +163 -0
  52. package/dist/developer/core-concepts/products.md +360 -0
  53. package/dist/developer/core-concepts/promotions.md +322 -0
  54. package/dist/developer/core-concepts/reports.md +206 -0
  55. package/dist/developer/core-concepts/search-filtering.md +237 -0
  56. package/dist/developer/core-concepts/shipments.md +212 -0
  57. package/dist/developer/core-concepts/slugs.md +111 -0
  58. package/dist/developer/core-concepts/staff-roles.md +123 -0
  59. package/dist/developer/core-concepts/store-credits-gift-cards.md +317 -0
  60. package/dist/developer/core-concepts/stores.md +117 -0
  61. package/dist/developer/core-concepts/taxes.md +135 -0
  62. package/dist/developer/core-concepts/translations.md +120 -0
  63. package/dist/developer/core-concepts/users.md +299 -0
  64. package/dist/developer/core-concepts/webhooks.md +378 -0
  65. package/dist/developer/create-spree-app/quickstart.md +158 -0
  66. package/dist/developer/customization/api.md +93 -0
  67. package/dist/developer/customization/authentication.md +88 -0
  68. package/dist/developer/customization/checkout.md +204 -0
  69. package/dist/developer/customization/configuration.md +55 -0
  70. package/dist/developer/customization/decorators.md +523 -0
  71. package/dist/developer/customization/dependencies.md +232 -0
  72. package/dist/developer/customization/emails.md +21 -0
  73. package/dist/developer/customization/extensions.md +92 -0
  74. package/dist/developer/customization/metadata.md +236 -0
  75. package/dist/developer/customization/model-preferences.md +130 -0
  76. package/dist/developer/customization/permissions.md +265 -0
  77. package/dist/developer/customization/quickstart.md +229 -0
  78. package/dist/developer/customization/routes.md +24 -0
  79. package/dist/developer/customization/v4/admin-panel.md +78 -0
  80. package/dist/developer/customization/v4/authentication.md +210 -0
  81. package/dist/developer/customization/v4/checkout.md +212 -0
  82. package/dist/developer/customization/v4/deface.md +251 -0
  83. package/dist/developer/customization/v4/images.md +86 -0
  84. package/dist/developer/customization/v4/storefront.md +450 -0
  85. package/dist/developer/deployment/assets.md +87 -0
  86. package/dist/developer/deployment/aws.md +335 -0
  87. package/dist/developer/deployment/caching.md +27 -0
  88. package/dist/developer/deployment/cdn.md +39 -0
  89. package/dist/developer/deployment/database.md +155 -0
  90. package/dist/developer/deployment/docker.md +128 -0
  91. package/dist/developer/deployment/emails.md +77 -0
  92. package/dist/developer/deployment/environment_variables.md +111 -0
  93. package/dist/developer/deployment/heroku.md +51 -0
  94. package/dist/developer/deployment/render.md +95 -0
  95. package/dist/developer/getting-started/quickstart.md +82 -0
  96. package/dist/developer/how-to/custom-payment-method.md +374 -0
  97. package/dist/developer/how-to/custom-promotion.md +373 -0
  98. package/dist/developer/how-to/custom-report.md +387 -0
  99. package/dist/developer/how-to/custom-search-provider.md +230 -0
  100. package/dist/developer/multi-store/quickstart.md +71 -0
  101. package/dist/developer/multi-store/setup.md +38 -0
  102. package/dist/developer/multi-tenant/configuration.md +41 -0
  103. package/dist/developer/multi-tenant/core-concepts.md +75 -0
  104. package/dist/developer/multi-tenant/installation.md +96 -0
  105. package/dist/developer/multi-tenant/quickstart.md +20 -0
  106. package/dist/developer/multi-vendor/installation.md +45 -0
  107. package/dist/developer/multi-vendor/quickstart.md +17 -0
  108. package/dist/developer/sdk/admin/quickstart.md +22 -0
  109. package/dist/developer/sdk/authentication.md +89 -0
  110. package/dist/developer/sdk/configuration.md +225 -0
  111. package/dist/developer/sdk/quickstart.md +82 -0
  112. package/dist/developer/sdk/store/account.md +67 -0
  113. package/dist/developer/sdk/store/cart-checkout.md +140 -0
  114. package/dist/developer/sdk/store/markets.md +151 -0
  115. package/dist/developer/sdk/store/payments.md +96 -0
  116. package/dist/developer/sdk/store/products.md +149 -0
  117. package/dist/developer/sdk/store/wishlists.md +52 -0
  118. package/dist/developer/security/pci_compliance.md +15 -0
  119. package/dist/developer/security/security_policy.md +68 -0
  120. package/dist/developer/storefront/blocks.md +285 -0
  121. package/dist/developer/storefront/custom-css.md +260 -0
  122. package/dist/developer/storefront/custom-javascript.md +166 -0
  123. package/dist/developer/storefront/helper-methods.md +1288 -0
  124. package/dist/developer/storefront/links.md +298 -0
  125. package/dist/developer/storefront/nextjs/architecture.md +150 -0
  126. package/dist/developer/storefront/nextjs/customization.md +141 -0
  127. package/dist/developer/storefront/nextjs/deployment.md +180 -0
  128. package/dist/developer/storefront/nextjs/quickstart.md +92 -0
  129. package/dist/developer/storefront/nextjs/spree-next-package.md +314 -0
  130. package/dist/developer/storefront/pages.md +163 -0
  131. package/dist/developer/storefront/sections.md +569 -0
  132. package/dist/developer/storefront/storefront.md +56 -0
  133. package/dist/developer/storefront/themes.md +161 -0
  134. package/dist/developer/tutorial/admin.md +134 -0
  135. package/dist/developer/tutorial/extending-models.md +380 -0
  136. package/dist/developer/tutorial/file-uploads.md +121 -0
  137. package/dist/developer/tutorial/introduction.md +33 -0
  138. package/dist/developer/tutorial/model.md +41 -0
  139. package/dist/developer/tutorial/page-builder.md +487 -0
  140. package/dist/developer/tutorial/rich-text.md +73 -0
  141. package/dist/developer/tutorial/seo.md +332 -0
  142. package/dist/developer/tutorial/storefront.md +352 -0
  143. package/dist/developer/tutorial/testing.md +558 -0
  144. package/dist/developer/upgrades/2.0-to-2.1.md +46 -0
  145. package/dist/developer/upgrades/2.1-to-2.2.md +59 -0
  146. package/dist/developer/upgrades/2.2-to-2.3.md +44 -0
  147. package/dist/developer/upgrades/2.3-to-2.4.md +42 -0
  148. package/dist/developer/upgrades/3.0-to-3.1.md +47 -0
  149. package/dist/developer/upgrades/3.1-to-3.2.md +34 -0
  150. package/dist/developer/upgrades/3.2-to-3.3.md +70 -0
  151. package/dist/developer/upgrades/3.3-to-3.4.md +36 -0
  152. package/dist/developer/upgrades/3.4-to-3.5.md +44 -0
  153. package/dist/developer/upgrades/3.5-to-3.6.md +40 -0
  154. package/dist/developer/upgrades/3.6-to-3.7.md +62 -0
  155. package/dist/developer/upgrades/3.7-to-4.0.md +152 -0
  156. package/dist/developer/upgrades/4.0-to-4.1.md +92 -0
  157. package/dist/developer/upgrades/4.1-to-4.2.md +109 -0
  158. package/dist/developer/upgrades/4.10-to-5.0.md +129 -0
  159. package/dist/developer/upgrades/4.2-to-4.3.md +100 -0
  160. package/dist/developer/upgrades/4.3-to-4.4.md +125 -0
  161. package/dist/developer/upgrades/4.4-to-4.5.md +94 -0
  162. package/dist/developer/upgrades/4.5-to-4.6.md +119 -0
  163. package/dist/developer/upgrades/4.6-to-4.7.md +39 -0
  164. package/dist/developer/upgrades/4.8-to-4.9.md +24 -0
  165. package/dist/developer/upgrades/4.9-to-4.10.md +24 -0
  166. package/dist/developer/upgrades/4.x-to-4.8.md +52 -0
  167. package/dist/developer/upgrades/5.0-to-5.1.md +28 -0
  168. package/dist/developer/upgrades/5.1-to-5.2.md +127 -0
  169. package/dist/developer/upgrades/5.2-to-5.3.md +338 -0
  170. package/dist/developer/upgrades/5.3-to-5.4.md +248 -0
  171. package/dist/developer/upgrades/quickstart.md +36 -0
  172. package/dist/integrations/analytics/google-analytics.md +64 -0
  173. package/dist/integrations/analytics/google-tag-manager.md +78 -0
  174. package/dist/integrations/integrations.md +39 -0
  175. package/dist/integrations/marketing/klaviyo.md +99 -0
  176. package/dist/integrations/payments/adyen.md +90 -0
  177. package/dist/integrations/payments/paypal.md +41 -0
  178. package/dist/integrations/payments/razorpay.md +45 -0
  179. package/dist/integrations/payments/stripe.md +109 -0
  180. package/dist/integrations/search/meilisearch.md +236 -0
  181. package/dist/integrations/sso-mfa-social-login/admin-dashboard.md +57 -0
  182. package/dist/integrations/sso-mfa-social-login/storefront.md +56 -0
  183. package/package.json +27 -0
@@ -0,0 +1,121 @@
1
+ ---
2
+ title: File Uploads
3
+ description: Learn how to add file uploads to the Brands feature
4
+ ---
5
+
6
+ > **INFO:** This guide assumes you've completed the [Model](/developer/tutorial/model), [Admin](/developer/tutorial/admin), and [Rich Text](/developer/tutorial/rich-text) tutorials.
7
+
8
+ In this tutorial, we'll add a logo image upload to our Brand model. Spree uses [Rails Active Storage](https://guides.rubyonrails.org/active_storage_overview.html) for handling file attachments, image processing, and storage.
9
+
10
+ ## Step 1: Add Attachment to the Model
11
+
12
+ First, let's add a logo attachment to the Brand model:
13
+
14
+ ```ruby app/models/spree/brand.rb {3}
15
+ module Spree
16
+ class Brand < Spree::Base
17
+ has_one_attached :logo
18
+
19
+ # ... existing code ...
20
+ end
21
+ end
22
+ ```
23
+
24
+ ## Step 2: Permit the Attachment Attribute
25
+
26
+ For the admin form to accept the file upload, we need to permit the `logo` attribute in the controller.
27
+
28
+ Update your brands controller:
29
+
30
+ ```ruby app/controllers/spree/admin/brands_controller.rb {10}
31
+ module Spree
32
+ module Admin
33
+ class BrandsController < ResourceController
34
+ private
35
+
36
+ def permitted_resource_params
37
+ params.require(:brand).permit(
38
+ :name,
39
+ :description,
40
+ :logo
41
+ )
42
+ end
43
+ end
44
+ end
45
+ end
46
+ ```
47
+
48
+ ## Step 3: Add File Upload Field to the Admin Form
49
+
50
+ Now let's add the file upload field to the brand form. Spree provides a `spree_file_field` helper that handles everything including:
51
+
52
+ - Drag and drop upload
53
+ - Image preview
54
+ - Direct upload to storage
55
+ - Optional image cropping
56
+
57
+ Update your brand form partial:
58
+
59
+ ```erb app/views/spree/admin/brands/_form.html.erb {11-19}
60
+ <div class="card mb-6">
61
+ <div class="card-header">
62
+ <h5 class="card-title"><%= Spree.t(:general_settings) %></h5>
63
+ </div>
64
+ <div class="card-body">
65
+ <%= f.spree_text_field :name, required: true %>
66
+ <%= f.spree_rich_text_area :description %>
67
+ </div>
68
+ </div>
69
+
70
+ <div class="card mb-6">
71
+ <div class="card-header">
72
+ <h5 class="card-title"><%= Spree.t(:logo) %></h5>
73
+ </div>
74
+ <div class="card-body">
75
+ <%= f.spree_file_field :logo, width: 300, height: 300 %>
76
+ </div>
77
+ </div>
78
+ ```
79
+
80
+ ### Add cropping functionality
81
+
82
+ To enable cropping functionality, add the `crop: true` option to the `spree_file_field` helper.
83
+
84
+ ## Step 4: Display the Logo in the Index Table
85
+
86
+ Let's show a thumbnail of the brand logo in the admin index view.
87
+
88
+ Update the table header partial:
89
+
90
+ ```erb app/views/spree/admin/brands/_table_header.html.erb {2}
91
+ <tr>
92
+ <th><%= Spree.t(:logo) %></th>
93
+ <th><%= Spree.t(:name) %></th>
94
+ <th></th>
95
+ </tr>
96
+ ```
97
+
98
+ Update the table row partial to display the logo:
99
+
100
+ ```erb app/views/spree/admin/brands/_table_row.html.erb {3-12}
101
+ <tr id="<%= spree_dom_id brand %>" class="cursor-pointer" data-controller="row-link">
102
+ <td data-action="click->row-link#openLink" class="w-70">
103
+ <div class="d-flex align-items-center gap-2">
104
+ <% if brand.logo.attached? %>
105
+ <%= spree_image_tag brand.logo, width: 48, height: 48, class: 'rounded' %>
106
+ <% else %>
107
+ <div class="bg-light rounded d-flex align-items-center justify-content-center" style="width: 48px; height: 48px;">
108
+ <%= icon('photo-off', class: 'text-muted') %>
109
+ </div>
110
+ <% end %>
111
+ <span class="font-weight-bold"><%= brand.name %></span>
112
+ </div>
113
+ </td>
114
+ <td data-action="click->row-link#openLink" class="w-20">
115
+ <%= spree_date(brand.created_at) %>
116
+ </td>
117
+ <td class="actions w-10">
118
+ <%= link_to_edit(brand, data: { row_link_target: :link, turbo_frame: '_top' }) if can? :edit, brand %>
119
+ </td>
120
+ </tr>
121
+ ```
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Tutorial
3
+ sidebarTitle: Introduction
4
+ description: Learn how to build a custom feature from scratch, covering models, Admin dashboard, API and Storefront.
5
+ ---
6
+
7
+ This tutorial walks you through creating a complete Spree feature from scratch, covering models, Admin dashboard and API.
8
+ You will also learn how to extend core Spree features to connect them with your new feature.
9
+ By the end, you'll understand how to add new manageable features to the Spree platform.
10
+
11
+ ## Overview
12
+
13
+ To fully implement a new feature, you will typically create the following components:
14
+
15
+ * Database model
16
+ * Admin Dashboard controllers and views
17
+ * Storefront views
18
+ * Automated tests
19
+
20
+ ## Tutorial Sections
21
+
22
+
23
+ - [1. Model](/developer/tutorial/model) — Create the Brand model with migrations, validations, and associations
24
+ - [2. Admin Dashboard](/developer/tutorial/admin) — Build admin interface for managing brands
25
+ - [3. Rich Text](/developer/tutorial/rich-text) — Add rich text descriptions using Action Text
26
+ - [4. File Uploads](/developer/tutorial/file-uploads) — Add logo images with Active Storage
27
+ - [5. Extending Core Models](/developer/tutorial/extending-models) — Connect Brands to Products using associations
28
+ - [7. Testing](/developer/tutorial/testing) — Write automated tests for your feature
29
+
30
+
31
+ ## Example: Building a Brands Feature
32
+
33
+ In this guide we will create a complete "Brands" feature that allows admins to manage [Product](/developer/core-concepts/products) brands.
@@ -0,0 +1,41 @@
1
+ ---
2
+ title: Model
3
+ description: Learn how to create a database model for the Brands feature
4
+ ---
5
+
6
+ ## Step 1: Create the Model and Database Migration
7
+
8
+ To create a new model and database migration file, run the following command:
9
+
10
+ ```bash
11
+ bin/rails g spree:model Spree::Brand name:string:index
12
+ ```
13
+
14
+ This will create a couple of files:
15
+ - `app/models/spree/brand.rb` - the model file
16
+ - `db/migrate/XXXXXXXXXXXXXX_create_spree_brands.rb` - the database migration file
17
+
18
+ Now run the migration:
19
+
20
+ ```bash
21
+ bin/rails db:migrate
22
+ ```
23
+
24
+ This will create the table `spree_brands` with the column `name` in the database. The `name` column is indexed for faster lookups. Also the model file `app/models/spree/brand.rb` is created.
25
+
26
+ ## Step 2: Extend the Model file
27
+
28
+ Now that the model file is created, let's add some additional functionality to it, starting with validations:
29
+
30
+ ```ruby app/models/spree/brand.rb {3-4}
31
+ module Spree
32
+ class Brand < Spree::Base
33
+ # Validations
34
+ validates :name, presence: true
35
+ end
36
+ end
37
+ ```
38
+
39
+ This is a standard [Ruby on Rails ActiveRecord model](https://guides.rubyonrails.org/active_record_basics.html). Let's break down each part:
40
+ - Inherits from `Spree::Base` to automatically inherit all Spree functionality. Also the model itself is namespaced under `Spree::` module, so it's available as `Spree::Brand` in the application.
41
+ - `validates :name, presence: true` - using ActiveRecord validations to ensure that the name is present.
@@ -0,0 +1,487 @@
1
+ ---
2
+ title: Page Builder Integration
3
+ description: Learn how to connect your Brands feature to Page Builder for admin-manageable pages
4
+ ---
5
+
6
+ In this tutorial, we'll enhance our brand pages by integrating them with Spree's Page Builder. This allows store administrators to customize page layouts, add sections, and modify designs without touching code.
7
+
8
+ > **INFO:** This guide assumes you've completed the [Storefront](/developer/tutorial/storefront) tutorial and have working brand pages.
9
+
10
+ ## What We're Building
11
+
12
+ By the end of this tutorial, you'll have:
13
+
14
+ - A **Brand List** page type manageable via Page Builder
15
+ - A **Brand** page type for individual brand pages
16
+ - Custom sections: `BrandGrid` and `BrandBanner`
17
+ - Full admin customization support
18
+
19
+ ## Understanding Page Builder Architecture
20
+
21
+ Page Builder uses three main components:
22
+
23
+ | Component | Purpose |
24
+ |-----------|---------|
25
+ | **Page** | Defines the page type (e.g., Homepage, Product Details, Brand List) |
26
+ | **Section** | Reusable content blocks within a page (e.g., Hero Banner, Product Grid) |
27
+ | **Block** | Smallest units within sections (e.g., Heading, Text, Button) |
28
+
29
+ ## Step 1: Create Page Types
30
+
31
+ ### Brand List Page
32
+
33
+ Create a page type for the brands listing:
34
+
35
+ ```ruby app/models/spree/pages/brand_list.rb
36
+ module Spree
37
+ module Pages
38
+ class BrandList < Spree::Page
39
+ def icon_name
40
+ 'building-store'
41
+ end
42
+
43
+ def customizable?
44
+ true
45
+ end
46
+
47
+ def page_builder_url
48
+ return unless page_builder_url_exists?(:brands_path)
49
+
50
+ Spree::Core::Engine.routes.url_helpers.brands_path
51
+ end
52
+
53
+ def default_sections
54
+ [
55
+ Spree::PageSections::PageTitle.new(
56
+ preferred_heading: Spree.t(:brands)
57
+ ),
58
+ Spree::PageSections::BrandGrid.new
59
+ ]
60
+ end
61
+ end
62
+ end
63
+ end
64
+ ```
65
+
66
+ ### Brand Page
67
+
68
+ Create a page type for individual brand pages:
69
+
70
+ ```ruby app/models/spree/pages/brand.rb
71
+ module Spree
72
+ module Pages
73
+ class Brand < Spree::Page
74
+ def icon_name
75
+ 'tag'
76
+ end
77
+
78
+ def customizable?
79
+ true
80
+ end
81
+
82
+ def page_builder_url
83
+ return unless page_builder_url_exists?(:brands_path)
84
+
85
+ brand = Spree::Brand.first
86
+ return unless brand
87
+
88
+ Spree::Core::Engine.routes.url_helpers.brand_path(brand)
89
+ end
90
+
91
+ def default_sections
92
+ [
93
+ Spree::PageSections::BrandBanner.new,
94
+ Spree::PageSections::ProductGrid.new(
95
+ preferred_heading: Spree.t(:products)
96
+ )
97
+ ]
98
+ end
99
+ end
100
+ end
101
+ end
102
+ ```
103
+
104
+ ## Step 2: Register Pages
105
+
106
+ Add your pages to the Spree configuration:
107
+
108
+ ```ruby config/initializers/spree.rb
109
+ Rails.application.config.after_initialize do
110
+ # Register custom pages
111
+ Spree.page_builder.pages += [
112
+ Spree::Pages::BrandList,
113
+ Spree::Pages::Brand
114
+ ]
115
+ end
116
+ ```
117
+
118
+ ## Step 3: Create Custom Sections
119
+
120
+ ### Brand Grid Section
121
+
122
+ This section displays a grid of all brands:
123
+
124
+ ```ruby app/models/spree/page_sections/brand_grid.rb
125
+ module Spree
126
+ module PageSections
127
+ class BrandGrid < Spree::PageSection
128
+ TOP_PADDING_DEFAULT = 40
129
+ BOTTOM_PADDING_DEFAULT = 40
130
+
131
+ preference :show_description, :boolean, default: false
132
+
133
+ def icon_name
134
+ 'layout-grid'
135
+ end
136
+
137
+ # Content sections can be added/removed in Page Builder
138
+ def self.role
139
+ 'content'
140
+ end
141
+
142
+ def brands
143
+ Spree::Brand.order(:name)
144
+ end
145
+ end
146
+ end
147
+ end
148
+ ```
149
+
150
+ ### Brand Banner Section
151
+
152
+ This section displays the brand header with logo and description:
153
+
154
+ ```ruby app/models/spree/page_sections/brand_banner.rb
155
+ module Spree
156
+ module PageSections
157
+ class BrandBanner < Spree::PageSection
158
+ TOP_PADDING_DEFAULT = 60
159
+ BOTTOM_PADDING_DEFAULT = 40
160
+
161
+ preference :show_logo, :boolean, default: true
162
+ preference :show_description, :boolean, default: true
163
+ preference :layout, :string, default: 'horizontal'
164
+
165
+ before_validation :ensure_valid_layout
166
+
167
+ def icon_name
168
+ 'id-badge'
169
+ end
170
+
171
+ # System sections are part of the core page functionality
172
+ def self.role
173
+ 'system'
174
+ end
175
+
176
+ def can_be_deleted?
177
+ false
178
+ end
179
+
180
+ private
181
+
182
+ def ensure_valid_layout
183
+ self.preferred_layout = 'horizontal' unless %w[horizontal vertical].include?(preferred_layout)
184
+ end
185
+ end
186
+ end
187
+ end
188
+ ```
189
+
190
+ ## Step 4: Register Sections
191
+
192
+ Add your sections to the configuration:
193
+
194
+ ```ruby config/initializers/spree.rb
195
+ Rails.application.config.after_initialize do
196
+ # Register custom pages
197
+ Spree.page_builder.pages += [
198
+ Spree::Pages::BrandList,
199
+ Spree::Pages::Brand
200
+ ]
201
+
202
+ # Register custom sections
203
+ Spree.page_builder.page_sections += [
204
+ Spree::PageSections::BrandGrid,
205
+ Spree::PageSections::BrandBanner
206
+ ]
207
+ end
208
+ ```
209
+
210
+ ## Step 5: Create Admin Forms
211
+
212
+ Admin section forms use Spree's Admin Form Builder, which provides helper methods like `spree_select` and `spree_check_box` for consistent styling and functionality.
213
+
214
+ ### Brand Grid Admin Form
215
+
216
+ ```erb app/views/spree/admin/page_sections/forms/_brand_grid.html.erb
217
+ <%= f.spree_check_box :preferred_show_description,
218
+ label: Spree.t(:show_description),
219
+ data: { action: 'auto-submit#submit' } %>
220
+ ```
221
+
222
+ ### Brand Banner Admin Form
223
+
224
+ ```erb app/views/spree/admin/page_sections/forms/_brand_banner.html.erb
225
+ <%= f.spree_check_box :preferred_show_logo,
226
+ label: Spree.t(:show_logo),
227
+ data: { action: 'auto-submit#submit' } %>
228
+
229
+ <%= f.spree_check_box :preferred_show_description,
230
+ label: Spree.t(:show_description),
231
+ data: { action: 'auto-submit#submit' } %>
232
+
233
+ <% content_for(:design_tab) do %>
234
+ <%= f.spree_select :preferred_layout,
235
+ options_for_select([
236
+ [Spree.t(:horizontal), 'horizontal'],
237
+ [Spree.t(:vertical), 'vertical']
238
+ ], @page_section.preferred_layout),
239
+ { label: Spree.t(:layout) },
240
+ { data: { action: 'auto-submit#submit' } } %>
241
+ <hr />
242
+ <% end %>
243
+ ```
244
+
245
+ ## Step 6: Create Storefront Views
246
+
247
+ ### Brand Grid Section View
248
+
249
+ ```erb app/views/themes/default/spree/page_sections/_brand_grid.html.erb
250
+ <% cache_unless page_builder_enabled?, spree_storefront_base_cache_scope.call(section) do %>
251
+ <div style="<%= section_styles(section) %>">
252
+ <div class="page-container">
253
+ <% brands = section.brands %>
254
+ <% if brands.any? %>
255
+ <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
256
+ <% brands.each do |brand| %>
257
+ <%= link_to spree.brand_path(brand),
258
+ class: 'block group',
259
+ data: { turbo_frame: '_top' } do %>
260
+ <div class="aspect-square bg-accent rounded-lg overflow-hidden mb-3">
261
+ <% if brand.logo.attached? %>
262
+ <%= spree_image_tag brand.logo,
263
+ width: 300,
264
+ height: 300,
265
+ class: 'w-full h-full object-contain p-6 group-hover:scale-105 transition-transform',
266
+ alt: brand.name %>
267
+ <% else %>
268
+ <div class="w-full h-full flex items-center justify-center">
269
+ <span class="text-4xl font-medium text-neutral-400">
270
+ <%= brand.name.first.upcase %>
271
+ </span>
272
+ </div>
273
+ <% end %>
274
+ </div>
275
+ <h3 class="font-medium group-hover:text-primary transition-colors">
276
+ <%= brand.name %>
277
+ </h3>
278
+ <% if section.preferred_show_description && brand.description.present? %>
279
+ <p class="mt-1 text-sm text-neutral-600 line-clamp-2">
280
+ <%= brand.description.to_plain_text.truncate(100) %>
281
+ </p>
282
+ <% end %>
283
+ <% end %>
284
+ <% end %>
285
+ </div>
286
+ <% else %>
287
+ <p class="text-neutral-600"><%= Spree.t(:no_brands_found) %></p>
288
+ <% end %>
289
+ </div>
290
+ </div>
291
+ <% end %>
292
+ ```
293
+
294
+ ### Brand Banner Section View
295
+
296
+ ```erb app/views/themes/default/spree/page_sections/_brand_banner.html.erb
297
+ <% cache_unless page_builder_enabled?, spree_storefront_base_cache_scope.call(section) do %>
298
+ <div style="<%= section_styles(section) %>">
299
+ <div class="page-container">
300
+ <% if brand.present? %>
301
+ <div class="<%= section.preferred_layout == 'horizontal' ? 'flex flex-col md:flex-row gap-8 items-start' : 'text-center' %>">
302
+ <% if section.preferred_show_logo && brand.logo.attached? %>
303
+ <div class="<%= section.preferred_layout == 'horizontal' ? 'w-32 h-32 flex-shrink-0' : 'w-40 h-40 mx-auto mb-6' %> bg-accent rounded-lg">
304
+ <%= spree_image_tag brand.logo,
305
+ width: 160,
306
+ height: 160,
307
+ class: 'w-full h-full object-contain p-4',
308
+ alt: brand.name %>
309
+ </div>
310
+ <% end %>
311
+
312
+ <div>
313
+ <h1 class="text-2xl lg:text-3xl font-medium mb-4">
314
+ <%= brand.name %>
315
+ </h1>
316
+
317
+ <% if section.preferred_show_description && brand.description.present? %>
318
+ <div class="prose max-w-none text-neutral-600">
319
+ <%= brand.description %>
320
+ </div>
321
+ <% end %>
322
+ </div>
323
+ </div>
324
+ <% end %>
325
+ </div>
326
+ </div>
327
+ <% end %>
328
+ ```
329
+
330
+ ## Step 7: Update the Controller
331
+
332
+ Update your controller to use Page Builder pages:
333
+
334
+ ```ruby app/controllers/spree/brands_controller.rb
335
+ module Spree
336
+ class BrandsController < StoreController
337
+ before_action :load_brand, only: [:show]
338
+
339
+ def index
340
+ # Load the Page Builder page
341
+ @current_page = current_theme.pages.find_by(type: 'Spree::Pages::BrandList')
342
+
343
+ # Fallback data if sections need it
344
+ @brands = Spree::Brand.order(:name)
345
+ end
346
+
347
+ def show
348
+ # Load the Page Builder page
349
+ @current_page = current_theme.pages.find_by(type: 'Spree::Pages::Brand')
350
+
351
+ # Load products for the ProductGrid section
352
+ @products = @brand.products
353
+ .active(current_currency)
354
+ .includes(storefront_products_includes)
355
+ .page(params[:page])
356
+ .per(12)
357
+ end
358
+
359
+ private
360
+
361
+ def load_brand
362
+ @brand = Spree::Brand.find(params[:id])
363
+ end
364
+
365
+ def accurate_title
366
+ if @brand
367
+ @brand.meta_title.presence || @brand.name
368
+ else
369
+ Spree.t(:brands)
370
+ end
371
+ end
372
+ end
373
+ end
374
+ ```
375
+
376
+ ## Step 8: Update Views to Use Page Builder
377
+
378
+ ### Brand List Index View
379
+
380
+ ```erb app/views/themes/default/spree/brands/index.html.erb
381
+ <%= render_page(@current_page, brands: @brands) %>
382
+ ```
383
+
384
+ ### Brand Show View
385
+
386
+ ```erb app/views/themes/default/spree/brands/show.html.erb
387
+ <%= render_page(@current_page, brand: @brand, products: @products) %>
388
+ ```
389
+
390
+ The `render_page` helper automatically renders all sections in the order defined in Page Builder.
391
+
392
+ ## Step 9: Passing Variables to Sections
393
+
394
+ Section views receive variables passed to `render_page`. Update your section views to use them:
395
+
396
+ ```erb app/views/themes/default/spree/page_sections/_brand_banner.html.erb
397
+ <% # 'brand' variable is passed from the controller via render_page %>
398
+ <% cache_unless page_builder_enabled?, [spree_storefront_base_cache_scope.call(section), brand] do %>
399
+ <div style="<%= section_styles(section) %>">
400
+ <%# ... use 'brand' variable ... %>
401
+ </div>
402
+ <% end %>
403
+ ```
404
+
405
+ ## Step 10: Add Translations
406
+
407
+ ```yaml config/locales/en.yml
408
+ en:
409
+ spree:
410
+ brands: Brands
411
+ no_brands_found: No brands found.
412
+ products_by_brand: "Products by %{brand}"
413
+ show_description: Show description
414
+ show_logo: Show logo
415
+ layout: Layout
416
+ horizontal: Horizontal
417
+ vertical: Vertical
418
+ ```
419
+
420
+ ## Testing Page Builder Integration
421
+
422
+ 1. Start your Rails server
423
+ 2. Go to **Admin → Storefront → Pages**
424
+ 3. You should see "Brand List" and "Brand" pages
425
+ 4. Click on a page to customize it in Page Builder
426
+ 5. Add, remove, or reorder sections
427
+ 6. Customize section settings
428
+ 7. Preview changes in real-time
429
+
430
+ ## Section Roles Explained
431
+
432
+ | Role | Description | Can Delete? | Example |
433
+ |------|-------------|-------------|---------|
434
+ | `content` | General content sections | Yes | BrandGrid, ImageBanner |
435
+ | `system` | Core page functionality | No | BrandBanner, ProductDetails |
436
+ | `header` | Layout header sections | No | Header, AnnouncementBar |
437
+ | `footer` | Layout footer sections | No | Footer, Newsletter |
438
+
439
+ ## Complete File Structure
440
+
441
+ After completing this tutorial, you should have:
442
+
443
+ ```
444
+ app/
445
+ ├── controllers/spree/
446
+ │ └── brands_controller.rb
447
+ ├── models/spree/
448
+ │ ├── pages/
449
+ │ │ ├── brand.rb
450
+ │ │ └── brand_list.rb
451
+ │ └── page_sections/
452
+ │ ├── brand_banner.rb
453
+ │ └── brand_grid.rb
454
+ └── views/
455
+ ├── spree/admin/page_sections/forms/
456
+ │ ├── _brand_banner.html.erb
457
+ │ └── _brand_grid.html.erb
458
+ └── themes/default/spree/
459
+ ├── brands/
460
+ │ ├── index.html.erb
461
+ │ └── show.html.erb
462
+ └── page_sections/
463
+ ├── _brand_banner.html.erb
464
+ └── _brand_grid.html.erb
465
+
466
+ config/
467
+ ├── initializers/
468
+ │ └── spree.rb (updated)
469
+ └── locales/
470
+ └── en.yml (updated)
471
+ ```
472
+
473
+ ## Benefits of Page Builder Integration
474
+
475
+ | Without Page Builder | With Page Builder |
476
+ |---------------------|-------------------|
477
+ | Developers edit views for layout changes | Admins customize layouts in browser |
478
+ | Code deployment required for design changes | Real-time preview and publish |
479
+ | Fixed page structure | Drag-and-drop section ordering |
480
+ | Hardcoded settings | Admin-configurable preferences |
481
+
482
+ ## Related Documentation
483
+
484
+ - [Sections](/developer/storefront/sections) - Creating custom sections
485
+ - [Blocks](/developer/storefront/blocks) - Adding blocks to sections
486
+ - [Pages](/developer/storefront/pages) - Page types and routing
487
+ - [Themes](/developer/storefront/themes) - Theme customization