@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,298 @@
1
+ ---
2
+ title: "Links"
3
+ sidebarTitle: "Links"
4
+ description: "Learn how to use links for navigation in your Spree Storefront"
5
+ ---
6
+
7
+ Links are used to create navigation throughout the storefront. They can be assigned to [sections](/developer/storefront/sections) and [blocks](/developer/storefront/blocks), enabling users to navigate to different pages, products, categories, or external URLs.
8
+
9
+ ## How Links Work
10
+
11
+ The `Spree::PageLink` model provides a flexible way to link to various content types:
12
+
13
+ - **Internal pages** - Link to Pages, Products, Taxons, Posts
14
+ - **External URLs** - Link to any external website
15
+ - **Special links** - Email (`mailto:`) and phone (`tel:`) links
16
+
17
+ Links are managed through the Page Builder interface, where store staff can select what each link points to.
18
+
19
+ ## Link Model
20
+
21
+ The [Spree::PageLink](https://github.com/spree/spree/blob/main/core/app/models/spree/page_link.rb) model has these key attributes:
22
+
23
+ | Attribute | Type | Description |
24
+ |-----------|------|-------------|
25
+ | `label` | String | Display text for the link |
26
+ | `url` | String | Custom URL (for external links) |
27
+ | `linkable` | Polymorphic | Reference to internal content (Page, Product, etc.) |
28
+ | `parent` | Polymorphic | Section or Block the link belongs to |
29
+ | `open_in_new_tab` | Boolean | Whether to open in new browser tab |
30
+ | `position` | Integer | Order when multiple links exist |
31
+
32
+ ## Linkable Types
33
+
34
+ Links can point to various Spree models:
35
+
36
+ | Linkable Type | Description |
37
+ |---------------|-------------|
38
+ | `Spree::Page` | Internal pages (Home, Shop All, Custom pages) |
39
+ | `Spree::Product` | Product detail pages |
40
+ | `Spree::Taxon` | Category/collection pages |
41
+ | `Spree::Post` | Blog posts |
42
+ | Custom URL | Any external or internal URL |
43
+
44
+ ## Using Links in Sections
45
+
46
+ ### Single Link
47
+
48
+ For sections that need one link (like a banner):
49
+
50
+ ```ruby app/models/spree/page_sections/promo_banner.rb
51
+ module Spree
52
+ module PageSections
53
+ class PromoBanner < Spree::PageSection
54
+ has_one :link, ->(ps) { ps.links },
55
+ class_name: 'Spree::PageLink',
56
+ as: :parent,
57
+ dependent: :destroy,
58
+ inverse_of: :parent
59
+ accepts_nested_attributes_for :link
60
+
61
+ def default_links
62
+ @default_links.presence || [
63
+ Spree::PageLink.new(label: Spree.t(:shop_now))
64
+ ]
65
+ end
66
+ end
67
+ end
68
+ end
69
+ ```
70
+
71
+ ### Multiple Links
72
+
73
+ For sections that need multiple links (like navigation):
74
+
75
+ ```ruby app/models/spree/page_sections/footer.rb
76
+ module Spree
77
+ module PageSections
78
+ class Footer < Spree::PageSection
79
+ # Links are provided by Spree::HasPageLinks concern
80
+ # which is included in Spree::PageSection by default
81
+
82
+ def default_links
83
+ @default_links.presence || [
84
+ Spree::PageLink.new(label: 'About Us'),
85
+ Spree::PageLink.new(label: 'Contact'),
86
+ Spree::PageLink.new(label: 'Privacy Policy')
87
+ ]
88
+ end
89
+ end
90
+ end
91
+ end
92
+ ```
93
+
94
+ ## Using Links in Blocks
95
+
96
+ Blocks can also have links. Use the `Spree::HasOneLink` concern for single links:
97
+
98
+ ```ruby app/models/spree/page_blocks/cta_button.rb
99
+ module Spree
100
+ module PageBlocks
101
+ class CtaButton < Spree::PageBlock
102
+ include Spree::HasOneLink
103
+
104
+ preference :button_style, :string, default: 'primary'
105
+
106
+ # Called when the link is deleted
107
+ def link_destroyed(_link)
108
+ destroy if page_links_count.zero?
109
+ end
110
+ end
111
+ end
112
+ end
113
+ ```
114
+
115
+ ## Accessing Links
116
+
117
+ ```ruby
118
+ # Single link on a section
119
+ section.link
120
+ section.link.label
121
+ section.link.linkable_url
122
+
123
+ # Multiple links on a section
124
+ section.links
125
+ section.links.each do |link|
126
+ link.label
127
+ link.linkable_url
128
+ end
129
+
130
+ # Link on a block
131
+ block.link
132
+ block.link.label if block.link.present?
133
+ ```
134
+
135
+ ## Rendering Links
136
+
137
+ ### Using the Helper
138
+
139
+ The `page_builder_link_to` helper renders links with Page Builder support:
140
+
141
+ ```erb
142
+ <%# Basic usage %>
143
+ <%= page_builder_link_to section.link %>
144
+
145
+ <%# With custom label %>
146
+ <%= page_builder_link_to section.link, label: 'Click Here' %>
147
+
148
+ <%# With CSS class %>
149
+ <%= page_builder_link_to section.link, class: 'btn-primary' %>
150
+
151
+ <%# Open in new tab %>
152
+ <%= page_builder_link_to section.link,
153
+ target: (section.link.open_in_new_tab ? '_blank' : nil),
154
+ rel: (section.link.open_in_new_tab ? 'noopener noreferrer' : nil) %>
155
+
156
+ <%# With block content %>
157
+ <%= page_builder_link_to section.link do %>
158
+ <span class="icon">→</span>
159
+ <%= section.link.label %>
160
+ <% end %>
161
+ ```
162
+
163
+ ### Manual Link Rendering
164
+
165
+ For more control, you can render links manually:
166
+
167
+ ```erb
168
+ <% if section.link.present? %>
169
+ <%= link_to section.link.linkable_url,
170
+ target: (section.link.open_in_new_tab ? '_blank' : nil),
171
+ rel: (section.link.open_in_new_tab ? 'noopener noreferrer' : nil),
172
+ class: 'btn-primary' do %>
173
+ <%= section.link.label %>
174
+ <% end %>
175
+ <% end %>
176
+ ```
177
+
178
+ ### Rendering Multiple Links
179
+
180
+ ```erb
181
+ <nav class="footer-links">
182
+ <% section.links.each do |link| %>
183
+ <%= page_builder_link_to link, class: 'footer-link' %>
184
+ <% end %>
185
+ </nav>
186
+ ```
187
+
188
+ ## Admin Form for Links
189
+
190
+ In your section's admin form, render the link editor:
191
+
192
+ ### Single Link
193
+
194
+ ```erb app/views/spree/admin/page_sections/forms/_promo_banner.html.erb
195
+ <%= render 'spree/admin/shared/page_section_image', f: f %>
196
+
197
+ <div class="py-2">
198
+ <%= f.fields_for :link do |lf| %>
199
+ <div class="form-group">
200
+ <%= lf.label :linkable_type, Spree.t(:link) %>
201
+ <%= lf.select :linkable_type,
202
+ @page_section.allowed_linkable_types,
203
+ { include_blank: false },
204
+ { class: 'custom-select mb-3', data: { action: 'auto-submit#submit' } } %>
205
+
206
+ <div id="linkable_type_dropdown">
207
+ <%= render 'spree/admin/page_links/linkable_type_dropdown',
208
+ page_link: lf.object,
209
+ form_name: 'page_section[link_attributes]' %>
210
+ </div>
211
+ </div>
212
+
213
+ <div class="custom-control custom-checkbox">
214
+ <%= lf.check_box :open_in_new_tab,
215
+ class: 'custom-control-input',
216
+ data: { action: 'auto-submit#submit' } %>
217
+ <%= lf.label :open_in_new_tab, class: 'custom-control-label' %>
218
+ </div>
219
+ <% end %>
220
+ </div>
221
+ ```
222
+
223
+ ## Link URL Resolution
224
+
225
+ The `linkable_url` method returns the appropriate URL:
226
+
227
+ ```ruby
228
+ link = Spree::PageLink.new(linkable: product)
229
+ link.linkable_url
230
+ # => "/products/red-shirt"
231
+
232
+ link = Spree::PageLink.new(url: "https://example.com")
233
+ link.linkable_url
234
+ # => "https://example.com"
235
+
236
+ link = Spree::PageLink.new(url: "example.com")
237
+ link.formatted_url
238
+ # => "http://example.com" # Adds protocol automatically
239
+
240
+ link = Spree::PageLink.new(url: "mailto:info@example.com")
241
+ link.formatted_url
242
+ # => "mailto:info@example.com" # Preserves mailto: protocol
243
+ ```
244
+
245
+ ## Creating Links Programmatically
246
+
247
+ ```ruby
248
+ # Link to an internal page
249
+ link = Spree::PageLink.create!(
250
+ parent: section,
251
+ label: 'Shop Now',
252
+ linkable: store.pages.find_by(type: 'Spree::Pages::ShopAll')
253
+ )
254
+
255
+ # Link to a product
256
+ link = Spree::PageLink.create!(
257
+ parent: section,
258
+ label: product.name,
259
+ linkable: product
260
+ )
261
+
262
+ # Link to a taxon
263
+ link = Spree::PageLink.create!(
264
+ parent: section,
265
+ label: 'New Arrivals',
266
+ linkable: store.taxons.find_by(name: 'New Arrivals')
267
+ )
268
+
269
+ # External link
270
+ link = Spree::PageLink.create!(
271
+ parent: section,
272
+ label: 'Visit Our Blog',
273
+ url: 'https://blog.example.com',
274
+ open_in_new_tab: true
275
+ )
276
+ ```
277
+
278
+ ## Automatic Label Setting
279
+
280
+ When a link's `linkable` is set, the label is automatically populated from the linked resource:
281
+
282
+ ```ruby
283
+ link = Spree::PageLink.new(linkable: product)
284
+ link.valid?
285
+ link.label
286
+ # => "Red T-Shirt" (from product.name)
287
+ ```
288
+
289
+ The label is derived from (in order):
290
+ 1. `linkable.title`
291
+ 2. `linkable.display_name`
292
+ 3. `linkable.name`
293
+
294
+ ## Related Documentation
295
+
296
+ - [Sections](/developer/storefront/sections) - Adding links to sections
297
+ - [Blocks](/developer/storefront/blocks) - Adding links to blocks
298
+ - [Pages](/developer/storefront/pages) - Understanding internal page linking
@@ -0,0 +1,150 @@
1
+ ---
2
+ title: Architecture
3
+ description: Server-first architecture, project structure, and auth flow
4
+ ---
5
+
6
+ ## Server-First Pattern
7
+
8
+ The storefront follows a **server-first architecture** where all API calls are made server-side. The Spree API key is never exposed to the browser.
9
+
10
+ ```
11
+ Browser → Server Action → @spree/next → Spree API
12
+ (with httpOnly cookies)
13
+ ```
14
+
15
+ - **Server Actions** (`src/lib/data/`) — thin wrappers around `@spree/next` data functions
16
+ - **httpOnly Cookies** — auth tokens, cart tokens, and locale are stored securely
17
+ - **No Client-Side API Calls** — the Spree API key stays on the server
18
+ - **Auto-Localization** — locale and country are read from cookies automatically by `@spree/next`
19
+
20
+ ## Project Structure
21
+
22
+ ```
23
+ src/
24
+ ├── app/
25
+ │ └── [country]/[locale]/ # Localized routes
26
+ │ ├── (storefront)/ # Main storefront layout
27
+ │ │ ├── page.tsx # Homepage
28
+ │ │ ├── account/ # Customer account
29
+ │ │ │ ├── addresses/ # Address management
30
+ │ │ │ ├── credit-cards/ # Saved payment methods
31
+ │ │ │ ├── gift-cards/ # Gift cards
32
+ │ │ │ ├── orders/ # Order history
33
+ │ │ │ │ └── [id]/ # Order details
34
+ │ │ │ ├── profile/ # Profile settings
35
+ │ │ │ └── register/ # Registration
36
+ │ │ ├── cart/ # Shopping cart
37
+ │ │ ├── products/ # Product listing
38
+ │ │ │ └── [slug]/ # Product details
39
+ │ │ ├── t/[...permalink]/ # Category pages
40
+ │ │ └── categories/ # Category overview
41
+ │ └── (checkout)/ # Checkout layout (no header/footer)
42
+ │ ├── checkout/[id]/ # Checkout flow
43
+ │ └── order-placed/[id]/ # Order confirmation
44
+ ├── components/
45
+ │ ├── cart/ # CartDrawer
46
+ │ ├── checkout/ # AddressStep, DeliveryStep, PaymentStep, etc.
47
+ │ ├── layout/ # Header, Footer, CountrySwitcher
48
+ │ ├── navigation/ # Breadcrumbs
49
+ │ ├── products/ # ProductCard, ProductGrid, Filters, MediaGallery, VariantPicker
50
+ │ └── search/ # SearchBar
51
+ ├── contexts/
52
+ │ ├── AuthContext.tsx # Auth state
53
+ │ ├── CartContext.tsx # Client-side cart state sync
54
+ │ ├── CheckoutContext.tsx # Checkout flow state
55
+ │ └── StoreContext.tsx # Store/locale/currency state
56
+ ├── hooks/
57
+ │ ├── useCarouselProducts.ts # Product carousel data
58
+ │ └── useProductListing.ts # Product listing with filters
59
+ └── lib/
60
+ ├── analytics/ # GTM integration
61
+ ├── constants.ts # App constants
62
+ ├── data/ # Server Actions
63
+ │ ├── addresses.ts # Address CRUD
64
+ │ ├── cart.ts # Cart operations
65
+ │ ├── checkout.ts # Checkout flow
66
+ │ ├── cookies.ts # Auth check helper
67
+ │ ├── countries.ts # Countries/regions
68
+ │ ├── credit-cards.ts # Payment methods
69
+ │ ├── customer.ts # Auth & profile
70
+ │ ├── gift-cards.ts # Gift cards
71
+ │ ├── orders.ts # Order history
72
+ │ ├── payment.ts # Payment processing
73
+ │ ├── products.ts # Product queries
74
+ │ ├── store.ts # Store configuration
75
+ │ ├── categories.ts # Categories
76
+ │ └── utils.ts # Shared helpers (actionResult, withFallback)
77
+ └── utils/ # Client utilities
78
+ ├── address.ts # Address formatting
79
+ ├── cookies.ts # Cookie helpers
80
+ ├── credit-card.ts # Card formatting
81
+ ├── path.ts # URL path helpers
82
+ └── product-query.ts # Product filter query builder
83
+ ```
84
+
85
+ ## Authentication Flow
86
+
87
+ 1. User submits login form
88
+ 2. Server action calls `@spree/next` which authenticates with the Spree API
89
+ 3. JWT token is stored in an httpOnly cookie by `@spree/next`
90
+ 4. Subsequent requests include the token automatically
91
+ 5. Token is never accessible to client-side JavaScript
92
+
93
+ ```typescript
94
+ // src/lib/data/customer.ts
95
+ import { login as _login, getCustomer as _getCustomer } from '@spree/next'
96
+
97
+ export async function login(email: string, password: string) {
98
+ return _login(email, password) // token stored in httpOnly cookie automatically
99
+ }
100
+
101
+ export async function getCustomer() {
102
+ return _getCustomer() // reads token from cookie automatically
103
+ }
104
+ ```
105
+
106
+ ## Multi-Region Support
107
+
108
+ The storefront supports multiple countries and currencies via URL segments:
109
+
110
+ ```
111
+ /us/en/products # US store, English
112
+ /de/de/products # German store, German
113
+ /uk/en/products # UK store, English
114
+ ```
115
+
116
+ A middleware (`src/proxy.ts`) uses `createSpreeMiddleware` from `@spree/next` to detect the visitor's country and locale, then redirects to the correct URL prefix. The `CountrySwitcher` component lets users change regions manually.
117
+
118
+ ## Server Actions
119
+
120
+ All data fetching is done through server actions in `src/lib/data/`. These are thin wrappers around `@spree/next` functions — locale and currency are resolved automatically from cookies:
121
+
122
+ ```typescript
123
+ // Products
124
+ import { getProducts, getProduct, getProductFilters } from '@/lib/data/products'
125
+
126
+ const products = await getProducts({ limit: 12 })
127
+ const product = await getProduct('product-slug')
128
+ const filters = await getProductFilters()
129
+
130
+ // Cart
131
+ import { getCart, addToCart, updateCartItem, removeCartItem } from '@/lib/data/cart'
132
+
133
+ const cart = await getCart()
134
+ await addToCart('var_xxx', 1)
135
+ await updateCartItem('li_xxx', 2)
136
+ await removeCartItem('li_xxx')
137
+
138
+ // Authentication
139
+ import { login, register, logout, getCustomer } from '@/lib/data/customer'
140
+
141
+ await login('user@example.com', 'password')
142
+ const customer = await getCustomer()
143
+ await logout()
144
+
145
+ // Addresses
146
+ import { getAddresses, createAddress, updateAddress, deleteAddress } from '@/lib/data/addresses'
147
+
148
+ const addresses = await getAddresses()
149
+ await createAddress({ first_name: 'John', ... })
150
+ ```
@@ -0,0 +1,141 @@
1
+ ---
2
+ title: Customization
3
+ description: Fork, customize, and extend the Spree Next.js Storefront
4
+ ---
5
+
6
+ ## Forking the Starter
7
+
8
+ The recommended approach is to fork the repository so you can customize freely while pulling upstream updates.
9
+
10
+ ### 1. Fork on GitHub
11
+
12
+ Go to [github.com/spree/storefront](https://github.com/spree/storefront) and click **Fork**.
13
+
14
+ ### 2. Clone Your Fork
15
+
16
+ ```bash
17
+ git clone https://github.com/YOUR_USERNAME/storefront.git
18
+ cd storefront
19
+ npm install
20
+ ```
21
+
22
+ ### 3. Add Upstream Remote
23
+
24
+ ```bash
25
+ git remote add upstream https://github.com/spree/storefront.git
26
+ ```
27
+
28
+ ### 4. Pull Upstream Updates
29
+
30
+ When the official starter gets updates, pull them into your fork:
31
+
32
+ ```bash
33
+ git fetch upstream
34
+ git merge upstream/main
35
+ ```
36
+
37
+ Resolve any conflicts in your customized files, then commit.
38
+
39
+ ## Styling
40
+
41
+ The storefront uses Tailwind CSS 4, which replaces the traditional `tailwind.config.ts` with CSS-native configuration via the `@theme` directive in `src/app/globals.css`.
42
+
43
+ ### Theme Customization
44
+
45
+ Edit the `@theme inline` block in `src/app/globals.css` to change colors, fonts, and other design tokens:
46
+
47
+ ```css
48
+ @import "tailwindcss";
49
+
50
+ :root {
51
+ --background: #fcfaf7;
52
+ --foreground: #171717;
53
+ }
54
+
55
+ @theme inline {
56
+ --color-background: var(--background);
57
+ --color-foreground: var(--foreground);
58
+ --font-sans: var(--font-geist);
59
+
60
+ /* Replace with your brand colors */
61
+ --color-primary-50: #eff6ff;
62
+ --color-primary-100: #dbeafe;
63
+ --color-primary-200: #bfdbfe;
64
+ --color-primary-300: #93c5fd;
65
+ --color-primary-400: #60a5fa;
66
+ --color-primary-500: #0077ff;
67
+ --color-primary-600: #0066dd;
68
+ --color-primary-700: #0055bb;
69
+ --color-primary-800: #004499;
70
+ --color-primary-900: #003377;
71
+ --color-primary-950: #001d4d;
72
+ }
73
+ ```
74
+
75
+ Variables defined in `@theme inline` become Tailwind utilities automatically — for example, `--color-primary-500` maps to `bg-primary-500`, `text-primary-500`, etc.
76
+
77
+ ## Components
78
+
79
+ All components live in `src/components/` and can be customized or replaced:
80
+
81
+ ```
82
+ src/components/
83
+ ├── cart/ # CartDrawer
84
+ ├── checkout/ # AddressStep, DeliveryStep, PaymentStep, StripePaymentForm, etc.
85
+ ├── layout/ # Header, Footer, CountrySwitcher
86
+ ├── navigation/ # Breadcrumbs
87
+ ├── products/ # ProductCard, ProductGrid, ProductCarousel, Filters, MediaGallery, VariantPicker
88
+ └── search/ # SearchBar
89
+ ```
90
+
91
+ Components use standard React patterns — modify them directly or replace them entirely with your own implementations.
92
+
93
+ ## Data Layer
94
+
95
+ To customize API behavior, modify the server actions in `src/lib/data/`. Each file handles a specific domain:
96
+
97
+ | File | Purpose |
98
+ |------|---------|
99
+ | `products.ts` | Product listing and detail queries |
100
+ | `cart.ts` | Cart operations (add, update, remove) |
101
+ | `checkout.ts` | Checkout flow (addresses, shipping, completion) |
102
+ | `customer.ts` | Authentication and profile management |
103
+ | `addresses.ts` | Address CRUD |
104
+ | `orders.ts` | Order history |
105
+ | `payment.ts` | Payment sessions and processing |
106
+ | `categories.ts` | Categories |
107
+ | `countries.ts` | Country and region data |
108
+ | `cookies.ts` | Auth check helper |
109
+ | `store.ts` | Store configuration |
110
+ | `credit-cards.ts` | Saved payment methods |
111
+ | `gift-cards.ts` | Gift card management |
112
+ | `utils.ts` | Shared helpers (error handling, fallbacks) |
113
+
114
+ These server actions wrap the `@spree/next` package functions. You can add custom logic, caching strategies, or additional transformations as needed.
115
+
116
+ ## Adding New Pages
117
+
118
+ Follow the existing App Router pattern with localized routes. Place pages under the `(storefront)` route group to inherit the shared header/footer layout:
119
+
120
+ ```
121
+ src/app/[country]/[locale]/(storefront)/your-new-page/page.tsx
122
+ ```
123
+
124
+ ```typescript
125
+ import { listProducts } from '@spree/next';
126
+
127
+ export default async function YourNewPage() {
128
+ const products = await listProducts({ limit: 6 });
129
+
130
+ return (
131
+ <div>
132
+ <h1>Your New Page</h1>
133
+ {/* Your content */}
134
+ </div>
135
+ );
136
+ }
137
+ ```
138
+
139
+ ## Building a Custom Storefront
140
+
141
+ If you prefer to build from scratch instead of forking the starter, you can use the `@spree/next` and `@spree/sdk` packages directly in any Next.js application. See the [@spree/next Package](/developer/storefront/nextjs/spree-next-package) documentation for the complete API reference.