Skip to main content

Shopify App package for Remix

The @shopify/shopify-app-remix package enables Remix apps to authenticate with Shopify and make API calls. It uses App Bridge to enable apps to embed themselves in the Shopify Admin.

In this page we'll go over the main components you need to integrate an app with Shopify.


The quickest way to create a new app is using the Shopify CLI. You can use your preferred package manager for that.

Check out the getting started guide, or the app template for a complete example.

Create an app

npm init @shopify/app@latest

If you're not using the CLI, then you can use the examples in this page to set up an existing app to use this package. Start by installing it using your preferred package manager.

Install package

npm i --save @shopify/shopify-app-remix

Using the shopifyApp function, you can create an object that enables your app's backend to authenticate requests coming from Shopify, and interacting with Shopify APIs.

These functions make it easy for your app stays up to date, benefitting from the current best practices and security updates.

Caution

When running on a node environment, you'll also need to import the node adapter, as per the example. This will ensure your app is using the appropriate implementation of the Web fetch and crypto APIs.

Configure ShopifyApp

/app/shopify.server.ts

import '@shopify/shopify-app-remix/server/adapters/node';
import {
LATEST_API_VERSION,
shopifyApp,
} from '@shopify/shopify-app-remix/server';

const shopify = shopifyApp({
apiKey: process.env.SHOPIFY_API_KEY!,
apiSecretKey: process.env.SHOPIFY_API_SECRET!,
appUrl: process.env.SHOPIFY_APP_URL!,
scopes: ['read_products'],
apiVersion: LATEST_API_VERSION,
});
export default shopify;

Anchor to headersResponse headers

When loading inside the Shopify Admin, your app will need to add the required Content-Security-Policy header directives, as per our documentation. To do that, this package provides the shopify.addDocumentResponseHeaders method.

You should return these headers from any endpoint that renders HTML in your app. Most likely you'll want to add this to every HTML response by updating the entry.server.tsx file:

Add required headers

/app/entry.server.tsx

import shopify from './shopify.server';

export default function handleRequest(
request: Request,
responseStatusCode: number,
responseHeaders: Headers,
remixContext: EntryContext,
) {
shopify.addDocumentResponseHeaders(request, responseHeaders);

// ..etc
}

Anchor to boundariesError boundaries

The OAuth process can't happen inside the admin iframe, and this package is capable of detecting that scenario and properly redirecting using the Remix ErrorBoundary export to set the correct headers for App Bridge.

Use the abstractions provided by this package in your authenticated routes, to automatically set up the error and headers boundaries to redirect outside the iframe when needed.

Tip

You can also add this to a Remix layout if you want to authenticate more than one route, but make sure to call the Shopify boundary methods whenever you need to add your own exports.

Configure header boundaries

/app/routes/**/*.tsx

import {boundary} from '@shopify/shopify-app-remix/server';

export function ErrorBoundary() {
return boundary.error(useRouteError());
}

export const headers = (headersArgs) => {
return boundary.headers(headersArgs);
};

Tip

This is only applicable to non-embedded apps or legacy embedded apps that are not using the new embedded app authorization strategy for OAuth and installation flow. If you're building an embedded app, we strongly recommend using the new embedded app authorization strategy

To install an app or refresh tokens, you'll need to set up an OAuth route. To do that, set up a splat route that calls authenticate.admin.

When that function is called, the package will start the OAuth process, and handle the callback from Shopify after it completes.

The default route is /app/routes/auth/$.tsx, but you can configure this route using the authPathPrefix option.

Add OAuth route

/app/routes/auth/$.tsx

import {LoaderFunctionArgs} from '@remix-run/node';

import shopify from '~/shopify.server';

export async function loader({request}: LoaderFunctionArgs) {
await shopify.authenticate.admin(request);

// App logic goes here

return null;
}

Anchor to embedded-auth-strategyNew embedded app authorization strategy

Tip

This is available for embedded apps that are using Shopify managed installation. If you're building an embedded app, we strongly recommend using this feature that utilizes Shopify managed install with token exchange.

We have introduced a new authorization and installation strategy for embedded apps that eliminates the redirects that were previously necessary. It replaces the legacy authorization Code install and grant flow.

It takes advantage of Shopify managed installation to handle automatic app installations and scope updates, while using token exchange to get an access token for the logged-in user.

If you wish to learn about scopes management and APIs, please read through Manage access scopes

Note

Newly created Remix apps from the template after February 1st 2024 has this feature enabled by default.

  1. Enable Shopify managed installation by configuring your scopes through the Shopify CLI.
  2. Enable the future flag unstable_newEmbeddedAuthStrategy in your app's server configuration file.
  3. Enjoy no-redirect OAuth flow, and app installation process.

Enabling the new embedded auth strategy

/app/shopify.server.ts

// ... imports
const shopify = shopifyApp({
// .. and the rest of the config
isEmbeddedApp: true,
future: {
unstable_newEmbeddedAuthStrategy: true,
},
)};

// ... exports

In order to use all of the features from App Bridge, you'll need to use the AppProvider component in your app's routes.

This component will set up App Bridge and Polaris so you can integrate your app into the Shopify Admin, and it helps us ensure your app stays up to date with Shopify requirements.

To do this pass the process.env.SHOPIFY_API_KEY to the frontend via the loader.

Add AppProvider

/app/root.tsx

import {LoaderFunctionArgs} from '@remix-run/node';
import {AppProvider} from '@shopify/shopify-app-remix/react';

import shopify from '~/shopify.server';

export async function loader({request}: LoaderFunctionArgs) {
await shopify.authenticate.admin(request);

return json({
apiKey: process.env.SHOPIFY_API_KEY,
});
}

export default function App() {
const {apiKey} = useLoaderData<typeof loader>();

return (
<html>
<head>
<Meta />
<Links />
</head>
<body>
<AppProvider apiKey={apiKey} isEmbeddedApp>
<Outlet />
</AppProvider>
</body>
</html>
);
}