@spree/docs 0.1.81 → 0.1.83

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 (30) hide show
  1. package/dist/api-reference/store-api/errors.md +4 -4
  2. package/dist/api-reference/store-api/idempotency.md +2 -2
  3. package/dist/developer/cli/quickstart.md +150 -2
  4. package/dist/developer/contributing/creating-an-extension.md +2 -2
  5. package/dist/developer/contributing/developing-spree.md +168 -79
  6. package/dist/developer/core-concepts/addresses.md +11 -11
  7. package/dist/developer/core-concepts/adjustments.md +2 -2
  8. package/dist/developer/core-concepts/customers.md +2 -2
  9. package/dist/developer/core-concepts/events.md +13 -7
  10. package/dist/developer/core-concepts/markets.md +11 -11
  11. package/dist/developer/core-concepts/media.md +3 -3
  12. package/dist/developer/core-concepts/orders.md +11 -11
  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 +2 -2
  16. package/dist/developer/core-concepts/search-filtering.md +12 -12
  17. package/dist/developer/core-concepts/shipments.md +3 -3
  18. package/dist/developer/core-concepts/slugs.md +4 -4
  19. package/dist/developer/core-concepts/stores.md +2 -2
  20. package/dist/developer/core-concepts/translations.md +2 -2
  21. package/dist/developer/core-concepts/users.md +2 -2
  22. package/dist/developer/create-spree-app/quickstart.md +9 -8
  23. package/dist/developer/customization/checkout.md +2 -2
  24. package/dist/developer/customization/decorators.md +11 -9
  25. package/dist/developer/customization/quickstart.md +2 -2
  26. package/dist/developer/deployment/environment_variables.md +2 -1
  27. package/dist/developer/sdk/store/markets.md +6 -6
  28. package/dist/developer/tutorial/extending-models.md +2 -2
  29. package/dist/developer/upgrades/5.4-to-5.5.md +84 -17
  30. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Errors
3
- description: Error response format, error codes, and handling strategies
3
+ description: Reference for Spree Store API error responses — JSON format, machine-readable codes, HTTP status codes, validation details, and retry strategies.
4
4
  ---
5
5
 
6
6
  The Store API uses a consistent, Stripe-style error format across all endpoints. Every error response includes a machine-readable `code` and a human-readable `message`.
@@ -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
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: "Idempotency"
3
3
  sidebarTitle: "Idempotency"
4
- description: "Prevent duplicate operations with idempotency keys"
4
+ description: "Use Idempotency-Key headers on Spree Store API mutations to safely retry carts, checkouts, and payments without creating duplicate side effects."
5
5
  ---
6
6
 
7
7
  The Store API supports idempotency keys on mutating endpoints. This lets you safely retry requests without risking duplicate side effects — for example, adding an item to cart twice or creating duplicate payments due to network timeouts.
@@ -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" \
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: Spree CLI
3
3
  sidebarTitle: Overview
4
- description: Manage your Spree Commerce project from the command line.
4
+ description: Install and use the @spree/cli to scaffold, run, build, migrate, and upgrade Docker-based Spree Commerce projects from the command line.
5
5
  ---
6
6
 
7
7
  The Spree CLI (`@spree/cli`) manages Docker-based Spree projects created with [create-spree-app](../create-spree-app/quickstart.md).
@@ -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
+ ```
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Creating an Extension
3
- description: Learn how to create a Spree extension.
3
+ description: Step-by-step guide to building a Spree extension gem — scaffolding, decorators, migrations, assets, and packaging for distribution.
4
4
  ---
5
5
 
6
6
  ## Overview
@@ -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)
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  title: Developing Spree
3
- description: >-
4
- This guide covers all the necessary steps to contributing to Spree source
5
- code. We're happy you're here!
3
+ description: Set up a Spree development environment with Docker, run the test suite, and submit pull requests to contribute to the Spree Commerce source code.
6
4
  ---
7
5
 
6
+ Please read our [Code of Conduct](https://github.com/spree/spree/blob/main/CODE_OF_CONDUCT.md) before contributing.
7
+
8
8
  ## Cloning the repository
9
9
 
10
10
  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 +24,98 @@ You need **Node.js 20+** to run the workspace scripts (including `pnpm server:se
24
24
  Spree is a monorepo with three main areas:
25
25
 
26
26
  - **`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)
27
+ - **`packages/`** — TypeScript packages (SDKs, CLI, project scaffolding, docs, React dashboard)
28
+ - **`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
29
 
30
- ## Backend Development (Ruby)
30
+ ## Setup
31
31
 
32
- ### Engines overview
32
+ 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
33
 
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):
34
+ ```bash
35
+ pnpm install # workspace dependencies
36
+ pnpm server:setup # ~5–10 min on first run; idempotent
37
+ ```
35
38
 
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 |
39
+ `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
40
 
43
- ### Spree namespace
41
+ 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
42
 
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).
43
+ Optionally load sample products, taxonomies, and option types:
46
44
 
47
- ### Setup
45
+ ```bash
46
+ pnpm server:load_sample_data
47
+ ```
48
48
 
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.
49
+ ## Running a backend day-to-day
50
50
 
51
- **Step 1: Clone the server app**
51
+ After the one-time setup, use these to bring the stack up and down:
52
52
 
53
53
  ```bash
54
- pnpm server:setup
54
+ pnpm server:dev # run the stack in the foreground — streams web + worker logs, Ctrl+C stops them
55
+ pnpm server:stop # full teardown (also stops postgres / redis / meilisearch)
56
+ pnpm server:restart # restart web + worker in place
57
+ pnpm server:logs # follow web container logs (when the stack runs detached)
58
+ pnpm server:console # open a Rails console inside the container
59
+ pnpm server:seed # re-run database seeds
60
+ pnpm server:build # rebuild the dev image (only after Dockerfile / .ruby-version changes)
55
61
  ```
56
62
 
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.
63
+ `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
64
 
59
- **Step 2: Configure and run**
65
+ Run any CLI command against the running backend from `server/`:
60
66
 
61
67
  ```bash
62
68
  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
69
+ pnpm exec spree migrate
70
+ pnpm exec spree generate model Brand name:string
71
+ pnpm exec spree upgrade --plan
66
72
  ```
67
73
 
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`:
74
+ See the [`@spree/cli` README](https://github.com/spree/spree/blob/main/packages/cli/README.md) for the full command surface.
69
75
 
70
- ```bash
71
- docker compose up -d postgres redis meilisearch
72
- ```
76
+ Which command after which change:
73
77
 
74
- Use `bin/setup --reset` to drop and recreate the database.
78
+ | What changed | What to run |
79
+ |---|---|
80
+ | Ruby code in `spree/*` gems | Nothing — gems are bind-mounted; code reloads on the next request |
81
+ | A new migration in a gem | `cd server && pnpm exec spree migrate` |
82
+ | Gem dependencies (gemspec / Gemfile) | `cd server && pnpm exec spree bundle install` (persists in the `bundle_cache` volume) |
83
+ | Compose files / `server/.env` | `pnpm server:dev` (force-recreates the containers) |
84
+ | `server/Dockerfile` / `.ruby-version` | `pnpm server:build`, then `pnpm server:dev` |
85
+ | Broken beyond repair | `pnpm server:setup` (full reset — wipes the database and volumes) |
75
86
 
76
- The app runs at [http://localhost:3000](http://localhost:3000). Admin Panel is at [http://localhost:3000/admin](http://localhost:3000/admin).
87
+ Re-run `pnpm server:setup` **only** to fully reset it does `docker compose down -v` + `rm -rf ./server`, wiping all DB data.
77
88
 
78
- **Step 3 (optional): Load sample data**
89
+ ## Native Ruby (advanced)
79
90
 
80
- To populate your store with sample products, customers, orders, and configuration:
91
+ 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
92
 
82
93
  ```bash
83
- pnpm server:load_sample_data # from repo root
84
- # or, from server/: bin/rails spree:load_sample_data
94
+ pnpm server:create # clones spree-starter, writes server/.env with SPREE_PATH=..
95
+ cd server
96
+ bin/setup # installs Ruby (via mise), Postgres/Redis/Meilisearch (via brew bundle on macOS), gems, prepares the database
97
+ bin/dev # starts Rails + Sidekiq + CSS watchers via Foreman
85
98
  ```
86
99
 
100
+ 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.
101
+
102
+ ## Backend Development (Ruby)
103
+
104
+ ### Engines overview
105
+
106
+ The Spree [Rails engines](https://guides.rubyonrails.org/engines.html) live inside `spree/` and are distributed as separate gems (Ruby packages installed via Bundler):
107
+
108
+ | Engine | Gem | Description |
109
+ |---|---|---|
110
+ | `core` | `spree_core` | Models, services, business logic |
111
+ | `api` | `spree_api` | REST APIs |
112
+ | `admin` | `spree_admin` | Admin dashboard |
113
+ | `emails` | `spree_emails` | Transactional emails |
114
+
115
+ ### Spree namespace
116
+
117
+ 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).
118
+
87
119
  ### Running engine tests
88
120
 
89
121
  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 +180,9 @@ bundle exec parallel_rspec -n 4 spec
148
180
 
149
181
  After schema changes, re-run `bundle exec rake parallel_setup` to update the worker databases.
150
182
 
151
- ### Integration tests (Admin Panel)
183
+ ### Integration tests (legacy Rails admin)
152
184
 
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.
185
+ 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
186
 
155
187
  Install chromedriver on macOS:
156
188
 
@@ -158,47 +190,35 @@ Install chromedriver on macOS:
158
190
  brew install chromedriver
159
191
  ```
160
192
 
161
- ### Performance in development mode
193
+ 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
194
 
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.
195
+ ### Performance in development mode
164
196
 
165
- Caching is disabled by default. To turn on caching please run:
197
+ Spree runs slower in development because caching is disabled and code reloads on each request. To turn on caching:
166
198
 
167
199
  ```bash
168
- cd server && bin/rails dev:cache
200
+ cd server && pnpm exec spree rails dev:cache
169
201
  ```
170
202
 
171
- You will need to restart rails server after this change.
203
+ Restart the Rails server after running this (Ctrl+C the running `pnpm server:dev` and start it again).
172
204
 
173
205
  ## TypeScript Development
174
206
 
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
- ```
207
+ 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
208
 
192
209
  ### Packages
193
210
 
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.
211
+ | Package | Path | Published | Description |
212
+ |---|---|---|---|
213
+ | `@spree/sdk` | `packages/sdk` | yes | TypeScript SDK for the Spree Store API |
214
+ | `@spree/admin-sdk` | `packages/admin-sdk` | yes | TypeScript SDK for the Spree Admin API |
215
+ | `@spree/cli` | `packages/cli` | yes | CLI for managing Spree Commerce projects |
216
+ | `create-spree-app` | `packages/create-spree-app` | yes | Project scaffolding (`npm create spree-app`) |
217
+ | `@spree/docs` | `packages/docs` | yes | Developer documentation for AI agents and local reference |
218
+ | `@spree/dashboard` | `packages/dashboard` | no | React SPA admin dashboard (Spree 6.0, replaces the legacy Rails admin) |
219
+ | `@spree/dashboard-core` | `packages/dashboard-core` | no | Framework: registries, providers, generic infra hooks for the dashboard |
220
+ | `@spree/dashboard-ui` | `packages/dashboard-ui` | no | Design system used by the dashboard |
221
+ | `@spree/sdk-core` | `packages/sdk-core` | no | Shared HTTP/retry/error layer used by both SDKs |
202
222
 
203
223
  ### Common commands
204
224
 
@@ -206,7 +226,7 @@ Run from the repository root — [Turborepo](https://turbo.build/) orchestrates
206
226
 
207
227
  | Command | Description |
208
228
  |---|---|
209
- | `pnpm dev` | Start Docker backend + watch mode for all packages |
229
+ | `pnpm dev` | Watch mode for all packages (does not boot the backend use `pnpm server:dev` for that) |
210
230
  | `pnpm build` | Build all packages (Turbo resolves dependency order) |
211
231
  | `pnpm test` | Run tests in all packages |
212
232
  | `pnpm lint` | Lint all packages |
@@ -225,21 +245,86 @@ pnpm --filter @spree/sdk generate:zod
225
245
 
226
246
  Tests use [Vitest](https://vitest.dev/) with [MSW](https://mswjs.io/) for API mocking at the network level.
227
247
 
228
- ### Type generation
248
+ ### Working on the React dashboard
249
+
250
+ 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.
251
+
252
+ ```bash
253
+ # Terminal 1: backend
254
+ pnpm server:dev
255
+
256
+ # Terminal 2: dashboard
257
+ cd packages/dashboard
258
+ pnpm dev # http://localhost:5173
259
+ ```
260
+
261
+ 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):
262
+
263
+ ```bash
264
+ VITE_SPREE_API_URL=https://my-spree.example.com pnpm dev
265
+ ```
266
+
267
+ **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.
268
+
269
+ 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`).
270
+
271
+ ### Dashboard E2E tests
272
+
273
+ 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
274
 
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:
275
+ To run locally you need Ruby (the suite boots a real Rails server) and a one-time browser install:
231
276
 
232
277
  ```bash
278
+ # Make sure the dummy Rails app exists (one-time, after a fresh checkout).
233
279
  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
280
+ bundle install
281
+ bundle exec rake test_app
282
+
283
+ # Install Playwright's Chromium (one-time per machine).
284
+ cd ../../packages/dashboard
285
+ pnpm test:e2e:install
286
+
287
+ # Run the suite. Boots Rails on :3010 + Vite on :5174, runs all specs, tears
288
+ # both down. Safe to re-run repeatedly — the SQLite DB resets each run.
289
+ pnpm test:e2e
237
290
  ```
238
291
 
239
- After regenerating types, update the Zod schemas:
292
+ For interactive debugging (time-travel through actions, inspect the DOM at each step):
240
293
 
241
294
  ```bash
242
- pnpm --filter @spree/sdk generate:zod
295
+ pnpm test:e2e:ui
296
+ ```
297
+
298
+ Filter to a single spec or test name:
299
+
300
+ ```bash
301
+ pnpm test:e2e e2e/auth.spec.ts
302
+ pnpm test:e2e -g "invites a teammate"
303
+ ```
304
+
305
+ 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.
306
+
307
+ ### Type generation
308
+
309
+ 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.
310
+
311
+ 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.
312
+
313
+ To regenerate manually (useful when iterating on serializers before committing):
314
+
315
+ ```bash
316
+ cd server
317
+ pnpm exec spree rake typelizer:generate # regenerate TS types
318
+ cd ../packages/sdk
319
+ pnpm generate:zod # regenerate Zod schemas
320
+ ```
321
+
322
+ If you'd rather avoid the Docker round-trip and have Ruby on your host, the native equivalent works too:
323
+
324
+ ```bash
325
+ cd spree/api
326
+ bundle install
327
+ bundle exec rake typelizer:generate
243
328
  ```
244
329
 
245
330
  ### Releasing packages
@@ -247,29 +332,33 @@ pnpm --filter @spree/sdk generate:zod
247
332
  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
333
 
249
334
  ```bash
250
- cd packages/sdk # or packages/cli, packages/create-spree-app
335
+ cd packages/sdk # or packages/admin-sdk, packages/cli, packages/create-spree-app
251
336
  pnpm changeset
252
337
  ```
253
338
 
254
339
  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
340
 
341
+ Private packages (`@spree/dashboard`, `@spree/dashboard-core`, `@spree/dashboard-ui`, `@spree/sdk-core`) don't need changesets.
342
+
256
343
  ## Code Style
257
344
 
258
345
  Consistent code style is enforced via automated linters. Please make sure your changes pass linting before submitting a PR.
259
346
 
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:
347
+ **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
348
 
262
349
  ```bash
263
350
  cd server
264
- bundle exec rubocop
351
+ pnpm exec spree exec bundle exec rubocop
265
352
  ```
266
353
 
267
354
  To auto-fix correctable offenses:
268
355
 
269
356
  ```bash
270
- bundle exec rubocop -a
357
+ pnpm exec spree exec bundle exec rubocop -a
271
358
  ```
272
359
 
360
+ (On the native path, drop the `pnpm exec spree exec` prefix and run `bundle exec rubocop` directly.)
361
+
273
362
  **TypeScript:** We use [Biome](https://biomejs.dev/) for linting and formatting TypeScript code. Run it from the repository root:
274
363
 
275
364
  ```bash
@@ -319,7 +408,7 @@ To help us review your PR quickly:
319
408
  - **Describe your changes.** Explain what you changed and why. Include screenshots for UI changes.
320
409
  - **Add tests.** All new features and bug fixes should include appropriate test coverage.
321
410
  - **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.
411
+ - **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
412
  - **Ensure CI passes.** PRs with failing CI will not be reviewed.
324
413
 
325
414
  ## Reporting Bugs