Shopify App Proxy with Remix (Notes)

Hello all,

I found the app proxy docs to be quite confusing so I thought I would detail the things I did to set up an app proxy page with a fresh remix project. (especially the steps that weren’t obvious). I’m not completely sure that all these steps are totally necessary but they’re the steps I took to get it working.

  1. Add proxy to toml:
[app_proxy]
url = "<domain or cloudflare tunnel>"
subpath = "<whatever>"
prefix = "a/apps/tools"
  1. Setup Cloudflare tunnel in Cloudflare zero trust dashboard, connect, run tunnel (just look up how to run Cloudflare tunnel if unfamiliar).

  2. Try your _index page on a test store. Go to domain .com/<<prefix/<<subpath and see if it shows up. If your styling isn’t showing up, you may need to remove ?url from your css routes/imports.

**A big issue I had was that I had to specify that the routes had to start with /<<prefix/<<subpath. I fixed this by adding a remix.config.js file and adding the link prefix as a base. This is what the file looked like:

/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
    base: '/<<prefix/<<subpath',
    ignoredRouteFiles: ['**/.*'],
    serverModuleFormat: 'cjs',
};
  1. Next, I had to figure out how to make http requests. This was by far the most frustrating part. There’s a specific flow that Shopify wants you to follow and they have docs about it but I found them quite confusing so I will explain what I did here.
    First, you must add a shopify.server.js file. This was mine:
import "@shopify/shopify-app-remix/adapters/node";
import {
    ApiVersion,
    shopifyApp,
} from "@shopify/shopify-app-remix/server";
import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma";
import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

const shopify = shopifyApp({
    apiKey: process.env.SHOPIFY_API_KEY,
    apiSecretKey: process.env.SHOPIFY_API_SECRET || "",
    apiVersion: ApiVersion.October24,
    scopes: process.env.SCOPES?.split(","),
    appUrl: process.env.SHOPIFY_APP_URL || "",
    authPathPrefix: "/auth",
    sessionStorage: new PrismaSessionStorage(prisma),
});

export default shopify;
export const authenticate = shopify.authenticate;
export const sessionStorage = shopify.sessionStorage;

It’s very important that you install everything and have your Prisma database correctly connected. Also you must add a Session table to your prisma database otherwise PrismaSessionStorage won’t work. Here’s the Session table I used:

model Session {
  id          String    @id
  shop        String?
  state       String?
  isOnline    Boolean?
  scope       String?
  expires     DateTime?
  accessToken String?
  createdAt   DateTime  @default(now())
  updatedAt   DateTime  @updatedAt
}

From there, you can set up your request. I just made a button with method=“post” and action=“/<<prefix/<<subpath/login”. Note: you can’t make a request to /<<prefix/<<subpath because it will try to make the request to your /root file instead of your _index file.

In your action function, add await authenticate.public.appProxy(request); just so Shopify will let you make an http request. If I’m not mistaken, Shopify uses params in the url to authenticate a request so that’s why you may see Shopify trying to navigate to a weird url. The params will be in this format:

    const url = new URL(request.url);
    const shop = url.searchParams.get("shop");
    const timestamp = url.searchParams.get("timestamp");
    const signature = url.searchParams.get("signature");

From there you can make whatever requests you like.

I apologize if any of this information is incorrect, I just cared to recount the process I used. Perhaps someone will find it useful, I know I will at least go back and refer to this. Cheers!

1 Like