Agent Skill · Spree Commerce

spree-extensions

Use when the user wants to install a specific third-party Spree gem (Stripe, Adyen, PayPal, i18n, search, social login, etc.), build their own Spree extension to share across apps, or swap a core Spree service via `Spree.dependencies`. Common phrasings include "add Stripe", "install spree_X", "what payment gateways", "create a Spree extension", "build a gem for Spree", "spree_dev_tools", "Spree.dependencies", "service swap". For deciding which customization pattern to use, see the `spree-customization` skill first — extensions are the last two rows of its decision tree and most single-app work doesn't need one.

Provider: Spree Commerce Path in repo: skills/spree-extensions/SKILL.md

Skill body

Spree Extensions

Commands below use the Spree CLI form (spree …, Docker). On a classic Rails app without the CLI (typical pre-5.4), use the native mapping in the spree-project skill — bin/rails / bundle exec rake from the app root, paths without the backend/ prefix.

This skill covers two distinct things: installing a third-party Spree gem (spree_stripe, spree_i18n, etc.) and building your own extension to share across multiple Spree apps. For single-app customization (the 99% case), use the spree-customization skill to find the right pattern — usually it’s a subscriber, dependency injection, or a decorator, not a gem.

Spree extensions are Rails engines packaged as gems. They mount into the host Rails app the same way Spree itself does. Adding one is a Gemfile entry + a generator run + a migrate.

Installing an extension

Three steps. Same pattern for every Spree extension. Requires the ejected dev stack: fresh create-spree-app projects run a prebuilt image where backend/ is not mounted into the container — run spree eject once first to switch to the bind-mounted dev compose.

# 1. Add to Gemfile
echo "gem 'spree_reviews'" >> backend/Gemfile

# 2. Install the gem
spree bundle install

# 3. Run the extension's install generator
spree rails g spree_reviews:install

The install generator is a convention — every Spree extension provides one at <gem_name>:install. It typically:

After the install generator runs, apply migrations and restart:

spree migrate
spree dev                 # Ctrl+C the running one first; `spree restart` does not reload Gemfile changes

Payment-provider gems bundled with create-spree-app

When you scaffold via npx create-spree-app, the resulting Gemfile already includes:

Gem What it provides
spree_stripe Stripe checkout — payment methods, sessions, webhooks
spree_adyen Adyen — drop-in component, methods, webhooks
spree_paypal_checkout PayPal Smart Buttons checkout
spree_i18n Translations for the admin UI across many locales

These are commercially-significant integrations. If you remove one from your Gemfile, also strip its admin Settings → Payment methods entry. If you add one to an existing project that wasn’t created with create-spree-app, follow the standard three-step install above.

Community extensions catalog

The authoritative list of community extensions is at docs/developer/customization/extensions.mdx (also at https://spreecommerce.org/docs/developer/customization/extensions). Categories covered:

Each extension links to its GitHub repo. Compatibility is per-extension-version — when you upgrade Spree, check each extension’s CHANGELOG before bumping.

spree_dev_tools — first install on any project

spree_dev_tools packages Spree’s test stack for host apps (RSpec, Factory Bot, Capybara, DatabaseCleaner) and loads the factories and helpers that ship inside spree_core — Spree’s own gems wire those dependencies directly and don’t use this gem. Projects scaffolded with create-spree-app already include it in the :development, :test group; add it yourself only on apps that weren’t:

# backend/Gemfile
group :development, :test do
  gem 'spree_dev_tools'
end
spree bundle install
spree rails g spree_dev_tools:install   # copies helpers into spec/support/ and enables loading them from rails_helper.rb

What it adds:

See the spree-testing skill for usage patterns.

Building your own extension

Skip this section unless you’re confident your customization belongs as a reusable gem. For one-app changes, put your code directly in backend/app/ and use subscribers + dependency injection.

If you do need to build an extension:

gem install spree_extension       # the Spree extension scaffolder
spree-extension simple_sales      # generates ./spree_simple_sales/
cd spree_simple_sales

The scaffold produces:

The engine declaration registers dependencies, subscribers, and admin UI extensions:

# lib/spree_simple_sales/engine.rb
module SpreeSimpleSales
  class Engine < ::Rails::Engine
    engine_name 'spree_simple_sales'

    initializer 'spree.simple_sales.subscribers' do
      Spree.subscribers << SpreeSimpleSales::OrderSubscriber
    end

    initializer 'spree.simple_sales.dependencies' do
      Spree.dependencies do |deps|
        deps.cart_add_item_service = 'SpreeSimpleSales::Cart::AddItem'
      end
    end
  end
end

For the full tutorial — decorators, controller extensions, model decorators, route additions, testing — see docs/developer/contributing/creating-an-extension.mdx.

Swapping a core service is NOT an extension

A common confusion: “I want my own version of an existing Spree service — should I build an extension?” Almost always no. Spree exposes 70 swappable core injection points via Spree.dependencies (or Spree.<name> = ... directly) plus 300+ API injection points (serializers, finders, per-endpoint services) via Spree.api. You subclass the default, register the override in config/initializers/spree.rb, and Spree calls your service everywhere. No gem packaging required.

# config/initializers/spree.rb
Spree.cart_add_item_service = MyApp::Cart::AddItem

See the spree-dependencies skill for the full pattern, the catalog of injection points, and the introspection rake tasks (spree:dependencies:list, spree:dependencies:overrides, spree:dependencies:validate).

Extensions become the right shape when you want to share customization (including dependency overrides) across multiple Spree apps — the extension’s engine declaration registers the overrides at boot, so any host app that bundles the gem gets the swap automatically.

When an extension is and isn’t the right shape

Extensions are the wrong tool for most single-app customization. They make sense when:

For one app: put the code directly in app/ (subscribers, decorators, services, controllers). No extension overhead. See the spree-customization skill for the full routing table; this skill picks up at “yes, I really want a gem.”

Common gotchas with extensions

Where to read further