Skip to content
Docs

How to deploy a Shopify App to Vercel

Deploy the official Shopify CLI React Router app template to Vercel with the @vercel/react-router preset and Postgres session storage.

Matt LewisPartner Solutions

Shopify apps built with the Shopify CLI React Router template are server-rendered web apps that authenticate merchants over OAuth and render inside the Shopify admin. Because the template is a standard React Router app, Vercel detects the framework and deploys it with zero configuration when you enable the @vercel/react-router preset.

This guide walks through deploying the template to Vercel, replacing its local SQLite session storage with Postgres, and pointing your Shopify configuration at the live URL.

Copy link to headingOverview

You'll learn how to:

  • Gather the Shopify configuration values your deployment needs
  • Enable the Vercel preset for a React Router app
  • Replace the template's local SQLite session storage with Postgres
  • Deploy to Vercel with the correct environment variables
  • Point your Shopify app configuration at the live Vercel URL and verify the installation

Copy link to headingPrerequisites

Before you begin, make sure you have:

  • A Vercel account
  • The Shopify CLI installed and authenticated to your store
  • A Shopify app scaffolded with the Shopify CLI React Router template. You can scaffold a new app by running shopify app init

Copy link to headingQuick start with an AI coding agent

If you're working with an AI coding agent like Claude Code or Cursor, you can use this prompt to have it help you with building your Shopify app:

Agent Prompt

I want to build a Shopify app that will be deployed to Vercel. Build the app with the Shopify CLI React Router template: https://github.com/Shopify/shopify-app-template-react-router. Then fetch and follow this Vercel knowledge base guide step by step: https://vercel.com/kb/guide/deploy-shopify-app-to-vercel. When searching for additional information, use the 'site:' search operator to scope your searches to vercel.com and shopify.dev. Ask me to complete any interactive or authenticated steps. If anything is ambiguous while you work on this, ask me instead of guessing.

Copy link to headingHow it works

The template is a standard React Router app with Shopify's OAuth, session storage, and embedded-app scaffolding on top. React Router deploys to Vercel with zero configuration, so there is no Dockerfile, container port, or secret manager to set up.

The @vercel/react-router preset splits the app bundle across Vercel Functions and enables function-level configuration.

Only two things need attention, both Shopify-specific:

  1. Feeding the production URL back into both Vercel and Shopify
  2. Moving the default SQLite session store to a database that persists across deployments

Copy link to headingSteps

Link your codebase with a new or existing Vercel project:

Terminal
vercel link

Copy link to heading2. Gather your Shopify configuration

Your deployed app needs the following environment variables:

VariableDescription
SHOPIFY_API_KEYYour app's client ID from the Shopify app configuration
SHOPIFY_API_SECRETYour app's client secret, used to validate requests from Shopify
SCOPESComma-separated list of access scopes the app requests, for example write_products

From your project root, print the current values:

Terminal
shopify app env show

These values live alongside shopify.app.toml.

If that file doesn't exist yet, link the Shopify project first:

Terminal
shopify app config link

Add each variable to your Vercel project with the Vercel CLI:

Terminal
vercel env add

Copy link to heading3. Enable the Vercel preset

Install the Vercel preset:

Terminal
pnpm install @vercel/react-router

Create react-router.config.ts in your project root:

react-router.config.ts
import { vercelPreset } from '@vercel/react-router/vite';
import type { Config } from '@react-router/dev/config';
export default {
ssr: true,
presets: [vercelPreset()],
} satisfies Config;

Copy link to heading4. Swap SQLite for Postgres

The template's default Prisma SQLite store doesn't persist reliably in a serverless environment, so session data would be lost between deployments. Use an existing Postgres database or provision one through the Vercel Marketplace.

For example, to install Prisma Postgres:

Terminal
vercel install prisma

vercel install is an alias for vercel integration add. After provisioning the resource, the command connects it to your linked project and runs vercel env pull, so DATABASE_URL is available locally without any extra steps.

Update the datasource in prisma/schema.prisma:

prisma/schema.prisma
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

Generate the Prisma client:

Terminal
prisma generate

Then apply the schema:

Terminal
prisma migrate deploy

If the project doesn't have migration history, push the schema directly instead:

Terminal
prisma db push

Copy link to heading5. Create a base URL resolver

The template references SHOPIFY_APP_URL in multiple places. Vercel exposes system environment variables such as VERCEL_PROJECT_PRODUCTION_URL, so you can resolve the app URL automatically instead of hardcoding it per environment.

Create app/utils/app-url.ts:

app/utils/app-url.ts
export function getAppUrl(): string {
const explicit = process.env.SHOPIFY_APP_URL;
if (explicit) return explicit.replace(/\/$/, "");
const vercel = process.env.VERCEL_PROJECT_PRODUCTION_URL;
if (vercel) return `https://${vercel}`;
return "http://localhost:3000";
}

Use it in app/shopify.server.ts:

app/shopify.server.ts
import { getAppUrl } from "./utils/app-url";
const shopify = shopifyApp({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
apiVersion: ApiVersion.July26,
scopes: process.env.SCOPES?.split(","),
appUrl: getAppUrl(),
// your existing code
});

Use it in vite.config.ts:

vite.config.ts
import { reactRouter } from "@react-router/dev/vite";
import { defineConfig, type UserConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import { getAppUrl } from "./app/utils/app-url";
// Related: https://github.com/remix-run/remix/issues/2835#issuecomment-1144102176
// Replace the HOST env var with SHOPIFY_APP_URL so that it doesn't break the Vite server.
// The CLI will eventually stop passing in HOST,
// so we can remove this workaround after the next major release.
if (
process.env.HOST &&
(!process.env.SHOPIFY_APP_URL ||
process.env.SHOPIFY_APP_URL === process.env.HOST)
) {
process.env.SHOPIFY_APP_URL = process.env.HOST;
delete process.env.HOST;
}
const host = new URL(getAppUrl()).hostname;
// your existing code

Copy link to heading6. Update your build command

Update the build script in package.json to generate the Prisma client:

package.json
"build": "prisma generate && react-router build"

Copy link to heading7. Deploy to Vercel

Run the following command from the project root:

Terminal
vercel deploy --prod

Vercel detects React Router and builds the application without additional configuration.

Copy link to heading8. Finish the Shopify configuration

In shopify.app.toml, set application_url to your Vercel production URL and update the redirect URLs:

shopify.app.toml
application_url = "https://<your-app-url>"
[auth]
redirect_urls = ["https://<your-app-url>/auth/callback"]

Deploy the Shopify app configuration:

Terminal
shopify app deploy

Install the app on a development store and confirm that:

  • The OAuth flow completes successfully
  • The app loads embedded inside the Shopify admin

Copy link to headingTroubleshooting

Copy link to headingThe OAuth flow fails or redirects to an error page

Shopify validates the redirect against your app configuration. Confirm that application_url and redirect_urls in shopify.app.toml match your Vercel production URL exactly, including the /auth/callback path, and run shopify app deploy again after any change.

Copy link to headingPrisma client errors during build or at runtime

The Prisma client must be generated as part of the Vercel build. Confirm your build script runs prisma generate before react-router build, and that you applied the schema to your Postgres database with prisma migrate deploy or prisma db push.

Copy link to headingThe app fails to authenticate after deploying

A mismatch between the credentials in Vercel and Shopify causes authentication to fail silently. Run shopify app env show and confirm that SHOPIFY_API_KEY, SHOPIFY_API_SECRET, and SCOPES in your Vercel project match those values for every environment.

Copy link to headingNext steps