Skip to content

Shopify/ai-agent-partner-sales-channel-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Your Shopify Sales Channel Template - React Router

This is a template for building your sales channel app Shopify sales channel using React Router. It was forked from the Shopify React Router app template with some concerns unique to our usecase.

Visit the shopify.dev documentation for more details on the React Router app package.

Quick start

Update Shopify app config

The first thing you should do when setting up your Sales Channel app is update the placeholder values in the Shopify config toml. You must set the client_id to match the client ID in your shopify developer dashboard, and your application_url and redirect_urls to match the URLs for your production application.

To learn more about working with app configurations, see the developer documentation.

Local Development

pnpm run dev

Press P to open the URL to your app. Once you click install, you can start development.

Local development is powered by the Shopify CLI. It logs into your account, connects to an app, provides environment variables, updates remote config, creates a tunnel and provides commands to generate extensions.

Partner specific setup

NOTE We have added testcases that fail if any of these steps are missed. You can run pnpm run test to validate that these placeholders have been correctly replaced.

For in depth documentation on how to integrate with Shopify refer to PARTNER_DOCS.md

Your app config

Getting up and running with this app template requires a few modifications. First up you must update the app config with your platform specific text and URLs.

export interface PartnerConfig {
  name: string;
  logo: string;
  supportUrl: string;
  docsUrl: string;
  termsOfServiceUrl: string;
  publicApiKey: string;
  afterAuthRedirectUrl: string;
  isStagingEnv?: boolean;
}

Once this config file is updated your app homepage should update to show copy and links relevant to your platform. You should feel free to update this template as you wish, but a few things should remain available on this page.

  1. A link to your terms of service
  2. The ability to manage what products are published to your sales channel (see ProductPublishingCard)
  3. Relevant support and documentation links

Links back to the merchants project

Once your config is setup, you need to teach the app how to get your external links. There are two methods set up on the PartnerProjectLinks class getProjectFrontendUrl and getProjectManagementUrl you may fill in these two stub methods with a utility to fetch your relevant project links, or completely replace the class with your own implementation, just ensure the urls are returned properly in the loader in app

Authenticating and querying data

To authenticate and query data you can use the shopify const that is exported from /app/shopify.server.ts:

export async function loader({ request }) {
  const { admin } = await shopify.authenticate.admin(request);

  const response = await admin.graphql(`
    {
      products(first: 25) {
        nodes {
          title
          description
        }
      }
    }`);

  const {
    data: {
      products: { nodes },
    },
  } = await response.json();

  return nodes;
}

This template comes pre-configured with examples of:

  1. Setting up your Shopify app in /app/shopify.server.ts.
  2. Responding to webhooks. Please see /app/routes/webhooks.tsx.

Please read the documentation for @shopify/shopify-app-react-router to see what other API's are available.

Shopify Dev MCP

This template is configured with the Shopify Dev MCP. This instructs Cursor, GitHub Copilot and Claude Code and Google Gemini CLI to use the Shopify Dev MCP.

For more information on the Shopify Dev MCP please read the documentation.

Deployment

Application Storage

This template uses Drizzle ORM to store session data, by default using an SQLite database. The database is defined as a schema in /app/utils/schema.server.ts.

This use of SQLite works in production if your app runs as a single instance. The database that works best for you depends on the data your app needs and how it is queried.

The database is not in source control and therefore will not be persisted between deploys. This is fine for our usecase, it simply means that a fresh session will need to be created between deploys. If you have a need to use a persisted database, you can use any for which we have a SessionStorage adapter package.

Build

Build the app by running the command below with the package manager of your choice:

Using yarn:

yarn build

Using npm:

npm run build

Using pnpm:

pnpm run build

Hosting

When you're ready to set up your app in production, you can follow our deployment documentation to host it externally.

Manual deployment guide: This resource provides general guidance on the requirements of deployment including environment variables, secrets, and persistent data.

When you reach the step for setting up environment variables, you also need to set the variable NODE_ENV=production.

Gotchas / Troubleshooting

Database tables don't exist

If you get an error like:

The table `main.Session` does not exist in the current database.

Create the database for Drizzle. Run the setup script in package.json using npm, yarn or pnpm.

Navigating/redirecting breaks an embedded app

Embedded apps must maintain the user session, which can be tricky inside an iFrame. To avoid issues:

  1. Use Link from react-router or @shopify/polaris. Do not use <a>.
  2. Use redirect returned from authenticate.admin. Do not use redirect from react-router
  3. Use useSubmit from react-router.

Webhooks: shop-specific webhook subscriptions aren't updated

If you are registering webhooks in the afterAuth hook, using shopify.registerWebhooks, you may find that your subscriptions aren't being updated.

Instead of using the afterAuth hook declare app-specific webhooks in the shopify.app.toml file. This approach is easier since Shopify will automatically sync changes every time you run deploy (e.g: npm run deploy). Please read these guides to understand more:

  1. app-specific vs shop-specific webhooks
  2. Create a subscription tutorial

If you do need shop-specific webhooks, keep in mind that the package calls afterAuth in 2 scenarios:

  • After installing the app
  • When an access token expires

During normal development, the app won't need to re-authenticate most of the time, so shop-specific subscriptions aren't updated. To force your app to update the subscriptions, uninstall and reinstall the app. Revisiting the app will call the afterAuth hook.

Webhooks: Admin created webhook failing HMAC validation

Webhooks subscriptions created in the Shopify admin will fail HMAC validation. This is because the webhook payload is not signed with your app's secret key.

The recommended solution is to use app-specific webhooks defined in your toml file instead. Test your webhooks by triggering events manually in the Shopify admin(e.g. Updating the product title to trigger a PRODUCTS_UPDATE).

Webhooks: Admin object undefined on webhook events triggered by the CLI

When you trigger a webhook event using the Shopify CLI, the admin object will be undefined. This is because the CLI triggers an event with a valid, but non-existent, shop. The admin object is only available when the webhook is triggered by a shop that has installed the app. This is expected.

Webhooks triggered by the CLI are intended for initial experimentation testing of your webhook configuration. For more information on how to test your webhooks, see the Shopify CLI documentation.

Incorrect GraphQL Hints

By default the graphql.vscode-graphql extension for will assume that GraphQL queries or mutations are for the Shopify Admin API. This is a sensible default, but it may not be true if:

  1. You use another Shopify API such as the storefront API.
  2. You use a third party GraphQL API.

If so, please update .graphqlrc.ts.

Using Defer & await for streaming responses

By default the CLI uses a cloudflare tunnel. Unfortunately cloudflare tunnels wait for the Response stream to finish, then sends one chunk. This will not affect production.

To test streaming using await during local development we recommend localhost based development.

"nbf" claim timestamp check failed

This is because a JWT token is expired. If you are consistently getting this error, it could be that the clock on your machine is not in sync with the server. To fix this ensure you have enabled "Set time and date automatically" in the "Date and Time" settings on your computer.

Resources

React Router:

Shopify:

Internationalization:

About

The Sales Channel template for AI Agent IDE platforms integrating with Shopify

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors