home / skills / toilahuongg / shopify-agents-kit / shopify-remix-template

shopify-remix-template skill

/.claude/skills/shopify-remix-template

This skill guides building Shopify apps with the Remix template, covering structure, authentication, API usage, and deployment to production.

npx playbooks add skill toilahuongg/shopify-agents-kit --skill shopify-remix-template

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
5.3 KB
---
name: shopify-remix-template
description: Guide for developing Shopify apps using the official Shopify Remix Template. Covers structure, authentication, API usage, and deployment.
---

# Shopify Remix Template Guide

This skill provides a guide for building Shopify apps using the official **Shopify Remix App Template**. This template is the recommended starting point for most new Shopify embedded apps (though React Router is the future direction, Remix is still widely used and supported).

## 🚀 Getting Started

To create a new app using the Remix template, run:

```bash
git clone https://github.com/Shopify/shopify-app-template-remix.git
```

## 📂 Project Structure

A typical Remix app structure:

*   `app/`
    *   `routes/`: File-system based routing.
        *   `app._index.tsx`: The main dashboard page.
        *   `app.tsx`: The root layout for the authenticated app.
        *   `webhooks.tsx`: Webhook handler.
    *   `shopify.server.ts`: **Critical**. Initializes the Shopify API client, authentication, and session storage (Redis).
    *   `db.server.ts`: Database connection (Mongoose).
    *   `models/`: Mongoose models (e.g., `Session.ts`, `Shop.ts`).
    *   `root.tsx`: The root component for the entire application.
*   `shopify.app.toml`: Main app configuration file.

## 🔐 Authentication & Sessions

The template uses `@shopify/shopify-app-remix` to handle authentication automatically.

### `shopify.server.ts`
This file exports an `authenticate` object used in loaders and actions. It is configured to use **Redis** for session storage.

```typescript
import { shopifyApp } from "@shopify/shopify-app-remix/server";
import { RedisSessionStorage } from "@shopify/shopify-app-session-storage-redis";

const sessionDb = new RedisSessionStorage(
  new URL(process.env.REDIS_URL!)
);

const shopify = shopifyApp({
  apiKey: process.env.SHOPIFY_API_KEY,
  apiSecretKey: process.env.SHOPIFY_API_SECRET,
  appUrl: process.env.SHOPIFY_APP_URL,
  scopes: process.env.SCOPES?.split(","),
  apiVersion: "2025-10",
  sessionStorage: sessionDb,
  isEmbeddedApp: true,
});

export const authenticate = shopify.authenticate;
export const apiVersion = "2025-10";
export const addDocumentResponseHeaders = shopify.addDocumentResponseHeaders;
```

### Usage in Loaders (Data Fetching)
Protect routes and get the session context:

```typescript
import { json } from "@remix-run/node";
import { authenticate } from "../shopify.server";

export const loader = async ({ request }) => {
  const { admin, session } = await authenticate.admin(request);
  
  // Use admin API
  const response = await admin.graphql(`...`);
  
  return json({ data: response });
};
```

## 📡 Webhooks

Webhooks are handled in `app/routes/webhooks.tsx` (or individual route files). The template automatically registers webhooks defined in `shopify.server.ts`.

To add a webhook:
1.  Add configuration in `shopify.server.ts`.
2.  Handle the topic in the `action` of `app/routes/webhooks.tsx`.

## 🗄️ Database (Mongoose/MongoDB)

Use **Mongoose** for persistent data storage (Shops, Settings, etc.).

### `app/db.server.ts`
Singleton connection to MongoDB.

```typescript
import mongoose from "mongoose";

let isConnected = false;

export const connectDb = async () => {
  if (isConnected) return;

  try {
    await mongoose.connect(process.env.MONGODB_URI!);
    isConnected = true;
    console.log("🚀 Connected to MongoDB");
  } catch (error) {
    console.error("❌ MongoDB connection error:", error);
  }
};
```

### `app/models/Shop.ts` (Example)

```typescript
import mongoose from "mongoose";

const ShopSchema = new mongoose.Schema({
  shop: { type: String, required: true, unique: true },
  accessToken: { type: String, required: true },
  isInstalled: { type: Boolean, default: true },
});

export const Shop = mongoose.models.Shop || mongoose.model("Shop", ShopSchema);
```

### Usage in Loaders
Connect to the DB before using models.

```typescript
import { connectDb } from "../db.server";
import { Shop } from "../models/Shop";

export const loader = async ({ request }) => {
  await connectDb();
  // ...
  const shopData = await Shop.findOne({ shop: session.shop });
  // ...
};
```

## 🎨 UI & Design (Polaris)

The template comes pre-configured with **Polaris**, Shopify's design system.
*   Wrap your pages in `<Page>` components.
*   Use `<Layout>`, `<Card>`, and other Polaris components for a native feel. 
*   App Bridge is initialized automatically in `app.tsx`.

## 🛠️ Common Tasks

### 1. Adding a Navigation Item
Update `app/routes/app.tsx`:
```typescript
<ui-nav-menu>
  <Link to="/app">Home</Link>
  <Link to="/app/settings">Settings</Link>
</ui-nav-menu>
```

### 2. Fetching Data from Shopify
Use the `admin` object from `authenticate.admin(request)` to make GraphQL calls.

### 3. Deploying
*   **Hosting:** Remix apps can be hosted on Vercel, Fly.io, Heroku, or Cloudflare.
*   **Database:** Ensure you have a persistent database (e.g., Postgres) for production.
*   **Environment Variables:** Set `SHOPIFY_API_KEY`, `SHOPIFY_API_SECRET`, `SCOPES`, `SHOPIFY_APP_URL`.

## 📚 References

*   [Shopify Remix App Template (GitHub)](https://github.com/Shopify/shopify-app-template-remix)
*   [@shopify/shopify-app-remix package](https://www.npmjs.com/package/@shopify/shopify-app-remix)
*   [Remix Documentation](https://remix.run/docs/en/main)

Overview

This skill is a concise guide for developing Shopify embedded apps using the official Shopify Remix App Template. It explains project structure, authentication, session storage, database integration, webhooks, UI with Polaris, and deployment considerations. The guide is focused on practical steps you can apply immediately to scaffold, secure, and deploy a Shopify app with Remix.

How this skill works

The template wires Shopify authentication via @shopify/shopify-app-remix and a Redis-backed session store, exposing an authenticate object for use in loaders and actions. It provides a centralized shopify.server.ts for API client initialization, automatic webhook registration and handling, and example Mongoose models with a singleton MongoDB connector. The UI is pre-configured with Polaris and App Bridge so pages render with native Shopify styling.

When to use it

  • Starting a new embedded Shopify app when you prefer Remix over React Router.
  • You need built-in authentication, session management, and webhook scaffolding.
  • Building apps that require server-side routes, GraphQL admin API calls, and persistent storage.
  • When you want a production-ready template with Polaris and App Bridge integrated.
  • If you plan to deploy to Vercel, Fly.io, Heroku, or similar hosts and need environment-driven config.

Best practices

  • Keep shopify.server.ts as the single source of truth for API keys, session storage, and webhook config.
  • Use Redis for session storage in production and ensure REDIS_URL is secured and monitored.
  • Initialize a singleton DB connection (e.g., Mongoose) and call it in loaders before model use.
  • Protect routes using authenticate.admin(request) and avoid exposing access tokens to the client.
  • Define webhooks in server config and handle topics in dedicated routes to keep logic modular.

Example use cases

  • Create an app that reads and updates store data via the Admin GraphQL API using authenticate.admin(request).
  • Store per-shop settings and installation state in MongoDB with a Shop model and accessToken.
  • Register and process order or app/uninstalled webhooks to keep shop records in sync.
  • Build an embedded admin UI with Polaris components and App Bridge for a native merchant experience.
  • Deploy to Vercel with environment variables for SHOPIFY_API_KEY, SHOPIFY_API_SECRET, SCOPES, and REDIS_URL.

FAQ

How do I protect a route and fetch shop data?

Call authenticate.admin(request) in the loader to get admin and session, then use admin.graphql(...) and connect to the DB before querying models.

Where should I store session data in production?

Use RedisSessionStorage with a managed Redis instance and set REDIS_URL; avoid in-memory stores for production.