npm package: @savchukoleksii/plugin-storage-shopify-files
Description: Payload CMS storage adapter for Shopify Files
Latest version: 1.0.0

# Shopify Storage Adapter for Payload CMS

A [Payload CMS](https://payloadcms.com) storage adapter that stores uploaded files in [Shopify Files](https://shopify.dev/docs/api/admin-graphql/2026-01/mutations/fileCreate) using the Shopify Admin GraphQL API.

## Installation

```bash
pnpm add @savchukoleksii/plugin-storage-shopify-files
# or
npm install @savchukoleksii/plugin-storage-shopify-files
# or
yarn add @savchukoleksii/plugin-storage-shopify-files
```

### Requirements

- Payload CMS `^3.37.0`
- A Shopify store with a [custom app](https://help.shopify.com/en/manual/apps/app-types/custom-apps) that has the following Admin API access scopes:
  - `read_files`
  - `write_files`

## Usage

```ts
import { buildConfig } from 'payload'
import { shopifyStorage } from '@savchukoleksii/plugin-storage-shopify-files'

export default buildConfig({
  // ... your config
  plugins: [
    shopifyStorage({
      collections: {
        media: true,
      },
      options: {
        accessToken: process.env.SHOPIFY_ACCESS_TOKEN,
        shop: 'my-store.myshopify.com',
      },
    }),
  ],
})
```

## Configuration

### Plugin Options

| Option | Type | Required | Description |
| --- | --- | --- | --- |
| `collections` | `Record<string, true \| CollectionOptions>` | Yes | Upload collections to store in Shopify Files. |
| `options` | `object` | Yes | Shopify Admin API connection options. |
| `enabled` | `boolean` | No | Enable or disable the plugin. Defaults to `true`. |

### `options`

| Option | Type | Required | Description |
| --- | --- | --- | --- |
| `shop` | `string` | Yes | Your Shopify store domain (e.g. `my-store.myshopify.com`). |
| `accessToken` | `string` | Yes | Your Shopify Admin API access token. |
| `apiVersion` | `string` | No | Shopify Admin API version. Defaults to `2026-01`. |

### Collection Options

Pass `true` to use defaults, or an object with additional options from `@payloadcms/plugin-cloud-storage`:

```ts
shopifyStorage({
  collections: {
    // Simple — use defaults
    media: true,
    // Advanced — with prefix and custom file URL generation
    documents: {
      prefix: 'docs',
      generateFileURL: ({ filename, prefix }) => {
        return `https://cdn.example.com/${prefix}/${filename}`
      },
    },
  },
  options: {
    accessToken: process.env.SHOPIFY_ACCESS_TOKEN,
    shop: 'my-store.myshopify.com',
  },
})
```

## How It Works

This adapter uses the Shopify Admin GraphQL API to manage files through a three-step upload flow:

1. **Staged Upload** — Requests a temporary upload URL via the `stagedUploadsCreate` mutation.
2. **File Upload** — Uploads the file binary to the staged URL.
3. **File Create** — Registers the uploaded file in Shopify via the `fileCreate` mutation.

File deletion uses the `fileDelete` mutation. File retrieval queries the `files` endpoint by filename and proxies the Shopify CDN response.

Local storage is automatically disabled for collections managed by this adapter.

## Development

```bash
# Install dependencies
pnpm install

# Create .env with your Shopify credentials
cp .env.example .env

# Start the dev server
pnpm dev

# Run tests
pnpm test

# Lint
pnpm lint

# Build
pnpm build
```

### Environment Variables

| Variable | Description |
| --- | --- |
| `SHOPIFY_ACCESS_TOKEN` | Shopify Admin API access token |
| `SHOPIFY_SHOP` | Shopify store domain |
| `PAYLOAD_SECRET` | Payload secret key |
| `DATABASE_URL` | Database connection URL (defaults to local SQLite) |

## License

MIT