A Shopify app starter, built on top of Cloudflare Workers. This template provides a foundation for building a Shopify app using the React Router 7 framework, deployed on Cloudflare's global network.
This lets you deploy an entire Shopify React Router 7 starter application to Cloudflare with a single click. It will setup a repo and a Cloudflare worker named after your project, along with Durable Objects for session storage and a D1 database binding for additional data storage needs.
Cloudflare Workers is flexible, scalable, and even has a free tier for those just getting started.
| Requests | Duration | CPU time | |
|---|---|---|---|
| Free | 100,000 per day | No charge for duration | 10 milliseconds of CPU time per invocation |
| Standard | 10 million included per month +$0.30 per additional million | No charge or limit for duration | 30 million CPU milliseconds included per month +$0.02 per additional million CPU milliseconds Max of 5 minutes of CPU time per invocation (default: 30 seconds) Max of 15 minutes of CPU time per Cron Trigger or Queue Consumer invocation |
This template uses Durable Objects for session storage, which provides excellent performance and consistency for store-specific data. Durable Objects are strongly consistent, geographically distributed, and perfect for storing any data that is specific to an individual Shopify store. When a store first uses your app, a Durable Object is created geographically close to that store, ensuring fast access times and strong consistency for all subsequent requests from that store. A D1 database is also included for cases where you need traditional SQL database functionality for data that spans across multiple stores or requires complex relational operations.
When to use Durable Objects:
- Store-specific data that is unique to each individual Shopify store. Since each store gets its own Durable Object instance created near their geographic location, this is ideal for any data that belongs to a single store and needs fast, consistent access.
When to use a D1 Database:
- Cross-store data, analytics that aggregate information from multiple stores, or any data that needs to be queried across your entire application rather than being specific to one store.
Before you begin, you'll need the following:
- Cloudflare Account: Sign up if you don't have one.
- Shopify Partner Account: Create an account if you don't have one.
- Shopify App: Create an app in the Shopify partner dashboard.
- Test Store: Set up either a development store or a Shopify Plus sandbox store for testing your app.
- Click the "Deploy to Cloudflare" button at the top of this README.
- Configure your deployment settings including worker name and repository details.
- After deployment, update the
wrangler.jsoncfile in your new repository with the credentials from your Shopify app:
You should consider storing them as secrets in a production application.
This template supports multiple D1 databases which can be useful for more complex applications. Two additional databases (DB2 and DB3) are included in the configuration but commented out by default. Here's how to enable them:
- Create the databases in Cloudflare Dashboard:
- Go to your Cloudflare Dashboard
- Navigate to Storage & Databases > D1 SQL Database
- Click "Create"
- Name your databases shop_auth_exampledb2 and shop_auth_exampledb3 (these names should match the database name in your wrangler.jsonc)
- Note the generated database IDs for each
- Update your wrangler.jsonc file
{
// ... other configuration
"d1_databases": [
{
"binding": "DB",
"database_name": "shop_auth",
"database_id": "151f7d9b-365f-41d7-83ed-0bf4eeef5086"
},
{
"binding": "DB2",
"database_name": "shop_auth_exampledb2",
"database_id": "your-actual-db2-id-from-dashboard"
},
{
"binding": "DB3",
"database_name": "shop_auth_exampledb3",
"database_id": "your-actual-db3-id-from-dashboard"
}
],
// ... rest of configuration- Commit and deploy your changes:
- After deployment, your Worker will have access to all three databases. You can access them in your code using the bindings.
- Visit the example page in the app to see how to interact with multiple databases.
To authenticate and query data you can use the shopify const that is exported from /app/shopify.server.ts:
export async function loader({ request }) {
const { admin } = await shopify.authenticate.admin(request);
const response = await admin.graphql(`
{
products(first: 25) {
nodes {
title
description
}
}
}`);
const {
data: {
products: { nodes },
},
} = await response.json();
return nodes;
}This template comes preconfigured with examples of:
- Setting up your Shopify app in /app/shopify.server.ts
- Querying data using Graphql. Please see: /app/routes/app._index.tsx.
- Responding to mandatory webhooks in /app/routes/webhooks.tsx
Please read the documentation for @shopify/shopify-app-remix to understand what other API's are available.
You may get an error similar to this "Error: Invalid appUrl configuration 'example.workers.dev', please provide a valid URL." When trying to update the domain in wrangler.jsonc
Make sure you have the url formatted properly, in this example it would be "https://example.workers.dev/"
Embedded Shopify apps must maintain the user session, which can be tricky inside an iFrame. To avoid issues:
- Use
Linkfromreact-routeror@shopify/polaris. Do not use<a>. - Use the
redirecthelper returned fromauthenticate.admin. Do not useredirectfromreact-router - Use
useSubmitor<Form/>fromreact-router. Do not use a lowercase<form/>.
This only applies if your app is embedded, which it will be by default.
Shopify apps are best when they are embedded in the Shopify Admin, which is how this template is configured. If you have a reason to not embed your app please make the following changes:
- Ensure
embedded = falseis set in shopify.app.toml`. Docs here. - Pass
isEmbeddedApp: falsetoshopifyApp()in./app/shopify.server.js|ts. - Change the
isEmbeddedAppprop toisEmbeddedApp={false}for theAppProviderin/app/routes/app.jsx|tsx. - Remove the
@shopify/app-bridge-reactdependency from package.json andvite.config.ts|js. - Remove anything imported from
@shopify/app-bridge-react. For example:NavMenu,TitleBaranduseAppBridge.
If you change your app's scopes and authentication goes into a loop and fails with a message from Shopify that it tried too many times, you might have forgotten to update your scopes with Shopify.
To do that, you can run the deploy CLI command.
If you are registering webhooks in the afterAuth hook, using shopify.registerWebhooks, you may find that your subscriptions aren't being updated.
Instead of using the afterAuth hook, the recommended approach is to declare app-specific webhooks in the shopify.app.toml file. This approach is easier since Shopify will automatically update changes to webhook subscriptions every time you run deploy. Please read these guides to understand more:
This template uses React Router 7 with Cloudflare Workers. The following Shopify tools are also included to ease app development:
- Shopify App React Router 7 provides authentication and methods for interacting with Shopify APIs.
- Shopify App Bridge allows your app to seamlessly integrate your app within Shopify's Admin.
- Polaris React is a powerful design system and component library that helps developers build high quality, consistent experiences for Shopify merchants.
- Webhooks: Callbacks sent by Shopify when certain events occur