> ## Documentation Index
> Fetch the complete documentation index at: https://spreecommerce.org/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrading to Spree 5.3

> This guide covers upgrading a Spree 5.2 application to Spree 5.3.

<Info>
  Before proceeding to upgrade, please ensure you're at [Spree 5.2](/developer/upgrades/5.1-to-5.2)
</Info>

## Upgrade steps

### Update gems

```bash theme={"theme":"night-owl"}
bundle update
```

### Fetch and run missing migrations

```bash theme={"theme":"night-owl"}
bin/rake spree:install:migrations && bin/rails db:migrate
```

This will setup new database schema for the new features in Spree 5.3 like Price Lists and Customer Groups.

### Re-run Admin Panel Install Generator

Admin Panel was completely rewritten to use Tailwind v4 so you need to re-run the install generator to setup Tailwind and remove any Dart Sass related files.

```bash theme={"theme":"night-owl"}
bin/rails g spree:admin:install
```

This will also modify your `Procfile.dev` file to include the new Tailwind CSS watch task instead of the old Dart Sass watch task.

#### Add listen gem to Gemfile

You also need to add `listen` gem to your Gemfile in the development group, unless you already have it.

```ruby theme={"theme":"night-owl"}
group :development do
  gem 'listen', '>= 3.0'
end
```

### Run counter cache rake tasks

Spree 5.3 introduces counter caches for products, taxons and variants. You need to run the following rake tasks to populate the counter caches:

```bash theme={"theme":"night-owl"}
bin/rake spree:products:reset_counter_caches
bin/rake spree:taxons:reset_counter_caches
bin/rake spree:variants:reset_counter_caches
```

This will greatly improve the performance of your application by avoiding N+1 queries.

<Warning>
  You will need to run this rake task locally and on your production environment to ensure that the counter caches are populated correctly.
</Warning>

### Generate product metrics

Spree 5.3 introduces product metrics for products. You need to run the following rake task to populate the product metrics:

```bash theme={"theme":"night-owl"}
bin/rake spree:products:populate_metrics
```

This will populate the product metrics for all products in your database. Product metrics are used to sort products by best selling scope.

<Warning>
  You will need to run this rake task locally and on your production environment to ensure that the product metrics are populated correctly.
</Warning>

This rake task will enqueue background jobs to populate the product metrics for all products in your database so you need to make sure that your background jobs are configured correctly.

### Replace `auto_strip_attributes` gem usage

`auto_strip_attributes` gem [was removed from Spree](https://github.com/spree/spree/pull/13462) due to bugs and conflicts with translations feature. Also it's not required anymore as built-in Rails `normalizes` provides the same feature without an additional depepdency.

If you used `auto_stripe_attributes` in your application, you will need to change it to `normalizez`, eg.

Replace

```ruby theme={"theme":"night-owl"}
auto_strip_attributes :name
```

With:

```ruby theme={"theme":"night-owl"}
normalizes :name, with: ->(value) { value&.to_s&.squish&.presence }
```

### Update Storefront to Tailwind v4 (Optional)

<Info>
  This is optional if you're not using the `spree_storefront` gem.
</Info>

Spree 5.3 requires Tailwind v4 as it's also used now for the Admin panel so you need to update your Storefront to Tailwind v4 as well.

If you didn't update your Storefront to Tailwind v4 in the previous upgrade guide, you need to do it now.

Running `bundle update` previously installed Tailwind v4. You only need to run

```bash theme={"theme":"night-owl"}
bin/rails g spree:storefront:install
```

This will:

1. Overwrite `config/tailwind.config.js` file with the new Tailwind v4 configuration.
2. Add `app/assets/tailwind/application.css` file with the new Tailwind v4 styles. If you modified `app/assets/stylesheets/application.tailwind.css` file, you will need to merge your changes with the new one.

### Update Storefront to use `pagy` instead of `kaminari` (Optional)

<Info>
  This is optional if you're not using the `spree_storefront` gem.
</Info>

Spree 5.3 introduces [pagy](https://ddnexus.github.io/pagy/) as the default pagination gem. Pagy is a faster and more memory-efficient pagination gem than Kaminari. This works automatically for the API and Admin panel.

For Storefront, you need to either update your theme (if you're not using the default theme) or set `use_kaminari_pagination` preference to `true` in your `config/initializers/spree.rb` file.

#### Products infinite scroll fix

Please replace the contents of your `show_more_button.html.erb` with the following code:

```erb theme={"theme":"night-owl"}
<% if storefront_pagy&.next %>
  <%= turbo_frame_tag "next_page", src: url_for(params.to_unsafe_h.merge(page: storefront_pagy.next, format: :turbo_stream)), class: "block relative w-full", data: { controller: "infinite-scroll", infinite_scroll_offset_value: "1350px" }, loading: "lazy" do %>
    <span class="flex justify-center gap-2 items-center py-4 left-0 w-full h-full">
      <%= render 'spree/shared/icons/spinner' %>
      <%= Spree.t(:loading) %>...
    </span>
  <% end %>
<% end %>
```

#### Posts pagination

In the following files:

* `page_sections/_post_grid.html.erb`
* `posts/_pagination.html.erb`

Replace this line:

```erb theme={"theme":"night-owl"}
<%= paginate @posts, theme: 'storefront', outer_window: 1, inner_window: 2 %>
```

with this line:

```erb theme={"theme":"night-owl"}
<%= render 'spree/shared/pagination' %>
```

### Include Page Builder factories (Optional)

Page Builder was extracted to a separate gem (`spree_page_builder`) so you need to include the Page Builder factories in your test suite if you were using them in your tests

Add this line to your `spec_helper.rb` file:

```ruby theme={"theme":"night-owl"}
require 'spree/page_builder/testing_support/factories'
```

## Updating Spree Extensions

If you maintain a Spree extension, the following changes may be required to ensure compatibility with Spree 5.3.

### Admin Controller Changes

#### Use `prepend_before_action` for filters that modify `params[:q]`

In Spree 5.3, the `ResourceController#load_resource` before\_action calls `collection` which builds the search query using `search_params`. If your extension uses before\_actions to load data needed for filtering (e.g., loading a vendor to filter products), you must use `prepend_before_action` to ensure your filter runs before `load_resource`.

**Before (Spree 5.2):**

```ruby theme={"theme":"night-owl"}
module MyExtension
  module Admin
    module ProductsControllerDecorator
      def self.prepended(base)
        base.before_action :load_vendor, only: :index
      end
    end
  end
end
```

**After (Spree 5.3):**

```ruby theme={"theme":"night-owl"}
module MyExtension
  module Admin
    module ProductsControllerDecorator
      def self.prepended(base)
        base.prepend_before_action :load_vendor, only: :index
      end
    end
  end
end
```

#### Replace `assign_extra_collection_params` with `search_params` override

The `assign_extra_collection_params` method is no longer used in Spree 5.3. Instead, override the `search_params` method to add custom Ransack filters.

**Before (Spree 5.2):**

```ruby theme={"theme":"night-owl"}
def assign_extra_collection_params
  params[:q][:vendor_id_eq] = @vendor.id if @vendor.present?
end
```

**After (Spree 5.3):**

```ruby theme={"theme":"night-owl"}
def search_params
  result = super
  result[:vendor_id_eq] = @vendor.id if @vendor.present?
  result
end
```

#### Date range filtering changes

The base `ResourceController#search_params` now processes date range params (`created_at_gt`, `created_at_lt`, etc.) and converts them to `beginning_of_day`. If you need `end_of_day` for `_lt` params, override `search_params` with custom handling:

```ruby theme={"theme":"night-owl"}
def search_params
  params[:q] ||= {}
  params[:q][:s] ||= collection_default_sort if collection_default_sort.present?

  if params[:q][:created_at_gt].present?
    params[:q][:created_at_gt] = parse_date_param(params[:q][:created_at_gt])
  end

  if params[:q][:created_at_lt].present?
    params[:q][:created_at_lt] = parse_date_param(params[:q][:created_at_lt])&.end_of_day
  end

  params[:q]
end
```

### Admin Tables API

The old filter partial system (`Spree.admin.partials.*_filters`) has been replaced with built-in filtering in the Tables API. Remove any filter partials and configure filtering directly in table column definitions.

**Before (Spree 5.2):**

```ruby theme={"theme":"night-owl"}
Spree.admin.partials.orders_filters << 'spree/admin/orders/vendor_filter'
```

**After (Spree 5.3):**

```ruby theme={"theme":"night-owl"}
Spree.admin.tables.orders.add :vendor,
  label: :vendor,
  type: :custom,
  filterable: true,
  filter_type: :select,
  ransack_attribute: :vendor_id_eq,
  value_options: -> { Spree::Vendor.pluck(:name, :id) },
  partial: 'spree/admin/orders/table/vendor_column'
```

See the [Admin Tables documentation](/developer/admin/tables) for more details.

### Tailwind CSS v4 Migration

If your extension includes admin views with CSS classes, update Bootstrap utility classes to Tailwind v4:

| Bootstrap          | Tailwind v4     |
| ------------------ | --------------- |
| `d-flex`           | `flex`          |
| `d-none`           | `hidden`        |
| `text-muted`       | `text-gray-500` |
| `ml-2`, `mr-2`     | `ms-2`, `me-2`  |
| `pl-2`, `pr-2`     | `ps-2`, `pe-2`  |
| `font-weight-bold` | `font-bold`     |

### Stimulus Tabs Controller

If your extension uses Bootstrap tabs, migrate to the Stimulus tabs controller:

**Before (Bootstrap):**

```erb theme={"theme":"night-owl"}
<ul class="nav nav-tabs">
  <li class="nav-item">
    <a class="nav-link active" data-toggle="tab" href="#tab1">Tab 1</a>
  </li>
</ul>
<div class="tab-content">
  <div class="tab-pane active" id="tab1">Content</div>
</div>
```

**After (Stimulus):**

```erb theme={"theme":"night-owl"}
<div data-controller="tabs">
  <ul class="nav nav-pills mb-4" role="tablist">
    <li class="nav-item" role="presentation">
      <a class="nav-link active" data-tabs-target="tab" data-action="click->tabs#select" role="tab">Tab 1</a>
    </li>
  </ul>
  <div data-tabs-target="panel" role="tabpanel" class="animate-fade-in">Content</div>
</div>
```

### Progress Bar Component

The `progress_bar_component` signature has changed:

**Before (Spree 5.2):**

```erb theme={"theme":"night-owl"}
<%= progress_bar_component(value, 0, 100) %>
```

**After (Spree 5.3):**

```erb theme={"theme":"night-owl"}
<%= progress_bar_component(value, min: 0, max: 100) %>
```

### Table Column Visibility

All table columns now require `default: true` to be visible by default:

```ruby theme={"theme":"night-owl"}
Spree.admin.tables.vendors.add :name,
  label: :name,
  type: :string,
  sortable: true,
  default: true,  # Required for column to be visible
  position: 10
```
