@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,352 @@
1
+ ---
2
+ title: Storefront
3
+ description: Learn how to create storefront pages for your Brands feature
4
+ ---
5
+
6
+ In this tutorial, we'll create storefront pages to display brands to your customers. We'll start with a simple Rails approach using controllers and views, then in the next guide we'll connect it to Page Builder.
7
+
8
+ > **INFO:** This guide assumes you've completed the [Model](/developer/tutorial/model), [Admin](/developer/tutorial/admin), [Rich Text](/developer/tutorial/rich-text), [File Uploads](/developer/tutorial/file-uploads), and [Extending Core Models](/developer/tutorial/extending-models) tutorials. You should have a working `Spree::Brand` model with products associated to brands.
9
+
10
+ ## What We're Building
11
+
12
+ By the end of this tutorial, you'll have:
13
+
14
+ - A custom theme for your store
15
+ - A brands listing page at `/brands`
16
+ - Individual brand pages at `/brands/:id`
17
+ - Styled views using Tailwind CSS
18
+
19
+ ## Step 1: Create a Custom Theme
20
+
21
+ Before adding custom views, create your own theme. This is important because:
22
+
23
+ - **Upgrade safety** - Your customizations won't be overwritten when updating Spree
24
+ - **Clean separation** - Your code stays separate from Spree's default theme
25
+ - **Full control** - You get a complete copy of all templates to customize
26
+
27
+ Run the theme generator:
28
+
29
+ ```bash
30
+ bin/rails g spree:storefront:theme MyStore
31
+ ```
32
+
33
+ This creates:
34
+ - `app/views/themes/my_store/` - Copy of all storefront templates
35
+ - `app/models/spree/themes/my_store.rb` - Theme configuration class
36
+
37
+ The generator also updates your `config/initializers/spree.rb`:
38
+
39
+ ```ruby config/initializers/spree.rb
40
+ Spree.page_builder.themes << Spree::Themes::MyStore
41
+ ```
42
+
43
+ ### Activate Your Theme
44
+
45
+ 1. Go to **Admin → Storefront → Themes**
46
+ 2. Find your new theme in the "Add new theme" section
47
+ 3. Click **Add** to activate it
48
+
49
+ > **WARNING:** Always create a custom theme for production stores. Never modify the default theme directly - your changes will be lost during Spree upgrades.
50
+
51
+ ## Step 2: Add Routes
52
+
53
+ Now let's add routes for our brand pages. Create or update your routes file:
54
+
55
+ ```ruby config/routes.rb
56
+ Spree::Core::Engine.add_routes do
57
+ scope '(:locale)', locale: /#{Spree.available_locales.join('|')}/, defaults: { locale: nil } do
58
+ resources :brands, only: [:index, :show]
59
+ end
60
+ end
61
+ ```
62
+
63
+ > **INFO:** The `scope '(:locale)'` wrapper enables internationalization - URLs like `/fr/brands` will work automatically if you have French locale enabled.
64
+
65
+ ## Step 3: Create the Controller
66
+
67
+ Create a controller that inherits from `Spree::StoreController`. This base controller provides:
68
+
69
+ - Access to `current_store`, `current_theme`, `current_currency`
70
+ - User authentication helpers
71
+ - Storefront layout and helpers
72
+ - SEO and meta tag support
73
+
74
+ ```ruby app/controllers/spree/brands_controller.rb
75
+ module Spree
76
+ class BrandsController < StoreController
77
+ before_action :load_brand, only: [:show]
78
+
79
+ def index
80
+ @brands = Spree::Brand.order(:name)
81
+ end
82
+
83
+ def show
84
+ @products = @brand.products.active(current_currency).includes(storefront_products_includes)
85
+ end
86
+
87
+ private
88
+
89
+ def load_brand
90
+ @brand = Spree::Brand.find(params[:id])
91
+ end
92
+
93
+ # Override to set page title for SEO
94
+ def accurate_title
95
+ if @brand
96
+ @brand.name
97
+ else
98
+ Spree.t(:brands)
99
+ end
100
+ end
101
+ end
102
+ end
103
+ ```
104
+
105
+ ### Key Points
106
+
107
+ - **Inherit from `Spree::StoreController`** - Not `ApplicationController`. This gives you access to all storefront functionality.
108
+ - **Use `current_store`** - Always scope queries to the current store for multi-store support.
109
+ - **Override `accurate_title`** - This sets the page `<title>` tag.
110
+
111
+ > **TIP:** Want SEO-friendly URLs like `/brands/nike` instead of `/brands/123`? See the [SEO](/developer/tutorial/seo) tutorial to add slug support.
112
+
113
+ ## Step 4: Create the Views
114
+
115
+ Storefront views live in your theme directory. Create the brands views in your custom theme:
116
+
117
+ ```bash
118
+ mkdir -p app/views/themes/my_store/spree/brands
119
+ ```
120
+
121
+ Your theme's view structure:
122
+
123
+ ```
124
+ app/views/themes/my_store/spree/brands/
125
+ ├── index.html.erb
126
+ ├── show.html.erb
127
+ └── _brand_card.html.erb
128
+ ```
129
+
130
+ ### Brands Listing Page
131
+
132
+ ```erb app/views/themes/my_store/spree/brands/index.html.erb
133
+ <div class="page-container py-8">
134
+ <h1 class="text-2xl lg:text-3xl font-medium mb-8">
135
+ <%= Spree.t(:brands) %>
136
+ </h1>
137
+
138
+ <% if @brands.any? %>
139
+ <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
140
+ <% @brands.each do |brand| %>
141
+ <%= render 'brand_card', brand: brand %>
142
+ <% end %>
143
+ </div>
144
+ <% else %>
145
+ <p class="text-neutral-600">
146
+ <%= Spree.t(:no_brands_found) %>
147
+ </p>
148
+ <% end %>
149
+ </div>
150
+ ```
151
+
152
+ ### Brand Card Partial
153
+
154
+ ```erb app/views/themes/my_store/spree/brands/_brand_card.html.erb
155
+ <%= link_to spree.brand_path(brand),
156
+ class: 'block group',
157
+ data: { turbo_frame: '_top' } do %>
158
+ <div class="aspect-square bg-accent rounded-lg overflow-hidden mb-3">
159
+ <% if brand.logo.attached? %>
160
+ <%= spree_image_tag brand.logo,
161
+ width: 300,
162
+ height: 300,
163
+ class: 'w-full h-full object-contain p-6 group-hover:scale-105 transition-transform',
164
+ alt: brand.name %>
165
+ <% else %>
166
+ <div class="w-full h-full flex items-center justify-center">
167
+ <span class="text-4xl font-medium text-neutral-400">
168
+ <%= brand.name.first.upcase %>
169
+ </span>
170
+ </div>
171
+ <% end %>
172
+ </div>
173
+ <h2 class="font-medium group-hover:text-primary transition-colors">
174
+ <%= brand.name %>
175
+ </h2>
176
+ <% end %>
177
+ ```
178
+
179
+ ### Single Brand Page
180
+
181
+ ```erb app/views/themes/my_store/spree/brands/show.html.erb
182
+ <div class="page-container py-8">
183
+ <%# Brand Header %>
184
+ <div class="flex flex-col md:flex-row gap-8 mb-12">
185
+ <% if @brand.logo.attached? %>
186
+ <div class="w-32 h-32 bg-accent rounded-lg flex-shrink-0">
187
+ <%= spree_image_tag @brand.logo,
188
+ width: 128,
189
+ height: 128,
190
+ class: 'w-full h-full object-contain p-4',
191
+ alt: @brand.name %>
192
+ </div>
193
+ <% end %>
194
+
195
+ <div>
196
+ <h1 class="text-2xl lg:text-3xl font-medium mb-4">
197
+ <%= @brand.name %>
198
+ </h1>
199
+
200
+ <% if @brand.description.present? %>
201
+ <div class="prose max-w-none text-neutral-600">
202
+ <%= @brand.description %>
203
+ </div>
204
+ <% end %>
205
+ </div>
206
+ </div>
207
+
208
+ <%# Products Grid %>
209
+ <% if @products.any? %>
210
+ <h2 class="text-xl font-medium mb-6">
211
+ <%= Spree.t(:products_by_brand, brand: @brand.name) %>
212
+ </h2>
213
+
214
+ <div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-6">
215
+ <%= render 'spree/shared/products', products: @products %>
216
+ </div>
217
+ <% else %>
218
+ <p class="text-neutral-600">
219
+ <%= Spree.t(:no_products_found) %>
220
+ </p>
221
+ <% end %>
222
+ </div>
223
+ ```
224
+
225
+ ## Step 5: Add Translations
226
+
227
+ Add the necessary translations:
228
+
229
+ ```yaml config/locales/en.yml
230
+ en:
231
+ spree:
232
+ brands: Brands
233
+ no_brands_found: No brands found.
234
+ products_by_brand: "Products by %{brand}"
235
+ ```
236
+
237
+ ## Step 6: Add Navigation Link (Optional)
238
+
239
+ To add a link to brands in your header navigation, you can use the Admin Dashboard:
240
+
241
+ 1. Go to **Storefront → Theme Editor**
242
+ 2. Click on **Header** section
243
+ 3. Add a new navigation link pointing to `/brands`
244
+
245
+ Or programmatically in your header partial:
246
+
247
+ ```erb
248
+ <%= link_to Spree.t(:brands), spree.brands_path, class: 'nav-link' %>
249
+ ```
250
+
251
+ ## Understanding the View Structure
252
+
253
+ ### Theme Directory
254
+
255
+ Views are organized by theme in `app/views/themes/{theme_name}/spree/`:
256
+
257
+ ```
258
+ app/views/themes/my_store/spree/
259
+ ├── brands/ # Your brand views
260
+ ├── products/ # Product views
261
+ ├── shared/ # Shared partials
262
+ └── page_sections/ # Page Builder sections
263
+ ```
264
+
265
+ > **INFO:** Spree looks for views in your active theme first. If a view isn't found, it falls back to the default theme. This means you only need to copy and customize the files you want to change.
266
+
267
+ ### Key CSS Classes
268
+
269
+ Spree's default theme uses these common patterns:
270
+
271
+ | Class | Purpose |
272
+ |-------|---------|
273
+ | `page-container` | Centered container with max-width and padding |
274
+ | `bg-accent` | Uses theme's accent background color |
275
+ | `text-primary` | Uses theme's primary text color |
276
+ | `btn-primary` | Primary button style |
277
+ | `btn-secondary` | Secondary button style |
278
+
279
+ ### Using Spree Helpers
280
+
281
+ ```erb
282
+ <%# Image helper with automatic optimization %>
283
+ <%= spree_image_tag image, width: 400, height: 400 %>
284
+
285
+ <%# URL helpers %>
286
+ <%= spree.brands_path %>
287
+ <%= spree.brand_path(brand) %>
288
+
289
+ <%# Translation helper %>
290
+ <%= Spree.t(:brands) %>
291
+
292
+ <%# Price display %>
293
+ <%= display_price(product.price_in(current_currency)) %>
294
+ ```
295
+
296
+ ## Testing Your Pages
297
+
298
+ Start your Rails server and visit:
299
+
300
+ - `http://localhost:3000/brands` - Brand listing
301
+ - `http://localhost:3000/brands/1` - Single brand (using the brand's ID)
302
+
303
+ > **TIP:** Want SEO-friendly URLs like `/brands/nike` instead of `/brands/1`? See the [SEO](/developer/tutorial/seo) tutorial to add slug support, meta tags, and Open Graph data.
304
+
305
+ ## What's Next?
306
+
307
+ You now have working brand pages using standard Rails MVC patterns. In the next guide, [Testing](/developer/tutorial/testing), we'll write automated tests for your feature to make sure it works as expected, also in the future when you make changes to your code.
308
+
309
+ ## Complete Controller Example
310
+
311
+ Here's the complete controller with all features:
312
+
313
+ ```ruby app/controllers/spree/brands_controller.rb
314
+ module Spree
315
+ class BrandsController < StoreController
316
+ before_action :load_brand, only: [:show]
317
+
318
+ def index
319
+ @brands = Spree::Brand.order(:name)
320
+ .page(params[:page])
321
+ .per(24)
322
+ end
323
+
324
+ def show
325
+ @products = @brand.products.active(current_currency).includes(storefront_products_includes)
326
+ @page_description = @brand.description&.to_plain_text&.truncate(160)
327
+ end
328
+
329
+ private
330
+
331
+ def load_brand
332
+ @brand = Spree::Brand.find(params[:id])
333
+ end
334
+
335
+ def accurate_title
336
+ if @brand
337
+ @brand.name
338
+ else
339
+ Spree.t(:brands)
340
+ end
341
+ end
342
+ end
343
+ end
344
+ ```
345
+
346
+ > **INFO:** To use SEO-friendly slugs like `/brands/nike` instead of `/brands/1`, follow the [SEO](/developer/tutorial/seo) tutorial.
347
+
348
+ ## Related Documentation
349
+
350
+ - [Storefront Overview](/developer/storefront/storefront) - Storefront architecture
351
+ - [Custom CSS](/developer/storefront/custom-css) - Styling with Tailwind
352
+ - [Helper Methods](/developer/storefront/helper-methods) - Available helpers