Built-in Pages

Spree Storefront comes with a full set of built-in pages that you can customize via page builder.

PageDescriptionClassURL
HomeThe main landing page of your storeSpree::Pages::Homepage/
Product DetailsIndividual product display pageSpree::Pages::ProductDetails/products/:id
TaxonShows products filtered by taxonSpree::Pages::Taxon/t/:permalink
Search ResultsDisplays search results for productsSpree::Pages::SearchResults/search
Shop AllShows all productsSpree::Pages::ShopAll/products
BlogShows your store’s blog posts and articlesSpree::Pages::PostList/posts
PostIndividual blog postSpree::Pages::Post/posts/:permalink
PasswordPassword page, when password protected storefront is enabledSpree::Pages::Password/

All of these page can be fully customized via page builder. You can add/remove sections, etc.

We’re planning to add page builder support for the following pages in the next Spree releases:

  • Cart
  • Checkout
  • Account

Sections

Each page is made of sections. Sections are the building blocks of a page. They are used to create the page content.

You can fetch page sections using:

current_page.sections

Custom Landing Pages in the Admin

You can easily create your own landing pages by going to to the Admin -> Storefront -> Pages and clicking on the New Page button. More on this in the Create a Landing Page guide. Each custom landing page can be customized via page builder.

Under the hood they use Spree::Pages::Custom class.

Building a new Page from scratch

If you need to build a page that is not one of the built-in pages, you can create your own page class. This will allow you to create a dedicated page for your business needs and at the same time allow your non-technical team to manage the page content without bugging you :)

Let’s assume you need to create a page that displays pickup locations. You already created a new model Spree::PickupLocation and added some data to the database. Now you want to create a page that displays these pickup locations.

First, let’s add a route for the new page.

# config/routes.rb
Spree::Core::Engine.add_routes do
  scope '(:locale)', locale: /#{Spree.available_locales.join('|')}/, defaults: { locale: nil } do # this line will enable translations for the new page
    resources :pickup_locations, only: [:index]
  end
end

Now, create the new page class file:

mkdir -p app/models/spree/pages && touch app/models/spree/pages/pickup_locations.rb

Now, let’s add the new page class:

module Spree
  module Pages
    class PickupLocations < Spree::Page
      # use https://tabler.io/icons to find the icon name
      def icon_name
        'map-marker-alt'
      end

      # This method is used to determine if the page is customizable via page builder
      def customizable?
        true
      end

      # this is the URL used to preview the page in the page builder UI
      def page_builder_url
        return unless page_builder_url_exists?(:pickup_locations_path)

        Spree::Core::Engine.routes.url_helpers.pickup_locations_path
      end

      # this is the default sections that will be shown on the page
      # in the later guide for sections you will learn how to add custom sections
      def default_sections
        [
          Spree::PageSections::PageTitle.new
        ]
      end
    end
  end
end

You will need to register the new page in the config/initializers/spree.rb file:

Rails.application.config.after_initialize do
  Rails.application.config.spree.pages << Spree::Pages::PickupLocations
end

Now, the controller:

mkdir -p app/controllers/spree && touch app/controllers/spree/pickup_locations_controller.rb
# app/controllers/spree/pickup_locations_controller.rb
module Spree
  class PickupLocationsController < StoreController
    def index
      @current_page = current_theme.pages.find_by(type: 'Spree::Pages::PickupLocations') # this is very important, without this the page will not be found
      @pickup_locations = current_store.pickup_locations
    end
  end
end

Lastly we need to add a view file for the page:

mkdir -p app/views/spree/pickup_locations && touch app/views/spree/pickup_locations/index.html.erb

And add the following code to the view file:

<%= render_page(current_page, pickup_locations: @pickup_locations) %>

render_page is a helper method defined in the Spree::PageHelper module that renders the page. It fetches all page sections and renders them one by one in the order they are set in the page builder by store staff.

Passing pickup_locations variable to the render_page method allows you to use it in the page sections templates, eg.

<%= pickup_locations.each do |pickup_location| %>
  <%= pickup_location.name %>
<% end %>