spree-checkout
Implement Spree's checkout — the Order state machine (cart → address → delivery → payment → confirm → complete), the Payment and Shipment sub-state machines, the return flow (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), guest checkout, payment-step skipping for credit-covered orders, and the V3 checkout API surface. Use when building or customizing checkout flows, debugging state transitions, or wiring custom checkout steps.
Best use case
spree-checkout is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Implement Spree's checkout — the Order state machine (cart → address → delivery → payment → confirm → complete), the Payment and Shipment sub-state machines, the return flow (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), guest checkout, payment-step skipping for credit-covered orders, and the V3 checkout API surface. Use when building or customizing checkout flows, debugging state transitions, or wiring custom checkout steps.
Teams using spree-checkout should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/spree-checkout/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How spree-checkout Compares
| Feature / Agent | spree-checkout | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Implement Spree's checkout — the Order state machine (cart → address → delivery → payment → confirm → complete), the Payment and Shipment sub-state machines, the return flow (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), guest checkout, payment-step skipping for credit-covered orders, and the V3 checkout API surface. Use when building or customizing checkout flows, debugging state transitions, or wiring custom checkout steps.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Spree Checkout
## Before writing code
**Fetch live docs**:
1. Fetch https://spreecommerce.org/docs/developer/core-concepts/orders for the canonical state machine.
2. Fetch https://spreecommerce.org/docs/developer/core-concepts/payments for the Payment + PaymentSession (v5.4+) flow.
3. Check the live `Spree::Order` source on GitHub for the `state_machine` block — transitions and callbacks change.
4. For headless checkout, fetch the v3 Store API docs at https://spreecommerce.org/docs/api-reference.
5. Verify any custom-step pattern against the latest examples in `spree-starter`.
## Conceptual Architecture
### The Order State Machine
```
cart → address → delivery → payment → confirm → complete
↓
skip if store-credit-covered
```
Each transition validates prerequisites:
| State | Prerequisites |
|-------|---------------|
| `cart` | One or more line items |
| `address` | Bill + ship address present |
| `delivery` | Shipping method selected for every shipment |
| `payment` | At least one payment method valid for the total |
| `confirm` | Optional review step (configurable) |
| `complete` | All sub-states valid; transitions trigger fulfillment + emails |
### Payment Sub-State
`Order#payment_state` is a separate field summarizing all `Payment` rows:
| Value | Meaning |
|-------|---------|
| `balance_due` | Outstanding amount remains |
| `paid` | Fully paid |
| `credit_owed` | Refund pending |
| `failed` | All payments failed |
| `void` | Voided |
### Shipment Sub-State
`Order#shipment_state` summarizes all `Shipment` rows:
| Value | Meaning |
|-------|---------|
| `pending` | Awaiting payment / stock |
| `ready` | Ready to ship |
| `partial` | Some shipped |
| `shipped` | All shipped |
| `backorder` | Inventory shortfall |
| `canceled` | Canceled |
### Individual Shipment / Payment State Machines
- **`Shipment#state`**: `pending → ready → shipped` (+ `canceled`)
- **`Payment#state`**: `checkout → processing → pending → completed` (+ `failed`, `void`, `invalid`)
### Return Flow
```
ReturnAuthorization (authorized | canceled)
→ CustomerReturn
→ Reimbursement (pending | reimbursed | errored)
→ Refund (against original Payment)
```
`StoreCredit` reimbursements skip the Refund step and credit the user's balance.
### Skipping the Payment Step
If `order.outstanding_balance.zero?` after store-credit/gift-card application, the state machine skips `payment` and goes straight to `confirm`. Useful for free-trial / 100%-off scenarios.
### Guest vs Authenticated Checkout
Spree supports guest checkout by default — orders carry an `email` and `order_token` even without a `User`. The token allows a guest to revisit their order. Convert guests to users post-checkout via `Spree::Order#associate_user!`.
### Custom Checkout Steps
Add a custom step by inserting into the state machine via decorator:
```ruby
# app/models/spree/order_decorator.rb
module MyApp::OrderDecorator
def self.prepended(base)
base.state_machine.before_transition to: :delivery, do: :verify_gift_message
end
def verify_gift_message
# …
end
Spree::Order.prepend(self)
end
```
Custom steps are powerful but **upgrade-fragile** — Spree's state machine evolves. Prefer events or service objects when you only need to react.
### Checkout via API v3 (v5.4+)
Headless checkout typically:
1. `POST /api/v3/store/cart` — create cart (returns `ord_…` ID + cart token)
2. `POST /api/v3/store/cart/line_items` — add items
3. `PUT /api/v3/store/checkout` — set addresses, shipping method, payment method
4. `POST /api/v3/store/checkout/payment_sessions` — create a PaymentSession (Stripe/Adyen/PayPal)
5. `POST /api/v3/store/checkout/complete` — finalize
(Verify exact paths in the v3 API reference — endpoint shapes are still settling.)
### Payment Sessions (v5.4+)
The v5.4 `PaymentSession` abstracts the payment-provider handshake. The storefront creates a PaymentSession, the user authorizes via the gateway's hosted UI (Stripe Elements, Adyen Drop-in, PayPal Checkout), and the session is captured into a `Payment` on completion. Provider-specific.
## Implementation Guidance
### Reading the Current State
```ruby
order.state # one of cart/address/delivery/payment/confirm/complete
order.payment_state # balance_due/paid/...
order.shipment_state # pending/ready/...
order.can_transition?(:complete) # check before triggering
```
### Triggering Transitions Programmatically
```ruby
order.next! # advance to the next state if valid
order.complete! # force to complete if valid (typically last step)
order.cancel! # cancel + revert inventory
```
Never call `update_attribute(:state, …)` directly — bypasses callbacks and corrupts inventory/payments.
### Subscribing to Checkout Events
```ruby
class CheckoutSubscriber < Spree::Subscriber
subscribes_to 'order.completed'
on 'order.completed', :send_welcome_email
def send_welcome_email(event)
return if event.order.user.nil?
# …
end
end
```
Events fire after the database commit — safe to enqueue background jobs.
### Headless Checkout Patterns
- **Always use httpOnly cookies for the cart/order token**, not localStorage.
- **Confirm the cart server-side before showing the review step** — prices, tax, shipping can change between page loads.
- **Idempotency-Key headers on `/complete`** — prevent double-charging on retry.
- **Use Payment Sessions for v5.4+** — they handle 3DS / SCA / Apple Pay / Google Pay uniformly.
### Debugging Stuck Transitions
```ruby
order.errors.full_messages
order.valid?(state) # validate for a specific state
order.checkout_steps # configured step list
```
### Returns Workflow
```ruby
ra = Spree::ReturnAuthorization.create!(order: order, return_items: items)
ra.authorize!
cr = Spree::CustomerReturn.create!(return_items: ra.return_items, stock_location: location)
cr.fully_received?
reimbursement = Spree::Reimbursement.create!(customer_return: cr, order: order)
reimbursement.perform! # creates Refunds or StoreCredits
```
### Common Pitfalls
- **Bypassing the state machine** by setting `state` directly → corrupts inventory and payment totals.
- **Forgetting to recompute totals** after adjusting line items → use `Spree::OrderUpdater`.
- **Marking a Payment `completed` manually** → use the gateway's capture flow; manual completion skips reconciliation.
- **Treating `confirm` as required** — it's configurable (`checkout_steps` order).
- **Headless checkout drift** — the storefront's local state can diverge from the server's `Order#state`. Re-fetch after every mutating call.
- **Custom decorator on `state_machine`** — survives minor upgrades poorly; prefer event subscribers when possible.
Always re-verify state names and transition guards against the live `Spree::Order` source for the version you target.Related Skills
woo-checkout
Customize WooCommerce checkout — classic and block-based checkout, custom fields, validation, order processing, and checkout extensibility. Use when modifying the checkout flow, adding custom checkout fields, or integrating checkout extensions.
ucp-embedded-checkout
Implement UCP Embedded Checkout Protocol — iframe/webview-based checkout UI for human escalation using JSON-RPC 2.0 over postMessage. Use when the checkout status is requires_escalation and the buyer needs a merchant-hosted UI.
ucp-checkout-rest
Implement UCP Checkout over the REST binding — create, get, update, complete, and cancel checkout sessions with proper headers, idempotency, status transitions, and error handling. Use when building REST-based UCP checkout endpoints or clients.
ucp-checkout-mcp
Implement UCP Checkout over the MCP (Model Context Protocol) binding — expose checkout operations as MCP tools for AI agents. Use when building an MCP server that AI agents like Claude or Gemini can call for commerce, or when integrating with Shopify's MCP endpoint.
ucp-checkout-a2a
Implement UCP Checkout over the A2A (Agent-to-Agent) binding — enable autonomous agent-to-agent commerce using Agent Cards and structured message parts. Use when building agent-to-agent commerce flows.
spree-upgrades
Upgrade a Spree application — version-to-version migration paths (v4 → v5 is a major rewrite; v5.x → v5.y are simpler), Gemfile pinning strategy, decorator brittleness across versions, deprecated gems to remove (`spree_auth_devise`, `deface`, `spree_backend`), API v2 → v3 migration via `spree_legacy_api_v2`, admin Bootstrap → Tailwind transition, the upgrade guide workflow, and rollback strategy. Use when planning a Spree upgrade or auditing technical debt blocking one.
spree-typescript-sdk
Build storefronts and integrations using `@spree/sdk` — the official TypeScript SDK for Spree's API v3 (v5.4+). Covers installation, the resource-builder pattern (`spree.products.list`, `spree.checkout.create`, etc.), Zod schema validation, server-only auth (httpOnly JWTs, never exposing API keys), error handling, typing customizations, and pinning SDK versions to backend Spree releases. Use when integrating Spree into a Next.js / Node.js / TypeScript project.
spree-testing
Test Spree applications and extensions with RSpec — `spree_dev_tools` gem (v5.2+) for factories and helpers, FactoryBot patterns (prefer `build` over `create`), Capybara feature specs, controller/request specs, testing decorators and subscribers, dummy app for extension testing, system specs for the Hotwire admin, and CI patterns. Use when writing Spree tests, setting up CI, or refactoring slow specs.
spree-shipping-fulfillment
Build and customize Spree's shipping and fulfillment — ShippingMethod, ShippingCategory, Zone/ZoneMember, ShippingRate, the Stock::Estimator service, StockLocation/StockItem/StockMovement, multi-shipment orders, ShippingCalculator classes (FlatRate, FlatPercentItemTotal, PerItem, FlexiRate), shipment state machine, returns (ReturnAuthorization → CustomerReturn → Reimbursement → Refund), and integrating carrier APIs (UPS, FedEx, ShipStation). Use when configuring shipping rules, building fulfillment integrations, or debugging shipping-rate calculations.
spree-setup
Bootstrap a new Spree project — `create-spree-app` CLI (v5.2+), `spree-starter` Rails backend, the Next.js storefront repo, `bin/rails g spree:install`, sample data, Docker Compose, and the PostgreSQL + Redis + Sidekiq prerequisites. Use when starting a new Spree project from scratch or onboarding an existing repo.
spree-security
Secure a Spree deployment — Rails credentials and env-var hygiene, Devise auth (Spree v5 ships it in-core; `spree_auth_devise` is archived), CanCanCan authorization rules, Doorkeeper OAuth2 scopes, Storefront publishable key vs admin API key, webhook HMAC verification, OWASP Top 10 for Rails (mass assignment, CSRF, SQL injection via Ransack, XSS, IDOR through prefixed IDs), PCI scope (Spree never touches raw cards thanks to gateway tokenization), and multi-store data isolation. Use when auditing a Spree app, hardening a deploy, or addressing a security incident.
spree-promotions
Build and customize Spree's promotions engine — Promotion + PromotionRule + PromotionAction + CouponCode + Adjustment, the bundled rules (FirstOrder/ItemTotal/Product/Taxon/User/OneUsePerUser/Country/CustomerGroup/etc.), bundled actions (CreateAdjustment/CreateItemAdjustments/FreeShipping/CreateLineItems), Calculator classes, coupon batches with CSV export, the v5.1+ advanced rule-based engine, and authoring custom rules/actions/calculators. Use when modeling promotions, building discount UIs, or extending the promotions engine.