top of page
Get a Demo
Get a Free Quote

Create a Shopify App for Product Vendors & Admin options using ReactJS & Polaris

Apr 18

3 min read

0

3

0



🧱 Requirements



  • Shopify Partner Account

  • Development store

  • Shopify CLI

  • Frontend: React.js with App Bridge + Polaris

  • App Hosted externally (e.g., Vercel/Netlify)

  • Authenticated using Shopify App Bridge + JWT token



✅ Step-by-Step Guide: Shopify Embedded App in React Only



🧩 Step 1: Create React App


npx create-react-app vendor-app
cd vendor-app




📦 Step 2: Install Dependencies


npm install @shopify/app-bridge-react @shopify/polaris @shopify/app-bridge @shopify/app-bridge-utils

Also install @shopify/polaris CSS:

npm install @shopify/polaris-tokens


⚙️ Step 3: Setup App Bridge Provider



In src/index.js:

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import {
  AppBridgeProvider
} from "@shopify/app-bridge-react";
import {
  Provider as PolarisProvider
} from "@shopify/polaris";
import "@shopify/polaris/build/esm/styles.css";

const config = {
  apiKey: process.env.REACT_APP_SHOPIFY_API_KEY, // from Shopify Partner dashboard
  host: new URLSearchParams(window.location.search).get("host"),
  forceRedirect: true,
};

ReactDOM.render(
  <PolarisProvider>
    <AppBridgeProvider config={config}>
      <App />
    </AppBridgeProvider>
  </PolarisProvider>,
  document.getElementById("root")
);




🗂️ Step 4: Add Navigation (Admin Menu)



In src/App.js:

import {
  NavigationMenu
} from "@shopify/app-bridge-react";
import { BrowserRouter as Router, Routes, Route, Link } from "react-router-dom";
import Vendors from "./pages/Vendors";
import VendorDetail from "./pages/VendorDetail";

function App() {
  return (
    <>
      <NavigationMenu
        navigationLinks={[
          {
            label: "Vendors",
            destination: "/vendors",
          },
        ]}
      />
      <Router>
        <Routes>
          <Route path="/vendors" element={<Vendors />} />
          <Route path="/vendors/:name" element={<VendorDetail />} />
        </Routes>
      </Router>
    </>
  );
}

export default App;


🗂️ Step 5: 

/vendors

 Page



src/pages/Vendors.js

import { Page, Card, ResourceList, Text } from "@shopify/polaris";
import { useEffect, useState } from "react";
import { Link } from "react-router-dom";

const Vendors = () => {
  const [vendors, setVendors] = useState([]);

  useEffect(() => {
    const fetchProducts = async () => {
      const token = window.sessionToken; // get from App Bridge utils
      const res = await fetch("/admin/api/2024-01/products.json", {
        headers: {
          "X-Shopify-Access-Token": token,
        },
      });
      const data = await res.json();

      const vendorMap = {};
      data.products.forEach((p) => {
        const vendor = p?.vendor || p?.metafields?.find(mf => mf.key === "vendor_name")?.value;
        if (vendor) vendorMap[vendor] = true;
      });

      setVendors(Object.keys(vendorMap).map((v) => ({ name: v })));
    };

    fetchProducts();
  }, []);

  return (
    <Page title="Vendors">
      <Card>
        <ResourceList
          items={vendors}
          renderItem={(vendor) => (
            <ResourceList.Item
              id={vendor.name}
              accessibilityLabel={`View ${vendor.name}`}
            >
              <Link to={`/vendors/${vendor.name}`}>{vendor.name}</Link>
            </ResourceList.Item>
          )}
        />
      </Card>
    </Page>
  );
};

export default Vendors;


📄 Step 6: 

/vendors/:name

 Page


src/pages/VendorDetail.js

import { useParams } from "react-router-dom";
import { Page, Card, ResourceList, Text } from "@shopify/polaris";
import { useEffect, useState } from "react";

const VendorDetail = () => {
  const { name } = useParams();
  const [products, setProducts] = useState([]);
  const [orders, setOrders] = useState([]);

  useEffect(() => {
    const token = window.sessionToken;
    
    const fetchProducts = async () => {
      const res = await fetch("/admin/api/2024-01/products.json", {
        headers: {
          "X-Shopify-Access-Token": token,
        },
      });
      const data = await res.json();
      const filtered = data.products.filter(p => p.vendor === name);
      setProducts(filtered);
    };

    const fetchOrders = async () => {
      const res = await fetch("/admin/api/2024-01/orders.json", {
        headers: {
          "X-Shopify-Access-Token": token,
        },
      });
      const data = await res.json();
      const vendorOrders = data.orders.filter(order =>
        order.line_items.some(li => li.vendor === name)
      );
      setOrders(vendorOrders);
    };

    fetchProducts();
    fetchOrders();
  }, [name]);

  return (
    <Page title={`Vendor: ${name}`}>
      <Card title="Products">
        <ResourceList
          items={products}
          renderItem={(p) => (
            <ResourceList.Item id={p.id}>
              <Text>{p.title}</Text>
            </ResourceList.Item>
          )}
        />
      </Card>
      <Card title="Orders">
        <ResourceList
          items={orders}
          renderItem={(o) => (
            <ResourceList.Item id={o.id}>
              <Text>Order #{o.name}</Text>
            </ResourceList.Item>
          )}
        />
      </Card>
    </Page>
  );
};

export default VendorDetail;


🔐 Step 7: Handle Access Token (JWT)



You need to use App Bridge Utils to get the JWT session token to call Admin API:

import { getSessionToken } from "@shopify/app-bridge-utils";

getSessionToken(app).then(token => {
  window.sessionToken = token;
});

Call this on app load (App.js) inside useEffect.



🚀 Final Hosting (Vercel/Netlify)



  1. Push your React app to GitHub.

  2. Deploy using Vercel or Netlify.

  3. Use the deployed URL to register the app in Shopify Partner → App Setup > App URL.

  4. Add /auth/callback, /auth, / to whitelist.



🧩 Notes


  • You must register your app from Partner dashboard.

  • Use Admin API scopes like:


    • read_products

    • read_orders

    • read_customers (optional)


  • All calls must pass JWT session token obtained via App Bridge.


Related Posts

Comments

Share Your ThoughtsBe the first to write a comment.
bg.8b803c47.png

READ OUR LATEST ARTICLES

Post

Welcome to the Intertoons Blog! Discover expert insights, the latest trends, and valuable tips on eCommerce, web development, and digital solutions. Stay informed and ahead in the digital world with our in-depth articles and guides!

5/5 based on 63 reviews | GDPR Compliant

bottom of page