Getting Started

View on GitHub

Copy-paste workflow, folder structure, and how to adapt recipes to your Shopify app.

Step 1
Copy to Your Project

Copy these folders into your project:

components/polaris/
├── primitives/      # Base Polaris wrappers (Button, Modal, etc.)
├── compositions/    # Composed components (AlertDialog, DataTable, etc.)
├── recipes/         # Full recipes
└── stories/         # Storybook stories

.storybook/          # Storybook configuration

Adjust import paths as needed for your project structure.

Optional
Explore with Storybook

Stories are included for every component. Run Storybook to explore variants, test states, and verify behavior before shipping.

pnpm storybook

Stories are co-located with components in components/polaris/. The Storybook config is in .storybook/.

Step 2
Install Polaris

Make sure Polaris Web Components are loaded in your app:

// In your root layout or _app.tsx
<Script src="https://cdn.shopify.com/shopifycloud/polaris.js" />
Step 3
Use a Recipe

Import and use primitives and recipes in your pages

import {
  PageHeader,
  IndexTable,
  EmptyState,
} from '@/components/polaris/recipes';

import {
  Page,
  Card,
  Button,
  Badge,
} from '@/components/polaris';

export default function ProductsPage() {
  return (
    <Page>
      {/* Recipe: page header */}
      <PageHeader
        title="Products"
        primaryAction={{
          label: 'Add product',
          onClick: openCreate,
        }}
      />

      {/* Primitive composition around a recipe */}
      <Card>
        <IndexTable
          items={products}
          resourceName="product"
          columns={[
            { key: 'title', header: 'Title' },
            {
              key: 'status',
              header: 'Status',
              render: (p) => (
                <Badge tone={p.status === 'active' ? 'success' : 'warning'}>
                  {p.status}
                </Badge>
              ),
            },
            {
              key: 'price',
              header: 'Price',
              align: 'end',
            },
          ]}
          selectable
          bulkActions={[
            { label: 'Archive', onAction: archive },
            { label: 'Delete', tone: 'critical', onAction: remove },
          ]}
          emptyState={
            <EmptyState
              heading="No products yet"
              description="Create your first product to get started."
              primaryAction={{
                label: 'Add product',
                onClick: openCreate,
              }}
            />
          }
        />
      </Card>
    </Page>
  );
}
Adapting Recipes

Recipes are starting points, not rigid templates. You own the code and should adapt it:

  • Rename components to match your domain
  • Add or remove props based on your needs
  • Combine recipes to build complex pages
  • Delete unused code — less is more
No Version Guarantees

This is copy-paste code, not a package. There are no version numbers or semver guarantees. When you copy code, it becomes yours to maintain. Updates are additive — new recipes and improvements you can adopt when useful.