Introduction
Building powerful, cohesive admin interfaces is a cornerstone of modern web applications. If you’re developing a Shopify app or any system with an embedded admin experience, App Bridge UI components provide a robust, consistent, and accessible foundation. App Bridge—Shopify’s JavaScript library for embedding apps into the Shopify admin—includes prebuilt React components for modals, resource pickers, navigations, and more. In this post, we’ll walk through how to leverage App Bridge UI components to create custom admin pages that blend seamlessly with the Shopify admin. You’ll learn how to:
- Set up App Bridge in your project
- Use core UI components for layout and navigation
- Implement common patterns like embedded Resource Pickers, Resource Lists, and Modals
- Manage actions, toasts, and alerts via the App Bridge Action API
- Structure your code for maintainability and future enhancements

By the end, you’ll have a clear blueprint for crafting admin pages that feel native, guide your users effectively, and adhere to Shopify’s Polaris design system principles.
1. Setting Up App Bridge in Your Project
Before using UI components, you need to initialize App Bridge and connect it to the Shopify admin context.
1.1 Install Dependencies
bashCopyEditnpm install @shopify/app-bridge-react @shopify/app-bridge @shopify/polaris
@shopify/app-bridge-reactprovides React helpers for App Bridge.@shopify/app-bridgeis the core library.@shopify/polarisbrings in UI styles and components.
1.2 Initialize App Bridge
Create a provider at the root of your admin app:
jsxCopyEdit// App.jsx
import React from 'react';
import {Provider as AppBridgeProvider} from '@shopify/app-bridge-react';
import {AppProvider as PolarisProvider} from '@shopify/polaris';
import {ClientRouter, RoutePropagator} from '@shopify/app-bridge-react';
import {BrowserRouter} from 'react-router-dom';
function App() {
const config = {
apiKey: process.env.SHOPIFY_API_KEY,
shopOrigin: new URLSearchParams(window.location.search).get('shop'),
forceRedirect: true,
};
return (
<BrowserRouter>
<AppBridgeProvider config={config}>
<RoutePropagator />
<PolarisProvider i18n={{}}>
<ClientRouter />
{/* Your routes/components */}
</PolarisProvider>
</AppBridgeProvider>
</BrowserRouter>
);
}
export default App;
- Provider: Makes App Bridge and Polaris available throughout.
- RoutePropagator/ClientRouter: Syncs React Router with App Bridge navigation.
2. Structuring a Custom Admin Page
A typical admin page needs a header, navigation, and main content area. App Bridge UI components help you compose these quickly.
2.1 Page Layout with Polaris
Use Polaris’s Page component to handle spacing, titles, and breadcrumbs:
jsxCopyEditimport {Page, Layout} from '@shopify/polaris';
function OrdersReportPage() {
return (
<Page title="Custom Orders Report" breadcrumbs={[{content: 'Home', url: '/'}]}>
<Layout>
<Layout.Section>
{/* Content goes here */}
</Layout.Section>
</Layout>
</Page>
);
}
2.2 Embedding in Shopify Admin
Ensure this route is mounted under your App Bridge router:
jsxCopyEdit// routes.jsx
import {Route} from 'react-router-dom';
import OrdersReportPage from './OrdersReportPage';
export default function Routes() {
return (
<>
<Route path="/" element={<HomePage />} />
<Route path="/orders-report" element={<OrdersReportPage />} />
</>
);
}
3. Implementing Core App Bridge UI Components
Let’s explore key App Bridge UI components and how to apply them.

3.1 Using Modals for Data Collection
Modals are ideal for collecting filter criteria or confirmations.
jsxCopyEditimport {useState, useCallback} from 'react';
import {Button, Modal, TextContainer} from '@shopify/polaris';
function FilterModal() {
const [active, setActive] = useState(false);
const toggleActive = useCallback(() => setActive(a => !a), []);
return (
<>
<Button onClick={toggleActive}>Filter Orders</Button>
<Modal
open={active}
onClose={toggleActive}
title="Filter Orders"
primaryAction={{
content: 'Apply',
onAction: () => {
// apply filter logic
toggleActive();
},
}}
>
<Modal.Section>
<TextContainer>
<p>Select your filter criteria below.</p>
{/* Inputs go here */}
</TextContainer>
</Modal.Section>
</Modal>
</>
);
}
3.2 Resource Picker for Customer or Product Selection
Use App Bridge’s ResourcePicker to let merchants choose Shopify resources:
jsxCopyEditimport {ResourcePicker} from '@shopify/app-bridge-react';
function SelectProducts({open, onSelection, onCancel}) {
return (
<ResourcePicker
resourceType="Product"
open={open}
onSelection={resources => {
onSelection(resources.selection);
}}
onCancel={onCancel}
showVariants={false}
showHidden={false}
/>
);
}
Integrate it inside a page:
jsxCopyEditfunction OrdersReportPage() {
const [pickerOpen, setPickerOpen] = useState(false);
return (
<Page title="Custom Orders Report">
<Button onClick={() => setPickerOpen(true)}>Select Products</Button>
<SelectProducts
open={pickerOpen}
onSelection={items => {
// update state with selected items
setPickerOpen(false);
}}
onCancel={() => setPickerOpen(false)}
/>
</Page>
);
}
3.3 Resource List for Displaying Data
Use Polaris’s ResourceList to show selected items:
jsxCopyEditimport {ResourceList, Avatar, TextStyle} from '@shopify/polaris';
function ProductsList({items}) {
return (
<ResourceList
resourceName={{singular: 'product', plural: 'products'}}
items={items}
renderItem={item => {
const {id, title, image} = item;
return (
<ResourceList.Item id={id} media={<Avatar source={image.src} />}>
<h3>
<TextStyle variation="strong">{title}</TextStyle>
</h3>
</ResourceList.Item>
);
}}
/>
);
}
Combine selection and display:
jsxCopyEditfunction OrdersReportPage() {
const [selectedProducts, setSelectedProducts] = useState([]);
return (
<Page title="Custom Orders Report">
{/* ...ResourcePicker code... */}
<ProductsList items={selectedProducts} />
</Page>
);
}
4. Managing App Bridge Actions: Toasts, Redirects, and More
Beyond UI, App Bridge’s Action API lets you push toasts, handle redirections, and interact with the host.

4.1 Displaying Toast Messages
jsxCopyEditimport {useAppBridge} from '@shopify/app-bridge-react';
import {Toast} from '@shopify/app-bridge/actions';
function showToast(app) {
const toastOptions = {message: 'Report generated successfully', duration: 3000};
const toast = Toast.create(app, toastOptions);
toast.dispatch(Toast.Action.SHOW);
}
// In component:
const app = useAppBridge();
<Button onClick={() => showToast(app)}>Generate Report</Button>
4.2 Redirecting Within the Admin
jsxCopyEditimport {Redirect} from '@shopify/app-bridge/actions';
function redirectToHome(app) {
const redirect = Redirect.create(app);
redirect.dispatch(Redirect.Action.APP, '/');
}
// Usage:
<Button onClick={() => redirectToHome(app)}>Back to Dashboard</Button>
5. Best Practices and Architectural Tips
5.1 Encapsulate App Bridge Logic
Create custom hooks for common actions:
jsxCopyEdit// useAppBridgeActions.js
import {useAppBridge} from '@shopify/app-bridge-react';
import {Toast, Redirect} from '@shopify/app-bridge/actions';
export function useToasts() {
const app = useAppBridge();
return message => {
Toast.create(app, {message, duration: 3000}).dispatch(Toast.Action.SHOW);
};
}
export function useRedirect() {
const app = useAppBridge();
return path => {
Redirect.create(app).dispatch(Redirect.Action.APP, path);
};
}
5.2 Lazy‑Load Heavy Components
To reduce bundle size:
jsxCopyEditimport dynamic from 'next/dynamic';
const ResourcePicker = dynamic(() => import('@shopify/app-bridge-react').then(mod => mod.ResourcePicker), {
ssr: false,
});
5.3 Theming and Styling
Leverage Polaris tokens for consistent spacing, typography, and colors. Override less frequently, and always test on both light and dark admin themes.

Conclusion
By combining App Bridge’s embedding framework with Polaris UI components, you can create custom admin pages that fit natively within Shopify’s admin interface. From setting up App Bridge and structuring your layout to integrating Resource Pickers, modals, toasts, and redirects, the tools you need are at your fingertips. Remember to encapsulate repetitive logic in custom hooks, lazy‑load large components, and adhere to Polaris styling guidelines. With this approach, your embedded app will feel intuitive, performant, and professionally polished—delighting merchants and unlocking new possibilities for your application’s user experience.























































































































































































































































































































































































































































































































































































































































































