import type { LoaderFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Page, Layout, Card, Text } from "@shopify/polaris";
import { authenticate } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { admin, session } = await authenticate.admin(request);
const response = await admin.graphql(`
#graphql
query getShopDetails {
shop {
name
plan {
displayName
}
}
}
`);
const { data } = await response.json();
return json({ shop: data.shop, shopDomain: session.shop });
};
export default function Dashboard() {
const { shop, shopDomain } = useLoaderData<typeof loader>();
return (
<Page title="Dashboard">
<Layout>
<Layout.Section>
<Card>
<Text as="h2" variant="headingMd">
Magazin: {shop.name} ({shopDomain})
</Text>
<Text as="p" variant="bodyMd">
Plan activ: {shop.plan.displayName}
</Text>
</Card>
</Layout.Section>
</Layout>
</Page>
);
}Dacă vrei să publici o aplicație în Shopify App Store în 2024, stack-ul standard recomandat de ei e Remix cu Polaris și App Bridge. Am migrat recent o aplicație cu peste 4.500 de merchant-i activi de pe vechiul template de Node + React SPA pe Remix și am trecut din nou prin tot calvarul de review. Economisești cam 40% din timpul de setup la auth și webhooks, dar dacă nu ești atent la câteva detalii stricte de UX, reviewerii Shopify îți dau reject instant.
De ce Remix + Polaris e combinația cerută
Până acum ceva timp, setup-ul clasic de embedded app înseamna să te chinui cu JWT-uri, iframe-uri blocate de browsere din cauza third-party cookies și un router de React care se bătea cap în cap cu App Bridge-ul. Cu noul @shopify/shopify-app-remix, autentificarea se face pe bază de session tokens direct în loader și action, server-side. Nu mai ai acel flicker enervant când se încarcă iframe-ul în Shopify Admin.
Polaris este biblioteca lor de componente. Trade-off-ul e simplu: arată 100% nativ în dashboard-ul magazinului și primești aprobare mai ușor la review, dar e teribil de rigidă dacă vrei să ieși din tipare sau să faci un branding personalizat. Pentru un tool B2B intern funcționează brici, însă dacă vrei animații fancy și layout-uri custom, te vei lupta cu CSS-ul lor.
Unde te taxează reviewerii Shopify
Am pățit de două ori să-mi respingă aplicația din motive care țin pur de detalii de implementare pe care le-am trecut cu vederea la testare:
- GDPR Webhooks obligatorii: Dacă nu ai definite cele trei endpoint-uri mandatorii (
customers/data_request,customers/redact,shop/redact) și nu răspund cu status 200 imediat, nici măcar nu testează restul aplicației. Testează-le local trimițând payload-uri mock prin CLI. - Loading States și Skeleton Screens: Dacă dai un query GraphQL mai greoi spre Shopify API și UI-ul rămâne alb mai mult de 500ms fără un
SkeletonPagedin Polaris, primești respingere. Reviewerii testează aplicația pe store-uri mari de test cu latență simulată. - Manevrarea erorilor de billing: Dacă folosești Shopify Billing API, utilizatorul trebuie să aibă opțiunea clară de a anula sau de a vedea planul direct în UI, fără să fie blocat într-un loop de redirect.
Un exemplu simplu de loader în Remix
Mai jos e structura de bază pe care o folosesc într-o pagină din Remix. Partea mișto e că authenticate.admin(request) gestionează automat re-autentificarea dacă tokenul a expirat, fără să mai scrii manual logica de redirect.