Building a Shopify app opens the door to a merchant base of millions. Whether you want to solve a workflow gap, extend store functionality, or launch a SaaS business, a well-built app can reach stores across the globe. But the path from idea to live listing involves several moving parts: authentication, API access, webhooks, hosting, and review.
This guide walks you through the full journey. You will learn how to build a Shopify app from scratch, test it locally, and deploy it to production. Let us get started.
What Is a Shopify App and Why Build One?
A Shopify app is a standalone web application that connects to a merchant’s store through Shopify’s APIs. It can read and write store data, add features to the admin, extend the checkout, or run background jobs.
There are three main app types:
| App Type | Best For | Distribution |
|---|---|---|
| Public app | Multiple merchants, App Store listing | Shopify App Store |
| Custom app | A single merchant or client | Direct install link |
| Plus/Partner app | Enterprise clients, advanced needs | Custom agreement |
Public apps earn revenue through the App Store. Custom apps serve one store and skip the review process. Most of this tutorial applies to both, with notes where they differ.
Prerequisites Before You Start
Before you write a line of code, set up your tools. You will need:
- A Shopify Partner account (free to create)
- A development store for testing
- Node.js 18 or later installed
- Basic knowledge of JavaScript or a backend language
- The Shopify CLI installed globally
Create your Partner account at the Shopify Partners portal. Inside, you can generate development stores that behave like real stores without billing.
Install the Shopify CLI with npm:
npm install -g @shopify/cli @shopify/app
Verify the install:
shopify version
The CLI scaffolds projects, runs local servers, and manages deployment. It is the backbone of modern Shopify app development.
Step 1: Scaffold Your App with the Shopify CLI
The fastest way to create a Shopify app is through the CLI template. Run the init command:
shopify app init
The CLI prompts you to name your app and pick a template. For most projects, choose the Remix template. It ships with authentication, session storage, and a working admin page out of the box.
After scaffolding, move into the project folder:
cd your-app-name
Install dependencies:
npm install
The generated structure looks like this:
| Folder/File | Purpose |
|---|---|
app/ |
Remix routes and React components |
shopify.app.toml |
App configuration and scopes |
prisma/ |
Database schema for session storage |
extensions/ |
Theme and checkout extensions |
.env |
API keys and secrets |
This layout keeps your frontend, backend, and config separate. You can swap the default SQLite database for PostgreSQL or MySQL later. For guidance on that, review these database optimization techniques.
Step 2: Understand App Authentication with OAuth
Every Shopify app authenticates through OAuth. When a merchant installs your app, Shopify redirects them to an authorization screen. Once they approve, Shopify returns an access token.
The Remix template handles this flow automatically. Still, you should understand what happens under the hood:
- The merchant clicks install.
- Shopify sends them to your app’s OAuth endpoint.
- Your app requests specific scopes.
- The merchant grants access.
- Shopify issues an access token tied to that store.
Define your scopes in shopify.app.toml:
[access_scopes] scopes = "read_products,write_products,read_orders"
Request only the scopes you need. Merchants and reviewers distrust apps that ask for broad permissions without reason. You can add scopes later through an update flow.
Session tokens power embedded apps inside the Shopify admin. The template stores these securely so you do not manage raw tokens by hand.
Step 3: Work with the Shopify API
Shopify offers two main APIs: REST and GraphQL. Shopify now recommends GraphQL for new apps because it returns exactly the fields you request and reduces round trips.
Here is a simple GraphQL query to fetch products:
query {
products(first: 10) {
edges {
node {
id
title
handle
}
}
}
}
In a Remix loader, you call the admin API like this:
export const loader = async ({ request }) => {
const { admin } = await authenticate.admin(request);
const response = await admin.graphql(`
query {
products(first: 10) {
edges { node { id title } }
}
}
`);
const data = await response.json();
return json(data);
};
As your app grows, raw API calls become a bottleneck. Learn to design high-performance Shopify API clients that batch requests and respect rate limits. For heavy workloads, the Bulk Operations API processes large datasets without hitting throttles.
Caching also matters. Repeated queries for the same data waste quota. Explore caching strategies for Shopify GraphQL to cut response times and API usage.
Step 4: Build Your App’s Interface
Embedded apps live inside the Shopify admin using App Bridge and Polaris. Polaris is Shopify’s design system, and it gives your app a native look.
The Remix template includes Polaris components. Here is a basic page:
import { Page, Card, Text } from "@shopify/polaris";
export default function Index() {
return (
<Page title="My App">
<Card>
<Text as="p">Welcome to your Shopify app.</Text>
</Card>
</Page>
);
}
Polaris handles spacing, buttons, tables, and forms with consistent styling. Merchants feel at home because your app matches the admin they already use.
If your app extends the storefront or checkout, you will work with different tools. The checkout flow uses Shopify checkout UI extensions for custom fields and content. Theme-facing features may rely on custom Shopify sections built with Liquid and JSON schema.
Step 5: Run and Test Locally
Start the development server with the CLI:
shopify app dev
The CLI creates a secure tunnel, updates your app URLs, and gives you an install link. Open the link to install the app on your development store.
Changes reload automatically. You can edit a route, save, and see the result in the admin within seconds.
Test with real scenarios. Create products, place test orders, and confirm your app responds correctly. For reliability, build a proper testing strategy early. These reliability testing practices for Shopify apps help you catch failures before merchants do.
Step 6: Handle Webhooks for Real-Time Events
Webhooks let your app react to store events like order creation, product updates, or app uninstalls. Instead of polling the API, Shopify pushes events to your endpoint.
Register a webhook in shopify.app.toml:
[[webhooks.subscriptions]] topics = ["orders/create"] uri = "/webhooks/orders/create"
Then handle the payload in a route:
export const action = async ({ request }) => {
const { topic, shop, payload } = await authenticate.webhook(request);
if (topic === "ORDERS_CREATE") {
// process the order
}
return new Response();
};
Always verify the webhook signature. The authenticate helper does this for you. Never trust an unverified payload.
Webhooks fail sometimes. Networks drop, servers restart, and payloads arrive out of order. To stay resilient, study how to build reliable Shopify webhook consumers and how Shopify webhooks fit an event-driven architecture.
For failed deliveries, a dead letter queue for Shopify webhooks captures messages you could not process so you can retry them safely. As volume grows, an event-driven architecture keeps your app responsive under load.
Step 7: Add Background Jobs and Queues
Many app tasks should not run in the request cycle. Syncing thousands of products or sending bulk notifications belongs in the background.
A queue system decouples slow work from user requests. The user gets an instant response while a worker processes the job.
Common queue patterns include:
| Pattern | Use Case |
|---|---|
| Simple job queue | One-off background tasks |
| Scheduled jobs | Periodic syncs and reports |
| Fan-out | Processing many items in parallel |
| Retry with backoff | Handling transient failures |
For a deeper look, see how to design queue infrastructure for Shopify apps and async architectures for Shopify operations. These patterns become essential when you move data between systems. If your app syncs with external platforms, review CRM synchronization strategies and ERP integration architecture with Shopify.
Step 8: Store and Map Your Data
Your app needs a database for sessions, settings, and cached store data. The template uses Prisma with SQLite by default. For production, switch to PostgreSQL.
When you pull data from Shopify into your own schema, mapping matters. Fields do not always align one to one. Thoughtful data mapping strategies prevent bugs and data loss during sync.
If your app transforms data at scale, you may build a pipeline. Learn how to construct Shopify ETL pipelines that extract, transform, and load store data reliably.
For storing custom structured data inside Shopify itself, metafields and metaobjects are powerful. This complete guide to Shopify metafields and metaobjects shows when to use each.
Step 9: Deploy Your Shopify App to Production
Now comes the moment to deploy your Shopify app. You need two things: a hosting platform and your app config pushed to Shopify.
Popular hosting options include:
| Platform | Strengths |
|---|---|
| Fly.io | Global edge, simple deploys |
| Railway | Fast setup, managed databases |
| Render | Free tier, auto deploys |
| AWS/GCP | Full control, enterprise scale |
First, build your app:
npm run build
Set your production environment variables on the host. These include your Shopify API key, API secret, app URL, and database connection string.
Then push your config to Shopify:
shopify app deploy
This command uploads your app configuration, extensions, and webhook subscriptions. Update your app URLs in the Partner Dashboard to point at your live domain instead of the local tunnel.
Run a smoke test. Install the app on a fresh development store from the production URL and confirm OAuth, pages, and webhooks all work.
Step 10: Scale and Harden Your App
Once merchants start installing, traffic grows. A single server can only do so much. Plan for scale before you hit limits.
Add caching layers across your Shopify ecosystem to reduce database and API pressure. Design for failure so one slow dependency does not take down the whole app. These guides on designing fault-tolerant Shopify integrations and preventing cascading failures cover the defensive patterns you need.
For global merchants, latency matters. A multi-region Shopify infrastructure serves users closer to home. And when you reach serious volume, learn how teams approach scaling Shopify apps to millions of requests using proven scalable integration patterns.
Self-healing systems reduce your on-call burden. Explore how to build self-healing Shopify integrations that recover from faults without manual intervention.
Submitting a Public App to the App Store
If you built a public app, you must pass Shopify’s review before listing. The review checks security, performance, billing, and merchant experience.
Prepare these items:
- A clear app listing with screenshots
- A privacy policy and GDPR webhooks
- Billing through the Shopify Billing API
- Fast load times and no console errors
- A demo video or test instructions for reviewers
Reviews can take days to weeks. Address feedback quickly and resubmit. Custom apps skip this entirely since they install directly on one store.
Common Mistakes to Avoid
New developers often stumble on the same issues. Watch out for these:
| Mistake | Fix |
|---|---|
| Requesting too many scopes | Ask only for what you use |
| Ignoring rate limits | Batch calls and add backoff |
| Skipping webhook verification | Always validate signatures |
| Blocking requests with slow work | Move tasks to a queue |
| No error handling on sync | Build retries and logging |
Avoiding these early saves hours of debugging and improves your chances of passing review.
Conclusion
You now know how to build a Shopify app from scratch, from scaffolding with the CLI to deploying in production. The core steps stay the same across projects: authenticate with OAuth, query the API, build a Polaris interface, handle webhooks, and host your code reliably.
The hard part is not the first install. It is building an app that stays fast and resilient as merchants pile on. Invest in queues, caching, and testing early, and your app will grow without breaking.
Start small, ship a focused feature, and iterate. The Shopify ecosystem rewards apps that solve real merchant problems with care.
Frequently Asked Questions
How long does it take to build a Shopify app?
A simple app with basic features takes a few days to a couple of weeks. A full public app with billing, extensions, and App Store review can take one to three months depending on complexity.
Do I need to know a specific programming language?
No. Shopify supports any language that can serve HTTP. The official templates use Node.js with Remix, but you can build in Ruby, Python, PHP, or others using the REST or GraphQL APIs.
Is a Shopify Partner account free?
Yes. Creating a Partner account and development stores costs nothing. You only pay for your own hosting and any paid tools you choose to use.
Should I use REST or GraphQL?
Use GraphQL for new apps. Shopify recommends it because you request only the fields you need, which reduces data transfer and round trips. Some legacy endpoints still use REST.
What is the difference between a public and custom app?
A public app lists on the App Store and serves many merchants after passing review. A custom app installs on a single store through a direct link and skips the review process.
How do I test my app before going live?
Use a development store with the Shopify CLI dev command. Create test products and orders, trigger webhooks, and confirm every flow works before you deploy to production.
Can I update my app’s permissions later?
Yes. You can add or change access scopes after launch. Merchants will see a prompt to approve the new permissions the next time they open your app.
