All Tutorials

Build a Shopify app with Rails, React, and App Bridge

All Tutorials

Build a Shopify app with Rails, React, and App Bridge

Build a Shopify app with Rails, React, and App Bridge

This guide will show you how to build a Shopify app with Rails 6, React, and App Bridge authentication. The app uses session token-based authentication to protect requests between the frontend and backend. When you've completed this tutorial, any requests made to /graphql will be authenticated with an Authorization: Bearer <session-token> header.

Requirements

Your app must meet the following requirements to complete this tutorial:

You can view the code for the sample app on GitHub.

Create a backend using Rails

  1. Run the following command in your working directory:

    $ rails new <your-app-name> --webpack=react
  2. In your newly created app, open the Gemfile and add the following dependencies:

    gem 'dotenv-rails'
    gem 'graphql'
    gem 'react-rails'
    gem 'shopify_app'    # Version 14.0.0 is used in the sample app
  3. Run the following command to install the gems:

    $ bundle install
  4. Run the following command to generate an embedded app using the Shopify App gem:

    $ rails generate shopify_app --with-session-token
  5. Run the following installer to create a GraphQL backend:

    $ rails generate graphql:install
  6. Run any outstanding database migrations:

    $ rails db:migrate

Create a frontend using React

  1. In the root folder of your app, run the following commands to install React using webpacker:

    $ rails webpacker:install
    $ rails webpacker:install:react
    $ rails generate react:install
  2. Add the following dependencies to your package.json file:

    $ yarn add \
         @apollo/client \
         graphql \
         @shopify/app-bridge-utils@1.26.0 \
         @shopify/polaris \
  3. Generate a default App.js component:

    $ rails generate react:component App
  4. Overwrite app/views/home/index.html.erb to match the following code:

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <link rel="stylesheet" href="https://unpkg.com/@shopify/polaris@4.22.0/styles.min.css"/>
      </head>
      <body>
        <%= react_component("App") %>
      </body>
    </html>

Make authenticated requests using App Bridge

Configure the backend

  1. Update GraphqlController in /app/controllers/graphql_controller.rb to inherit AuthenticatedController:

    class GraphqlController < AuthenticatedController
  2. Add an expected message to the test_field method of app/grapqhl/types/query_type.rb:

    def test_field
      "Congratulations! Your requests are now authorized using App Bridge Authentication."
    end

Configure the frontend

  1. In app/javascript/components/App.js, import authenticatedFetch from @shopify/app-bridge-utils:

    import { authenticatedFetch } from '@shopify/app-bridge-utils';
  2. In app/javascript/components/App.js, create an Apollo Client and provide authenticatedFetch as the fetch method:

    import {
      ApolloClient,
      ApolloProvider,
      HttpLink,
      InMemoryCache,
    } from '@apollo/client';
    import { AppProvider, EmptyState, Page } from '@shopify/polaris';
    import { authenticatedFetch } from '@shopify/app-bridge-utils';
    
    import enTranslations from '@shopify/polaris/locales/en.json';
    import React from 'react';
    
    export default function App() {
      const client = new ApolloClient({
        link: new HttpLink({
          credentials: 'same-origin',
          fetch: authenticatedFetch(window.app), // created in shopify_app.js
          uri: '/graphql'
        }),
        cache: new InMemoryCache()
      });
    
      return (
        <AppProvider i18n={enTranslations}>
          <ApolloProvider client={client}>
            <Page>
              <EmptyState>
                ...
              </EmptyState>
            </Page>
          </ApolloProvider>
        </AppProvider>
      );
    }
  3. Create a TestData component to query the /graphql endpoint of the app:

    import { gql, useQuery } from '@apollo/client';
    
    import React from 'react';
    
    const TEST_QUERY = gql`query { testField }`;
    
    export default function TestData() {
      const {loading, error, data} = useQuery(TEST_QUERY);
    
      if (loading) {
        return (
          <div>Loading</div>
        );
      } else if (error) {
        return (
          <div>Something went wrong!</div>
        );
      } else {
        return (
          <p>{data.testField}</p>
        );
      }
    }
  4. Import the TestData in the App component:

    import TestData from './TestData'
    
    export default function App() {
    
     return (
        <AppProvider i18n={enTranslations}>
          <ApolloProvider client={client}>
            <Page>
              <EmptyState>
                <TestData/>    # Add the TestData component here
              </EmptyState>
            </Page>
          </ApolloProvider>
        </AppProvider>
      );
    }
  5. Start the app:

    $ rails s

Resources

Sample app using Rails and React