@spree/docs 0.1.80 → 0.1.82

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 (31) hide show
  1. package/dist/api-reference/store-api/errors.md +3 -3
  2. package/dist/api-reference/store-api/idempotency.md +1 -1
  3. package/dist/developer/cli/quickstart.md +149 -1
  4. package/dist/developer/contributing/creating-an-extension.md +1 -1
  5. package/dist/developer/contributing/developing-spree.md +167 -76
  6. package/dist/developer/core-concepts/addresses.md +10 -10
  7. package/dist/developer/core-concepts/adjustments.md +1 -1
  8. package/dist/developer/core-concepts/customers.md +1 -1
  9. package/dist/developer/core-concepts/events.md +12 -6
  10. package/dist/developer/core-concepts/markets.md +10 -10
  11. package/dist/developer/core-concepts/media.md +2 -2
  12. package/dist/developer/core-concepts/orders.md +10 -10
  13. package/dist/developer/core-concepts/pricing.md +2 -2
  14. package/dist/developer/core-concepts/products.md +12 -12
  15. package/dist/developer/core-concepts/promotions.md +1 -1
  16. package/dist/developer/core-concepts/search-filtering.md +11 -11
  17. package/dist/developer/core-concepts/shipments.md +2 -2
  18. package/dist/developer/core-concepts/slugs.md +4 -4
  19. package/dist/developer/core-concepts/stores.md +1 -1
  20. package/dist/developer/core-concepts/translations.md +1 -1
  21. package/dist/developer/core-concepts/users.md +1 -1
  22. package/dist/developer/create-spree-app/quickstart.md +8 -7
  23. package/dist/developer/customization/checkout.md +1 -1
  24. package/dist/developer/customization/decorators.md +10 -8
  25. package/dist/developer/customization/quickstart.md +1 -1
  26. package/dist/developer/deployment/environment_variables.md +1 -1
  27. package/dist/developer/how-to/custom-order-routing.md +18 -3
  28. package/dist/developer/sdk/store/markets.md +5 -5
  29. package/dist/developer/tutorial/extending-models.md +1 -1
  30. package/dist/developer/upgrades/5.4-to-5.5.md +84 -17
  31. package/package.json +1 -1
@@ -145,7 +145,7 @@ Validation errors include an additional `details` field with per-field error mes
145
145
 
146
146
  ```bash
147
147
  curl https://api.mystore.com/api/v3/store/products/prod_nonexistent \
148
- -H "Authorization: Bearer pk_xxx"
148
+ -H "X-Spree-API-Key: pk_xxx"
149
149
  ```
150
150
 
151
151
  ```json 404
@@ -185,7 +185,7 @@ curl -X POST https://api.mystore.com/api/v3/store/account/addresses \
185
185
 
186
186
  ```bash
187
187
  curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
188
- -H "Authorization: Bearer pk_xxx" \
188
+ -H "X-Spree-API-Key: pk_xxx" \
189
189
  -H "X-Spree-Token: abc123" \
190
190
  -H "Content-Type: application/json" \
191
191
  -d '{"variant_id": "var_xxx", "quantity": 999}'
@@ -204,7 +204,7 @@ curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
204
204
 
205
205
  ```bash
206
206
  curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/complete \
207
- -H "Authorization: Bearer pk_xxx"
207
+ -H "X-Spree-API-Key: pk_xxx"
208
208
  ```
209
209
 
210
210
  ```json 422
@@ -16,7 +16,7 @@ Include an `Idempotency-Key` header with a unique value (e.g., a UUID) on any su
16
16
 
17
17
  ```bash
18
18
  curl -X POST https://api.mystore.com/api/v3/store/carts/cart_xxx/items \
19
- -H "Authorization: Bearer pk_xxx" \
19
+ -H "X-Spree-API-Key: pk_xxx" \
20
20
  -H "X-Spree-Token: abc123" \
21
21
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
22
22
  -H "Content-Type: application/json" \
@@ -40,7 +40,7 @@ spree init --no-open # Skip opening browser
40
40
 
41
41
  ### `spree dev`
42
42
 
43
- Start services and stream logs.
43
+ Run the app in the foreground — streams web + worker logs; `Ctrl+C` stops them. The databases keep running for a fast next boot (`spree stop` shuts everything down).
44
44
 
45
45
  ```bash
46
46
  spree dev
@@ -54,6 +54,16 @@ Stop all services.
54
54
  spree stop
55
55
  ```
56
56
 
57
+ ### `spree restart`
58
+
59
+ Restart `web` and `worker` in place — same image, same volumes, fresh Rails process. Good for `config/initializers/*.rb` changes or anything Zeitwerk doesn't auto-reload.
60
+
61
+ ```bash
62
+ spree restart
63
+ ```
64
+
65
+ Not appropriate for Gemfile changes (use `spree bundle install`, then Ctrl+C and re-run `spree dev`), Dockerfile / `.ruby-version` changes (use `spree build`), or compose file changes (Ctrl+C and re-run `spree dev`).
66
+
57
67
  ### `spree update`
58
68
 
59
69
  Pull the latest Spree Docker image and recreate containers. Migrations run automatically on startup.
@@ -62,6 +72,34 @@ Pull the latest Spree Docker image and recreate containers. Migrations run autom
62
72
  spree update
63
73
  ```
64
74
 
75
+ ### `spree build`
76
+
77
+ Rebuild the dev image after Dockerfile or `.ruby-version` changes. Only relevant after `spree eject`.
78
+
79
+ ```bash
80
+ spree build
81
+ spree build --reset-bundle # Also drop the bundle_cache volume so gems re-seed
82
+ spree build --yes # Skip confirmation prompts (for CI)
83
+ ```
84
+
85
+ `spree bundle add` does NOT require a rebuild — gems land in the `bundle_cache` volume which survives image rebuilds.
86
+
87
+ `--reset-bundle` only drops `bundle_cache`. Postgres, Redis, Meilisearch, and storage volumes are preserved.
88
+
89
+ ### `spree upgrade`
90
+
91
+ Walk a Spree version upgrade end-to-end inside the dev stack. Runs `bundle update`, applies pending migrations, then walks the version-specific data backfills from the upgrade manifest.
92
+
93
+ ```bash
94
+ spree upgrade # Detect target, run the full sequence interactively
95
+ spree upgrade --plan # Print the plan without executing (DRY_RUN=1)
96
+ spree upgrade --to 5.5 # Cap the walk at a specific target version
97
+ spree upgrade --step <id> # Re-run a single step idempotently (skips bundle + migrate)
98
+ spree upgrade --yes # Skip the per-step prompts
99
+ ```
100
+
101
+ Production upgrades only need the third stage — `bundle install` and `db:migrate` happen in your deploy pipeline. The CLI runs all three for local development. See [Upgrades](../upgrades.md) for the manual production path.
102
+
65
103
  ### `spree eject`
66
104
 
67
105
  Switch from the prebuilt Docker image to building from your local `backend/` directory. This lets you customize the Rails app — add gems, override models, add migrations, etc.
@@ -135,3 +173,113 @@ spree api-key create --name "Storefront" --type publishable # Store API key
135
173
  spree api-key create --name "Admin" --type secret # Admin API key
136
174
  spree api-key revoke <id> # Revoke a key
137
175
  ```
176
+
177
+ ## Dev workflow commands
178
+
179
+ These mirror the Rails commands you'd run if you were running the app directly on your host — but each is routed through `docker compose exec` against the running stack.
180
+
181
+ ### `spree generate`
182
+
183
+ Run a generator inside the container. Bare generator names are auto-prefixed with `spree:` — `model` runs `spree:model`, `api_resource` runs `spree:api_resource` — so you get the Spree conventions (`Spree::` namespace, `spree_`-prefixed table, prefixed IDs, `null: false`, no FK constraints) by default. Rails built-ins (`migration`, `scaffold`, `mailer`, `job`, …) and any name containing `:` are forwarded as-is.
184
+
185
+ ```bash
186
+ spree generate model Brand name:string slug:string:uniq # runs spree:model
187
+ spree generate api_resource Brand name:string slug:string:uniq # runs spree:api_resource — model + v3 Store/Admin API
188
+ spree generate migration AddPositionToSpreeBrands position:integer # Rails built-in, forwarded as-is
189
+ ```
190
+
191
+ `spree:api_resource` scaffolds the full v3 surface: model, migration, Store + Admin controllers and serializers, factory, controller specs, and routes.
192
+
193
+ ### `spree migrate`
194
+
195
+ Install pending Spree migrations from gems, then run `db:migrate` — the canonical post-update sequence.
196
+
197
+ ```bash
198
+ spree migrate
199
+ spree migrate:status # show the migration log (`db:migrate:status`)
200
+ spree migrate:rollback STEP=2 # roll back (`db:rollback`)
201
+ ```
202
+
203
+ ### `spree db:reset`
204
+
205
+ Drop, recreate, migrate, and seed the database. **Destructive** — wipes everything. Asks for confirmation.
206
+
207
+ ```bash
208
+ spree db:reset
209
+ spree db:reset --yes # Skip confirmation (for CI)
210
+ ```
211
+
212
+ ### `spree db:console`
213
+
214
+ Open a `psql` session against the dev Postgres database (runs inside the `postgres` container).
215
+
216
+ ```bash
217
+ spree db:console
218
+ ```
219
+
220
+ ### `spree routes`
221
+
222
+ Show Rails routes. All flags pass through to `bin/rails routes`.
223
+
224
+ ```bash
225
+ spree routes
226
+ spree routes -g products # Filter by pattern
227
+ spree routes -c Spree::Api::V3::Store::ProductsController # Filter by controller
228
+ spree routes --expanded
229
+ ```
230
+
231
+ ## Running things inside the container
232
+
233
+ These are passthrough commands — anything after the subcommand reaches the inner Rails/Bundle/Rake invocation as-is. Useful for ad-hoc commands that don't have a dedicated wrapper.
234
+
235
+ ### `spree exec`
236
+
237
+ Run an arbitrary command inside the `web` container.
238
+
239
+ ```bash
240
+ spree exec ls -la
241
+ spree exec env
242
+ spree exec ruby -v
243
+ ```
244
+
245
+ ### `spree rails`
246
+
247
+ Run a `bin/rails` command.
248
+
249
+ ```bash
250
+ spree rails c # Console (alias of `spree console`)
251
+ spree rails routes -g products # Alias of `spree routes -g products`
252
+ spree rails runner "puts Spree::Product.count"
253
+ spree rails new_subcommand arg1 arg2
254
+ ```
255
+
256
+ ### `spree bundle`
257
+
258
+ Run a `bundle` command. Gems land in the `bundle_cache` volume (no image rebuild needed).
259
+
260
+ ```bash
261
+ spree bundle install
262
+ spree bundle add stripe
263
+ spree bundle update spree_core
264
+ spree bundle outdated
265
+ ```
266
+
267
+ ### `spree rake`
268
+
269
+ Run a Rake task.
270
+
271
+ ```bash
272
+ spree rake -T # List tasks
273
+ spree rake spree:upgrade # Run the version-specific data backfills
274
+ spree rake spree:upgrade DRY_RUN=1 # Same, plan only
275
+ ```
276
+
277
+ ### `spree task`
278
+
279
+ Shortcut for `bin/rails <task>` (Spree-style rake tasks registered as Rails tasks).
280
+
281
+ ```bash
282
+ spree task load_sample_data
283
+ spree task spree:price_history:seed
284
+ spree task spree:price_history:prune
285
+ ```
@@ -248,7 +248,7 @@ module MyExtension
248
248
  subscribes_to 'product.updated'
249
249
 
250
250
  def handle(event)
251
- product = Spree::Product.find_by(id: event.payload['id'])
251
+ product = Spree::Product.find_by_prefix_id(event.payload['id'])
252
252
  return unless product
253
253
 
254
254
  ExternalService.sync(product)
@@ -5,6 +5,8 @@ description: >-
5
5
  code. We're happy you're here!
6
6
  ---
7
7
 
8
+ Please read our [Code of Conduct](https://github.com/spree/spree/blob/main/CODE_OF_CONDUCT.md) before contributing.
9
+
8
10
  ## Cloning the repository
9
11
 
10
12
  Spree is a big monorepo. For a faster clone, use a **partial clone** which downloads file contents on demand while keeping full commit history for `git log` and `git blame`:
@@ -24,66 +26,98 @@ You need **Node.js 20+** to run the workspace scripts (including `pnpm server:se
24
26
  Spree is a monorepo with three main areas:
25
27
 
26
28
  - **`spree/`** — Ruby gems (core, api, admin, emails) distributed as separate packages via RubyGems
27
- - **`packages/`** — TypeScript packages (SDKs, CLI, project scaffolding, docs)
28
- - **`server/`** — A Rails application cloned from [spree-starter](https://github.com/spree/spree-starter) that mounts the Spree gems (not checked in — run `pnpm server:setup` to create it)
29
+ - **`packages/`** — TypeScript packages (SDKs, CLI, project scaffolding, docs, React dashboard)
30
+ - **`server/`** — A Rails application cloned from [spree-starter](https://github.com/spree/spree-starter) that mounts the local Spree gems (not checked in — `pnpm server:setup` creates it)
29
31
 
30
- ## Backend Development (Ruby)
32
+ ## Setup
31
33
 
32
- ### Engines overview
34
+ A single command bootstraps the whole monorepo for both backend and frontend work. You need **Docker** running locally (Docker Desktop, OrbStack, or any compatible runtime) — no Ruby, Postgres, or Redis on your host.
33
35
 
34
- The Spree [Rails engines](https://guides.rubyonrails.org/engines.html) live inside `spree/` and are distributed as separate gems (Ruby packages installed via Bundler):
36
+ ```bash
37
+ pnpm install # workspace dependencies
38
+ pnpm server:setup # ~5–10 min on first run; idempotent
39
+ ```
35
40
 
36
- | Engine | Gem | Description |
37
- |---|---|---|
38
- | `core` | `spree_core` | Models, services, business logic |
39
- | `api` | `spree_api` | REST APIs |
40
- | `admin` | `spree_admin` | Admin dashboard |
41
- | `emails` | `spree_emails` | Transactional emails |
41
+ `pnpm server:setup` clones [spree-starter](https://github.com/spree/spree-starter) into `./server/`, wires it to load Spree gems from the monorepo via a Docker compose overlay, builds the dev image, starts the stack (Postgres + Redis + Meilisearch + Rails `web` + Sidekiq `worker`), and prepares the database. The full sequence lives in `scripts/server-setup.sh`.
42
42
 
43
- ### Spree namespace
43
+ When it's done, the backend is up at [http://localhost:3000](http://localhost:3000) and the admin is at [http://localhost:3000/admin](http://localhost:3000/admin). Sign in with the seed admin: **`spree@example.com`** / **`spree123`** (override at seed time with `ADMIN_EMAIL` / `ADMIN_PASSWORD` env vars — see `spree/core/app/services/spree/seeds/admin_user.rb`).
44
44
 
45
- All Spree models, controllers and other Ruby classes are namespaced by the `Spree` keyword, eg. `Spree::Product`. This means that those files are also located in `spree` sub-directories eg. [app/models/spree/product.rb](https://github.com/spree/spree/blob/main/spree/core/app/models/spree/product.rb).
45
+ Optionally load sample products, taxonomies, and option types:
46
46
 
47
- ### Setup
47
+ ```bash
48
+ pnpm server:load_sample_data
49
+ ```
48
50
 
49
- The server app is not checked into the monorepo. It's cloned from [spree-starter](https://github.com/spree/spree-starter) on first setup, with `SPREE_PATH=..` automatically configured so it uses your local Spree gems.
51
+ ## Running a backend day-to-day
50
52
 
51
- **Step 1: Clone the server app**
53
+ After the one-time setup, use these to bring the stack up and down:
52
54
 
53
55
  ```bash
54
- pnpm server:setup
56
+ pnpm server:dev # run the stack in the foreground — streams web + worker logs, Ctrl+C stops them
57
+ pnpm server:stop # full teardown (also stops postgres / redis / meilisearch)
58
+ pnpm server:restart # restart web + worker in place
59
+ pnpm server:logs # follow web container logs (when the stack runs detached)
60
+ pnpm server:console # open a Rails console inside the container
61
+ pnpm server:seed # re-run database seeds
62
+ pnpm server:build # rebuild the dev image (only after Dockerfile / .ruby-version changes)
55
63
  ```
56
64
 
57
- This clones [spree-starter](https://github.com/spree/spree-starter) into `server/` and sets `SPREE_PATH=..` in `server/.env` so it uses your local Spree gems.
65
+ `server:dev` behaves like any TS dev server (`vite dev`, the dashboard's `pnpm dev`): it runs in the foreground and Ctrl+C stops the app containers. Postgres, Redis, and Meilisearch keep running for a fast next boot — `pnpm server:stop` shuts everything down.
58
66
 
59
- **Step 2: Configure and run**
67
+ Run any CLI command against the running backend from `server/`:
60
68
 
61
69
  ```bash
62
70
  cd server
63
- # Edit .env if needed (e.g. DATABASE_USERNAME, DATABASE_HOST, DATABASE_PORT)
64
- bin/setup # installs Ruby (via mise), Postgres/Redis/Meilisearch (via brew), gems, prepares database
65
- bin/dev # starts Rails + Sidekiq + CSS watchers via overmind
71
+ pnpm exec spree migrate
72
+ pnpm exec spree generate model Brand name:string
73
+ pnpm exec spree upgrade --plan
66
74
  ```
67
75
 
68
- `bin/setup` installs system services natively (PostgreSQL, Redis, Meilisearch) via `brew bundle` on macOS or `apt-get` on Linux. If you'd rather run those services in Docker, start them from the repo root before running `bin/setup`:
76
+ See the [`@spree/cli` README](https://github.com/spree/spree/blob/main/packages/cli/README.md) for the full command surface.
69
77
 
70
- ```bash
71
- docker compose up -d postgres redis meilisearch
72
- ```
78
+ Which command after which change:
73
79
 
74
- Use `bin/setup --reset` to drop and recreate the database.
80
+ | What changed | What to run |
81
+ |---|---|
82
+ | Ruby code in `spree/*` gems | Nothing — gems are bind-mounted; code reloads on the next request |
83
+ | A new migration in a gem | `cd server && pnpm exec spree migrate` |
84
+ | Gem dependencies (gemspec / Gemfile) | `cd server && pnpm exec spree bundle install` (persists in the `bundle_cache` volume) |
85
+ | Compose files / `server/.env` | `pnpm server:dev` (force-recreates the containers) |
86
+ | `server/Dockerfile` / `.ruby-version` | `pnpm server:build`, then `pnpm server:dev` |
87
+ | Broken beyond repair | `pnpm server:setup` (full reset — wipes the database and volumes) |
75
88
 
76
- The app runs at [http://localhost:3000](http://localhost:3000). Admin Panel is at [http://localhost:3000/admin](http://localhost:3000/admin).
89
+ Re-run `pnpm server:setup` **only** to fully reset it does `docker compose down -v` + `rm -rf ./server`, wiping all DB data.
77
90
 
78
- **Step 3 (optional): Load sample data**
91
+ ## Native Ruby (advanced)
79
92
 
80
- To populate your store with sample products, customers, orders, and configuration:
93
+ If you prefer the fastest possible inner loop and don't mind installing Ruby, Postgres, Redis, and Meilisearch on your host directly, you can skip Docker:
81
94
 
82
95
  ```bash
83
- pnpm server:load_sample_data # from repo root
84
- # or, from server/: bin/rails spree:load_sample_data
96
+ pnpm server:create # clones spree-starter, writes server/.env with SPREE_PATH=..
97
+ cd server
98
+ bin/setup # installs Ruby (via mise), Postgres/Redis/Meilisearch (via brew bundle on macOS), gems, prepares the database
99
+ bin/dev # starts Rails + Sidekiq + CSS watchers via Foreman
85
100
  ```
86
101
 
102
+ This path is faster per request but means more on your host. It also runs against your installed system services, not a sandboxed Docker stack.
103
+
104
+ ## Backend Development (Ruby)
105
+
106
+ ### Engines overview
107
+
108
+ The Spree [Rails engines](https://guides.rubyonrails.org/engines.html) live inside `spree/` and are distributed as separate gems (Ruby packages installed via Bundler):
109
+
110
+ | Engine | Gem | Description |
111
+ |---|---|---|
112
+ | `core` | `spree_core` | Models, services, business logic |
113
+ | `api` | `spree_api` | REST APIs |
114
+ | `admin` | `spree_admin` | Admin dashboard |
115
+ | `emails` | `spree_emails` | Transactional emails |
116
+
117
+ ### Spree namespace
118
+
119
+ All Spree models, controllers and other Ruby classes are namespaced by the `Spree` keyword, eg. `Spree::Product`. This means that those files are also located in `spree` sub-directories eg. [app/models/spree/product.rb](https://github.com/spree/spree/blob/main/spree/core/app/models/spree/product.rb).
120
+
87
121
  ### Running engine tests
88
122
 
89
123
  Each engine has its own test suite. First install the shared dependencies at the `spree/` level, then navigate into the specific engine to set up and run its tests:
@@ -148,9 +182,9 @@ bundle exec parallel_rspec -n 4 spec
148
182
 
149
183
  After schema changes, re-run `bundle exec rake parallel_setup` to update the worker databases.
150
184
 
151
- ### Integration tests (Admin Panel)
185
+ ### Integration tests (legacy Rails admin)
152
186
 
153
- The Admin Panel uses feature specs that run in a real browser via chromedriver. You only need this if you're working on admin UI changes.
187
+ The legacy Rails admin (`spree/admin`) ships feature specs that run in a real browser via chromedriver. You only need this if you're touching the legacy admin UI.
154
188
 
155
189
  Install chromedriver on macOS:
156
190
 
@@ -158,47 +192,35 @@ Install chromedriver on macOS:
158
192
  brew install chromedriver
159
193
  ```
160
194
 
161
- ### Performance in development mode
195
+ The 6.0 React dashboard (`packages/dashboard`) has its own end-to-end test suite running on Playwright against a real Rails backend — see [Dashboard E2E tests](#dashboard-e2e-tests) under TypeScript Development.
162
196
 
163
- You may notice that your Spree store runs slower in development environment. This is caused by disabled caching and automatic reloading of code after each change.
197
+ ### Performance in development mode
164
198
 
165
- Caching is disabled by default. To turn on caching please run:
199
+ Spree runs slower in development because caching is disabled and code reloads on each request. To turn on caching:
166
200
 
167
201
  ```bash
168
- cd server && bin/rails dev:cache
202
+ cd server && pnpm exec spree rails dev:cache
169
203
  ```
170
204
 
171
- You will need to restart rails server after this change.
205
+ Restart the Rails server after running this (Ctrl+C the running `pnpm server:dev` and start it again).
172
206
 
173
207
  ## TypeScript Development
174
208
 
175
- ### Setup
176
-
177
- TypeScript developers don't need Ruby installed. Docker Compose from the repository root starts the backend using a prebuilt image:
178
-
179
- ```bash
180
- docker compose up -d
181
- ```
182
-
183
- This boots PostgreSQL, Redis, Meilisearch, and the Spree backend automatically (no `pnpm server:setup` needed). The API is available at `http://localhost:3000`.
184
-
185
- Then install dependencies and start all packages in watch mode:
186
-
187
- ```bash
188
- pnpm install
189
- pnpm dev
190
- ```
209
+ The backend setup is the same as for Ruby work — see [Setup](#setup) above. With `pnpm server:setup` done, the Rails backend is running and you can start the packages you want to work on.
191
210
 
192
211
  ### Packages
193
212
 
194
- | Package | Path | Description |
195
- |---|---|---|
196
- | `@spree/sdk` | `packages/sdk` | TypeScript SDK for the Spree Store API |
197
- | `@spree/cli` | `packages/cli` | CLI for managing Spree Commerce projects |
198
- | `create-spree-app` | `packages/create-spree-app` | Project scaffolding (`npm create spree-app`) |
199
- | `@spree/docs` | `packages/docs` | Developer documentation for AI agents and local reference |
200
-
201
- Internal packages (`@spree/admin-sdk`, `@spree/sdk-core`) are also part of the workspace but are not published to npm.
213
+ | Package | Path | Published | Description |
214
+ |---|---|---|---|
215
+ | `@spree/sdk` | `packages/sdk` | yes | TypeScript SDK for the Spree Store API |
216
+ | `@spree/admin-sdk` | `packages/admin-sdk` | yes | TypeScript SDK for the Spree Admin API |
217
+ | `@spree/cli` | `packages/cli` | yes | CLI for managing Spree Commerce projects |
218
+ | `create-spree-app` | `packages/create-spree-app` | yes | Project scaffolding (`npm create spree-app`) |
219
+ | `@spree/docs` | `packages/docs` | yes | Developer documentation for AI agents and local reference |
220
+ | `@spree/dashboard` | `packages/dashboard` | no | React SPA admin dashboard (Spree 6.0, replaces the legacy Rails admin) |
221
+ | `@spree/dashboard-core` | `packages/dashboard-core` | no | Framework: registries, providers, generic infra hooks for the dashboard |
222
+ | `@spree/dashboard-ui` | `packages/dashboard-ui` | no | Design system used by the dashboard |
223
+ | `@spree/sdk-core` | `packages/sdk-core` | no | Shared HTTP/retry/error layer used by both SDKs |
202
224
 
203
225
  ### Common commands
204
226
 
@@ -206,7 +228,7 @@ Run from the repository root — [Turborepo](https://turbo.build/) orchestrates
206
228
 
207
229
  | Command | Description |
208
230
  |---|---|
209
- | `pnpm dev` | Start Docker backend + watch mode for all packages |
231
+ | `pnpm dev` | Watch mode for all packages (does not boot the backend use `pnpm server:dev` for that) |
210
232
  | `pnpm build` | Build all packages (Turbo resolves dependency order) |
211
233
  | `pnpm test` | Run tests in all packages |
212
234
  | `pnpm lint` | Lint all packages |
@@ -225,21 +247,86 @@ pnpm --filter @spree/sdk generate:zod
225
247
 
226
248
  Tests use [Vitest](https://vitest.dev/) with [MSW](https://mswjs.io/) for API mocking at the network level.
227
249
 
228
- ### Type generation
250
+ ### Working on the React dashboard
251
+
252
+ The dashboard runs as a Vite dev server (port 5173) that proxies `/api/*` to the Rails backend on port 3000 — required for the auth refresh cookie to work over plain HTTP.
253
+
254
+ ```bash
255
+ # Terminal 1: backend
256
+ pnpm server:dev
257
+
258
+ # Terminal 2: dashboard
259
+ cd packages/dashboard
260
+ pnpm dev # http://localhost:5173
261
+ ```
262
+
263
+ Sign in with `spree@example.com` / `spree123`. To point at a non-default backend, set `VITE_SPREE_API_URL` (also needs to be set at build time for production bundles, not just dev):
264
+
265
+ ```bash
266
+ VITE_SPREE_API_URL=https://my-spree.example.com pnpm dev
267
+ ```
268
+
269
+ **Gotcha:** the dashboard imports `@spree/admin-sdk` from its **built** `dist/`, not source. If you edit `admin-sdk` (or `sdk-core`, or `sdk`) and want the dashboard to see the changes, run `pnpm build` from the monorepo root first (Turbo-cached). Editing dashboard code alone doesn't need this.
270
+
271
+ See the [dashboard README](https://github.com/spree/spree/blob/main/packages/dashboard/README.md) for the full architecture (auth, permissions, extension points, the three-package split between `dashboard`, `dashboard-core`, and `dashboard-ui`).
272
+
273
+ ### Dashboard E2E tests
274
+
275
+ The React dashboard ships an end-to-end suite running on [Playwright](https://playwright.dev/) against a real Rails backend — no mocks. The spec files exercise the full UI: login, staff invitation, invitee signup. CI runs the same suite via the `dashboard-e2e` job in `.github/workflows/packages.yml`.
229
276
 
230
- TypeScript types in `packages/sdk/src/types/generated/` are auto-generated from the Rails API serializers using [typelizer](https://github.com/skryukov/typelizer). To regenerate after changing serializers:
277
+ To run locally you need Ruby (the suite boots a real Rails server) and a one-time browser install:
231
278
 
232
279
  ```bash
280
+ # Make sure the dummy Rails app exists (one-time, after a fresh checkout).
233
281
  cd spree/api
234
- mise install --yes # to install Ruby if you don't have it already
235
- bundle install # to install dependencies
236
- bundle exec rake typelizer:generate
282
+ bundle install
283
+ bundle exec rake test_app
284
+
285
+ # Install Playwright's Chromium (one-time per machine).
286
+ cd ../../packages/dashboard
287
+ pnpm test:e2e:install
288
+
289
+ # Run the suite. Boots Rails on :3010 + Vite on :5174, runs all specs, tears
290
+ # both down. Safe to re-run repeatedly — the SQLite DB resets each run.
291
+ pnpm test:e2e
237
292
  ```
238
293
 
239
- After regenerating types, update the Zod schemas:
294
+ For interactive debugging (time-travel through actions, inspect the DOM at each step):
240
295
 
241
296
  ```bash
242
- pnpm --filter @spree/sdk generate:zod
297
+ pnpm test:e2e:ui
298
+ ```
299
+
300
+ Filter to a single spec or test name:
301
+
302
+ ```bash
303
+ pnpm test:e2e e2e/auth.spec.ts
304
+ pnpm test:e2e -g "invites a teammate"
305
+ ```
306
+
307
+ When a test fails, Playwright drops a screenshot, video, and DOM snapshot in `packages/dashboard/test-results/<spec>/` — usually enough to diagnose without re-running.
308
+
309
+ ### Type generation
310
+
311
+ TypeScript types in `packages/sdk/src/types/generated/` (Store API) and `packages/admin-sdk/src/types/generated/` (Admin API) are auto-generated from the Rails serializers using [typelizer](https://github.com/skryukov/typelizer). Zod schemas in `packages/sdk/src/zod/generated/` are derived from the TS types.
312
+
313
+ A **Lefthook pre-commit hook** regenerates both whenever you commit a change to `spree/api/app/serializers/**/*.rb` and re-stages the generated output. You don't need to run anything manually for the common case.
314
+
315
+ To regenerate manually (useful when iterating on serializers before committing):
316
+
317
+ ```bash
318
+ cd server
319
+ pnpm exec spree rake typelizer:generate # regenerate TS types
320
+ cd ../packages/sdk
321
+ pnpm generate:zod # regenerate Zod schemas
322
+ ```
323
+
324
+ If you'd rather avoid the Docker round-trip and have Ruby on your host, the native equivalent works too:
325
+
326
+ ```bash
327
+ cd spree/api
328
+ bundle install
329
+ bundle exec rake typelizer:generate
243
330
  ```
244
331
 
245
332
  ### Releasing packages
@@ -247,29 +334,33 @@ pnpm --filter @spree/sdk generate:zod
247
334
  Published packages use [Changesets](https://github.com/changesets/changesets) for version management. Each package owns its own `.changeset/` folder, so changesets must be created from inside the package directory:
248
335
 
249
336
  ```bash
250
- cd packages/sdk # or packages/cli, packages/create-spree-app
337
+ cd packages/sdk # or packages/admin-sdk, packages/cli, packages/create-spree-app
251
338
  pnpm changeset
252
339
  ```
253
340
 
254
341
  This creates a changeset file describing your changes. Commit it with your PR. When merged to `main`, a GitHub Action creates a "Version Packages" PR that bumps the version and publishes to npm.
255
342
 
343
+ Private packages (`@spree/dashboard`, `@spree/dashboard-core`, `@spree/dashboard-ui`, `@spree/sdk-core`) don't need changesets.
344
+
256
345
  ## Code Style
257
346
 
258
347
  Consistent code style is enforced via automated linters. Please make sure your changes pass linting before submitting a PR.
259
348
 
260
- **Ruby:** We use [RuboCop](https://rubocop.org/) for Ruby code. The configuration lives in `server/.rubocop.yml` and is shipped with [spree-starter](https://github.com/spree/spree-starter), so it's only available after running `pnpm server:setup`. Run it from the `server/` directory:
349
+ **Ruby:** We use [RuboCop](https://rubocop.org/) for Ruby code. The configuration lives in `server/.rubocop.yml` and is shipped with [spree-starter](https://github.com/spree/spree-starter), so it's only available after running `pnpm server:setup`. Run it inside the container via the CLI:
261
350
 
262
351
  ```bash
263
352
  cd server
264
- bundle exec rubocop
353
+ pnpm exec spree exec bundle exec rubocop
265
354
  ```
266
355
 
267
356
  To auto-fix correctable offenses:
268
357
 
269
358
  ```bash
270
- bundle exec rubocop -a
359
+ pnpm exec spree exec bundle exec rubocop -a
271
360
  ```
272
361
 
362
+ (On the native path, drop the `pnpm exec spree exec` prefix and run `bundle exec rubocop` directly.)
363
+
273
364
  **TypeScript:** We use [Biome](https://biomejs.dev/) for linting and formatting TypeScript code. Run it from the repository root:
274
365
 
275
366
  ```bash
@@ -319,7 +410,7 @@ To help us review your PR quickly:
319
410
  - **Describe your changes.** Explain what you changed and why. Include screenshots for UI changes.
320
411
  - **Add tests.** All new features and bug fixes should include appropriate test coverage.
321
412
  - **Update documentation.** If your change affects user-facing behavior, update the relevant docs.
322
- - **Include a changeset** if your change affects a published TypeScript package (`@spree/sdk`, `@spree/cli`, or `create-spree-app`). Run `pnpm changeset` from inside that package's directory — each package owns its own `.changeset/` folder.
413
+ - **Include a changeset** if your change affects a published TypeScript package (`@spree/sdk`, `@spree/admin-sdk`, `@spree/cli`, or `create-spree-app`). Run `pnpm changeset` from inside that package's directory — each package owns its own `.changeset/` folder.
323
414
  - **Ensure CI passes.** PRs with failing CI will not be reviewed.
324
415
 
325
416
  ## Reporting Bugs
@@ -129,14 +129,14 @@ await client.carts.update(cartId, {
129
129
  ```bash cURL
130
130
  # Use a saved address
131
131
  curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
132
- -H 'Authorization: Bearer pk_xxx' \
132
+ -H 'X-Spree-API-Key: pk_xxx' \
133
133
  -H 'X-Spree-Token: order_token' \
134
134
  -H 'Content-Type: application/json' \
135
135
  -d '{ "shipping_address_id": "addr_xxx", "billing_address_id": "addr_yyy" }'
136
136
 
137
137
  # Or pass a new address inline
138
138
  curl -X PATCH 'https://api.mystore.com/api/v3/store/carts/cart_xxx' \
139
- -H 'Authorization: Bearer pk_xxx' \
139
+ -H 'X-Spree-API-Key: pk_xxx' \
140
140
  -H 'X-Spree-Token: order_token' \
141
141
  -H 'Content-Type: application/json' \
142
142
  -d '{
@@ -189,15 +189,15 @@ const germany = await client.countries.get('DE', { include: 'market' })
189
189
  ```bash cURL
190
190
  # List all countries
191
191
  curl 'https://api.mystore.com/api/v3/store/countries' \
192
- -H 'Authorization: Bearer pk_xxx'
192
+ -H 'X-Spree-API-Key: pk_xxx'
193
193
 
194
194
  # Get a country with states
195
- curl 'https://api.mystore.com/api/v3/store/countries/US?include=states' \
196
- -H 'Authorization: Bearer pk_xxx'
195
+ curl 'https://api.mystore.com/api/v3/store/countries/US?expand=states' \
196
+ -H 'X-Spree-API-Key: pk_xxx'
197
197
 
198
198
  # Get a country with its market
199
- curl 'https://api.mystore.com/api/v3/store/countries/DE?include=market' \
200
- -H 'Authorization: Bearer pk_xxx'
199
+ curl 'https://api.mystore.com/api/v3/store/countries/DE?expand=market' \
200
+ -H 'X-Spree-API-Key: pk_xxx'
201
201
  ```
202
202
 
203
203
 
@@ -207,7 +207,7 @@ Use the `states_required` and `zipcode_required` fields to build adaptive addres
207
207
 
208
208
  States (provinces, regions) belong to a country and are used for address validation and zone matching. Countries like the US, Canada, Australia, and India have predefined states — for these countries, customers must select a state from the list rather than typing a name.
209
209
 
210
- States are fetched via the country endpoint using `?include=states`:
210
+ States are fetched via the country endpoint using `?expand=states`:
211
211
 
212
212
 
213
213
  ```typescript SDK
@@ -220,8 +220,8 @@ usa.states.forEach(state => {
220
220
  ```
221
221
 
222
222
  ```bash cURL
223
- curl 'https://api.mystore.com/api/v3/store/countries/US?include=states' \
224
- -H 'Authorization: Bearer pk_xxx'
223
+ curl 'https://api.mystore.com/api/v3/store/countries/US?expand=states' \
224
+ -H 'X-Spree-API-Key: pk_xxx'
225
225
  ```
226
226
 
227
227
 
@@ -94,7 +94,7 @@ order.included_tax_total
94
94
 
95
95
  ```bash cURL
96
96
  curl 'https://api.mystore.com/api/v3/store/orders/or_abc123?expand=items,fulfillments' \
97
- -H 'Authorization: Bearer pk_xxx' \
97
+ -H 'X-Spree-API-Key: pk_xxx' \
98
98
  -H 'X-Spree-Token: <token>'
99
99
  ```
100
100