I’m aware of the existence of other posts with the same topic, but our team needs to get rid of this blocker ASAP.
Our app:
- Is embedded
- Has been scaffolded using the remix template
- Is using the latest version of
@shopify/app-bridge-react
:^4.1.6
- Has enabled
isEmbeddedApp: true
withinshopify.server.ts
as well as inshopify.app.production.toml
andshopify.app.development.toml
configuration files. - Is properly wrapped using
AppProvider
from@shopify/shopify-app-remix
. Also latest version - Generates session tokens (screenshot attached)
package.json
"dependencies": {
"@prisma/client": "^6.4.1",
"@remix-run/dev": "^2.16.0",
"@remix-run/fs-routes": "^2.16.0",
"@remix-run/node": "^2.16.0",
"@remix-run/react": "^2.16.0",
"@remix-run/serve": "^2.16.0",
"@shopify/app-bridge-react": "^4.1.6",
"@shopify/polaris": "^13.9.2",
"@shopify/polaris-icons": "^9.3.0",
"@shopify/shopify-api": "^11.9.0",
"@shopify/shopify-app-remix": "^3.7.2",
"@shopify/shopify-app-session-storage-prisma": "^6.0.2",
"isbot": "^4.4.0",
"prisma": "^6.2.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"remix-utils": "^7.5.0",
"vite-tsconfig-paths": "^5.0.1"
},
shopify.server.ts
import '@shopify/shopify-app-remix/adapters/node';
import {
ApiVersion,
AppDistribution,
shopifyApp,
} from '@shopify/shopify-app-remix/server';
import { PrismaSessionStorage } from '@shopify/shopify-app-session-storage-prisma';
import { WEBHOOK_HANDLERS } from 'constants/webhooks';
import prisma from './db.server';
const shopify = shopifyApp({
apiKey: process.env.SHOPIFY_API_KEY,
apiSecretKey: process.env.SHOPIFY_API_SECRET || '',
apiVersion: ApiVersion.October24,
appUrl: process.env.SHOPIFY_APP_URL || '',
authPathPrefix: '/auth',
distribution: AppDistribution.AppStore,
future: {
unstable_newEmbeddedAuthStrategy: true,
removeRest: true,
},
isEmbeddedApp: true,
scopes: process.env.SCOPES?.split(','),
sessionStorage: new PrismaSessionStorage(prisma),
webhooks: WEBHOOK_HANDLERS,
...(process.env.SHOP_CUSTOM_DOMAIN
? { customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN] }
: {}),
});
export default shopify;
export const apiVersion = ApiVersion.October24;
export const addDocumentResponseHeaders = shopify.addDocumentResponseHeaders;
export const authenticate = shopify.authenticate;
export const unauthenticated = shopify.unauthenticated;
export const login = shopify.login;
export const registerWebhooks = shopify.registerWebhooks;
export const sessionStorage = shopify.sessionStorage;
app/routes/app.tsx
import type { HeadersFunction, LoaderFunctionArgs } from '@remix-run/node';
import { Link, Outlet, useLoaderData, useRouteError } from '@remix-run/react';
import { NavMenu } from '@shopify/app-bridge-react';
import polarisStyles from '@shopify/polaris/build/esm/styles.css?url';
import polarisTranslations from '@shopify/polaris/locales/en.json';
import { AppProvider } from '@shopify/shopify-app-remix/react';
import { boundary } from '@shopify/shopify-app-remix/server';
import { authenticate } from '~/shopify.server';
import { Atlas } from '~/utils';
export const links = () => [{ rel: 'stylesheet', href: polarisStyles }];
export const loader = async ({ request }: LoaderFunctionArgs) => {
await authenticate.admin(request);
return {
apiKey: process.env.SHOPIFY_API_KEY || '',
polarisTranslations,
};
};
export default function App() {
const { apiKey, polarisTranslations } = useLoaderData<typeof loader>();
return (
<AppProvider isEmbeddedApp apiKey={apiKey} i18n={polarisTranslations}>
<NavMenu>
<Link to={Atlas.urls.Home} rel="home">
Home
</Link>
<Link to={Atlas.urls.SellingPlan.Create}>Create Selling Plan</Link>
</NavMenu>
<Outlet />
</AppProvider>
);
}
// Shopify needs Remix to catch some thrown responses, so that their headers are included in the response.
export function ErrorBoundary() {
return boundary.error(useRouteError());
}
export const headers: HeadersFunction = (headersArgs) => {
return boundary.headers(headersArgs);
};
schema.prisma
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Session {
id String @id
shop String
state String
isOnline Boolean @default(false)
scope String?
expires DateTime?
accessToken String
userId BigInt?
firstName String?
lastName String?
email String?
accountOwner Boolean @default(false)
locale String?
collaborator Boolean? @default(false)
emailVerified Boolean? @default(false)
}
We kindly ask for assistance on this matter.
Regards,