Receber por email
← Voltar para o catálogo

shopify-apps

Expert patterns for Shopify app development including Remix/React

41.2kestrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add sickn33/antigravity-awesome-skills

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/shopify-apps-mptd6c1q/svg)](https://www.skillteca.com.br/skills/shopify-apps-mptd6c1q)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Shopify Apps

Expert patterns for Shopify app development including Remix/React Router apps, embedded apps with App Bridge, webhook handling, GraphQL Admin API, Polaris components, billing, and app extensions.

Patterns

React Router App Setup

Modern Shopify app template with React Router

When to use: Starting a new Shopify app

Template

Create new Shopify app with CLI

npm init @shopify/app@latest my-shopify-app

Project structure

my-shopify-app/

├── app/

│ ├── routes/

│ │ ├── app._index.tsx # Main app page

│ │ ├── app.tsx # App layout with providers

│ │ ├── auth.$.tsx # Auth callback

│ │ └── webhooks.tsx # Webhook handler

│ ├── shopify.server.ts # Server configuration

│ └── root.tsx # Root layout

├── extensions/ # App extensions

├── shopify.app.toml # App configuration

└── package.json

// shopify.app.toml name = "my-shopify-app" client_id = "your-client-id" application_url = "https://your-app.example.com"

[access_scopes] scopes = "read_products,write_products,read_orders"

[webhooks] api_version = "2024-10"

[webhooks.subscriptions] topics = ["orders/create", "products/update"] uri = "/webhooks"

[auth] redirect_urls = ["https://your-app.example.com/auth/callback"]

// app/shopify.server.ts import "@shopify/shopify-app-remix/adapters/node"; import { LATEST_API_VERSION, shopifyApp, DeliveryMethod, } from "@shopify/shopify-app-remix/server"; import { PrismaSessionStorage } from "@shopify/shopify-app-session-storage-prisma"; import prisma from "./db.server";

const shopify = shopifyApp({ apiKey: process.env.SHOPIFY_API_KEY!, apiSecretKey: process.env.SHOPIFY_API_SECRET!, scopes: process.env.SCOPES?.split(","), appUrl: process.env.SHOPIFY_APP_URL!, authPathPrefix: "/auth", sessionStorage: new PrismaSessionStorage(prisma), distribution: AppDistribution.AppStore, future: { unstable_newEmbeddedAuthStrategy: true, }, ...(process.env.SHOP_CUSTOM_DOMAIN ? { customShopDomains: [process.env.SHOP_CUSTOM_DOMAIN] } : {}), });

export default shopify; export const apiVersion = LATEST_API_VERSION; export const authenticate = shopify.authenticate; export const sessionStorage = shopify.sessionStorage;

Notes

  • React Router replaced Remix as recommended template (late 2024)
  • unstable_newEmbeddedAuthStrategy enabled by default for new apps
  • Webhooks configured in shopify.app.toml, not code
  • Run 'shopify app deploy' to apply configuration changes

Embedded App with App Bridge

Render app embedded in Shopify Admin

When to use: Building embedded admin app

Template

// app/routes/app.tsx - App layout with providers import { Link, Outlet, useLoaderData, useRouteError } from "@remix-run/react"; import { AppProvider } from "@shopify/shopify-app-remix/react"; import polarisStyles from "@shopify/polaris/build/esm/styles.css?url";

export const links = () => [{ rel: "stylesheet", href: polarisStyles }];

export async function loader({ request }: LoaderFunctionArgs) { await authenticate.admin(request); return json({ apiKey: process.env.SHOPIFY_API_KEY! }); }

export default function App() { const { apiKey } = useLoaderData<typeof loader>();

return ( <AppProvider isEmbeddedApp apiKey={apiKey}> <ui-nav-menu> <Link to="/app" rel="home">Home</Link> <Link to="/app/products">Products</Link> <Link to="/app/settings">Settings</Link> </ui-nav-menu> <Outlet /> </AppProvider> ); }

export function ErrorBoundary() { const error = useRouteError(); return ( <AppProvider isEmbeddedApp> <Page> <Card> <Text as="p" variant="bodyMd"> Something went wrong. Please try again. </Text> </Card> </Page> </AppProvider> ); }

// app/routes/app._index.tsx - Main app page import { Page, Layout, Card, Text, BlockStack, Button, } from "@shopify/polaris"; import { TitleBar } from "@shopify/app-bridge-react";

export async function loader({ request }: LoaderFunctionArgs) { const { admin } = await authenticate.admin(request);

// GraphQL query const response = await admin.graphql( query { shop { name email } } );

const { data } = await response.json(); return json({ shop: data.shop }); }

export default function Index() { const { shop } = useLoaderData<typeof loader>();

return ( <Page> <TitleBar title="My Shopify App" /> <Layout> <Layout.Section> <Card> <BlockStack gap="200"> <Text as="h2" variant="headingMd"> Welcome to {shop.name}! </Text> <Text as="p" variant="bodyMd"> Your app is now connected to this store. </Text> <Button variant="primary"> Get Started </Button> </BlockStack> </Card> </Layout.Section> </Layout> </Page> ); }

Notes

  • App Bridge required for Built for Shopify (July 2025)
  • Polaris components match Shopify Admin design
  • TitleBar and navigation from App Bridge
  • Always authenticate requests with authenticate.admin()

Webhook Handling

Secure webhook processing with HMAC verification

When to use: Receiving Shopify webhooks

Template

// app/routes/webhooks.tsx import type { ActionFunctionArgs } from "@remix-run/node"; import { authenticate } from "../shopify.server"; import db from "../db.server";

export const action = async ({ request }: ActionFunctionArgs) => { // Authenticate webhook (verifies HMAC signature) const { topic, shop, payload, admin } = await authenticate.webhook(request);

console.log(Received ${topic} webhook for ${shop});

// Process based on topic switch (topic) { case "ORDERS_CREATE": // Queue for async processing await queueOrderProcessing(payload); break;

case "PRODUCTS_UPDATE": await handleProductUpdate(shop, payload); break;

case "APP_UNINSTALLED": // Clean up shop data await db.session.deleteMany({ where: { shop } }); await db.shopData.delete({ where: { shop } }); break;

case "CUSTOMERS_DATA_REQUEST": case "CUSTOMERS_REDACT": case "SHOP_REDACT": // GDPR webhooks - mandatory await handleGDPRWebhook(topic, payload); break;

default: console.log(Unhandled webhook topic: ${topic}); }

// CRITICAL: Return 200 immediately // Shopify expects response within 5 seconds return new Response(null, { status: 200 }); };

// Process asynchronously after responding async function queueOrderProcessing(payload: any) { // Use a job queue (BullMQ, etc.) await jobQueue.add("process-order", { orderId: payload.id, orderData: payload, }); }

async function handleProductUpdate(shop: string, payload: any) { // Quick sync operation only await db.product.upsert({ where: { shopifyId: payload.id }, update: { title: payload.title, updatedAt: new Date(), }, create: { shopifyId: payload.id, shop, title: payload.title, }, }); }

async function handleGDPRWebhook(topic: string, payload: any) { // GDPR compliance - required for all apps switch (topic) { case "CUSTOMERS_DATA_REQUEST": // Return customer data within 30 days break; case "CUSTOMERS_REDACT": // Delete customer data break; case "SHOP_REDACT": // Delete all shop data (48 hours after uninstall) break; } }

Notes

  • Respond within 5 seconds or webhook fails
  • Use job queues for heavy processing
  • GDPR webhooks are mandatory for App Store
  • HMAC verification handled by authenticate.webhook()

GraphQL Admin API

Query and mutate shop data with GraphQL

When to use: Interacting with Shopify Admin API

Template

// GraphQL queri

Compartilhar X LinkedIn