How We Built Shopify Theme Extensions With React
First, let’s do some introductions, right!
What are Shopify Theme App Extensions?
Shopify Theme App Extensions allow developers to add app features directly into Shopify themes, giving merchants more flexibility and control over their storefronts. Introduced in 2021, these extensions allow apps to integrate seamlessly with Shopify’s Online Store 2.0 themes, unlike app blocks, which offer limited customization.
Theme app extensions enable developers to build custom, dynamic content, such as embedded product recommendations, announcements, or special features directly within the theme. They’re typically built using a combination of React for the front end, Shopify CLI for setup, and Liquid templates to handle dynamic content rendering within the theme.
Now to the main part: why I talked about what I talked about earlier:
When our team at Codup began to build Extend Commerce for Shopify, we had a long list of features we wanted to integrate directly into the storefront theme. Since our team is already skilled in React, it made sense to use it to speed up the development process and keep things straightforward.
In addition, with Gadget’s support in app development, we had an opportunity to create a seamless experience between our admin app and theme extension. After some research, I mapped out a configuration setup that allowed us to leverage React effectively within Shopify’s ecosystem.
Initializing the extension:
– Make sure you have Shopify CLI installed globally, if not you can install it by running
“`bash
npm install -g @shopify/cli
“`
– Go to the root of your project and then run the following command in your terminal:
“`bash
shopify app config link
“`
This will ask you whether you want to create a new Shopify app. I assume that you already have an app created on the Shopify partner’s dashboard and connected to this project. So just search for the app’s name, and it should show up in the list from which you can select it.
– After the previous step a `shopify.app.toml` file should be generated at the project’s root with the relevant configuration.
– Now run the following command:
“`bash
shopify app generate extension
“`
Now select ‘Theme App Extension’ under “Online Store”, give it a name, and press ‘Return’. You should have a `extensions/` directory generated at the root of your project
Setup React App:
– Now, create an `apps/` directory at the root of your project, and initialize a react app using vite:
“`bash
yarn create vite
“`
– Once created, make the following changes in your `vite.config.js` or `vite.config.ts`:
“`javascript
import { defineConfig } from ‘vite’;
import { react } from ‘@vitejs/plugin-react-swc’;
const config = defineConfig(({ mode }) => {
const DEV = mode === ‘development’;
const EXTENSION_NAME = ‘<extension-name>’;
const outDir = path.join(__dirname, ‘..’, ‘..’, ‘extensions’, EXTENSION_NAME, ‘assets’);
return {
plugins: [react()],
build: {
outDir,
emptyOutDir: true,
assetsDir: ”,
rollupOptions: {
input: {
main: path.resolve(__dirname, ‘src’, ‘main.tsx’),
},
output: {
entryFileNames: ‘main.js’,
compact: !DEV_ONLY,
sanitizeFileName: !DEV_ONLY,
},
treeshake: true,
},
},
};
})
“`
Replace `<extension-name>` with your extension’s name. Also, make sure to replace `main.tsx` in the input path to `main.jsx` if you used JavaScript for the vite react starter.
– Now add the following script in the extension’s `package.json`
“`json
{
“scripts”: {
“build:dev”: “vite build –mode development –watch”
}
}
“`
And, in your project’s root `package.json` add the following lines:
“`json
{
“workspaces”: [“.”, “apps/*”],
“extension”: “yarn workspace <extension-name> run build:dev”,
“extension:build”: “yarn workspace <extension-name> run build”
}
“`
Now, you can just go and run the following 2 commands in different terminals:
“`bash
yarn dev
“`
and
“`
yarn extension
“`
Now, the last thing that you need to do is configure a block to use the react app. For this you can have any `div` or any tag with a selector and configure the react app to mount to that `div`. You can add the following line at the end of the block to load the JavaScript with the block.
“`html
<script src=”{{ ‘main.js’ | asset_url }}” type=”module” defer=”defer”></script>
“`
Finally, you can replace the name of the file with what you configured to be in the output section of vite config.
That’s it.