docs/developer/storefront/rails/custom-javascript.mdx
Spree Storefront can be easily extended with custom JavaScript. Most of the JavaScript in the storefront is powered by a framework called Stimulus.js. It's a very simple and minimalistic framework only enhancing our server-side rendered HTML with a bit of interactivity.
Spree Storefront comes with a few 3rd party JavaScript libraries already included.
Main libraries we're using:
You can find them in the app/assets/javascripts/vendor directory.
You're probably wondering why these libraries are in the vendor directory, and not in node_modules.
That's because we're not using Node.js at all. So no Yarn or npm. We're using a different approach to manage dependencies.
We're using a tool called Importmaps to manage dependencies.
<Info> If you want to use a different JavaScript package manager you can do so by using [jsbundling-rails](https://github.com/rails/jsbundling-rails) gem. </Info>To install dependencies you need to run the following command:
bin/importmap pin react
This will install the dependencies, download the files to your vendor/javascript directory and add them to your config/importmap.rb file, eg.
pin "react" # @19.1.0
Now you can just import the library in your application entry point, eg. application.js:
import "react";
Mentioned above, the application entry point is the application.js file. It's located in the app/javascript directory.
If you want to add custom JavaScript to your Spree storefront, you can do so by adding a new file to the app/javascript directory.
Stimulus controllers are a way to add interactivity to your Spree storefront. Storefront controllers can be found in the Spree repository in the storefront/app/javascript/spree/storefront/controllers directory.
You can find more information about Stimulus controllers in the Stimulus.js documentation.
To add a new controller you need to create a new file in the app/javascript/controllers directory. It will be automatically picked up by the application.
// app/javascript/controllers/hello_controller.js
import { Controller } from '@hotwired/stimulus'
export default class extends Controller {
connect() {
console.log("Hello Spree Commerce Stimulus!", this.element);
}
}
To use the controller in your HTML you need to add the data-controller attribute to your element, eg.
<div data-controller="hello">
Hello Spree Commerce Stimulus!
</div>
If you need to add a small piece of JavaScript code (eg. tracking, marketing, analytics, customer service etc.) you can do this by:
Declaring a new head partial in the config/initializers/spree.rb file, eg.
Creating a new file in the app/views/spree/shared/my_tracking_code.html.erb, where you can add your tracking code, eg.
<script>
console.log("I'm a spy!");
</script>
You can extend or override existing Storefront Stimulus controllers:
// app/javascript/controllers/cart_controller.js
import CartController from 'spree/storefront/controllers/cart_controller'
export default class extends CartController {
connect() {
super.connect()
console.log('Extended cart controller connected!')
}
// Override existing method
addItem(event) {
// Custom logic before adding
console.log('Adding item...')
super.addItem(event)
// Custom logic after adding
}
}
Spree Storefront uses Turbo for navigation. You can hook into Turbo events:
// app/javascript/application.js
document.addEventListener('turbo:load', () => {
console.log('Page loaded via Turbo')
})
document.addEventListener('turbo:before-visit', (event) => {
console.log('About to visit:', event.detail.url)
})
document.addEventListener('turbo:frame-load', (event) => {
console.log('Turbo frame loaded:', event.target.id)
})