import type { LoaderFunctionArgs } from "@remix-run/node";
import { json } from "@remix-run/node";
import { useLoaderData } from "@remix-run/react";
import { Page, Layout, Card, Text, BlockStack } from "@shopify/polaris";
import { authenticate } from "../shopify.server";
export const loader = async ({ request }: LoaderFunctionArgs) => {
const { admin } = await authenticate.admin(request);
const response = await admin.graphql(
`#graphql
query getShop {
shop {
name
currencyCode
}
}`
);
const data = await response.json();
return json({ shop: data.data.shop });
};
export default function Index() {
const { shop } = useLoaderData<typeof loader>();
return (
<Page title="Dashboard">
<Layout>
<Layout.Section>
<Card>
<BlockStack gap="200">
<Text as="h2" variant="headingMd">
Magazin conectat: {shop.name}
</Text>
<Text as="p" variant="bodyMd">
Monedă principală: {shop.currencyCode}
</Text>
</BlockStack>
</Card>
</Layout.Section>
</Layout>
</Page>
);
}M-am lovit grav de review-ul celor de la Shopify la ultimele două aplicații lansate în App Store. Dacă vrei să construiești o aplicație embedded modernă, stack-ul oficial cu Remix și Polaris e cea mai bună opțiune în 2024, dar vine cu niște capcane specifice. Îți spun exact unde am pierdut 10 zile de re-submit și cum să le eviți.
Setup-ul cu Remix: Autentificare simplă, dar atenție la sesiune
Trecerea de la vechiul Express + REST API la pachetul @shopify/shopify-app-remix mi-a redus boilerplate-ul cu cel puțin 40%. Autentificarea prin OAuth și gestionarea token-urilor de sesiune (offline/online) funcționează impecabil din cutie când le cuplezi cu Prisma sau Redis.
Totuși, cel mai mare trade-off este că ești complet legat de arhitectura de Remix route-uri și de iframe-ul App Bridge. Dacă încerci să faci redirect-uri clasice de browser din backend fără să folosești helperii de Shopify (authenticate.admin(request)), aplicația se va bloca într-o buclă infinită de iframe reload. Am pățit asta pe un proiect cu 5.000 de comercianți activi când am încercat să implementez un flux custom de billing.
Polaris UI: De ce review-ul îți va respinge design-ul custom
Shopify are o echipă de review extrem de pedantă când vine vorba de UX. Am fost respins o dată doar pentru că un buton primar de "Save" era plasat în stânga în loc de dreapta sus, în header-ul de pagină Polaris.
Nu încerca să fii creativ cu Tailwind sau CSS custom peste componentele Polaris v12. Folosește structura lor nativă: <Page>, <Layout>, <BlockStack> și <Card>. Dacă respecți design system-ul lor, reviewerul dă scroll rapid și marchează UX-ul ca fiind aprobat. Pentru UI custom, păstrează macar regulile de spațiere (var(--p-space-4)) și tipografia oferită de pachet.
Capcanele de la Shopify App Store Review
Dacă vrei să treci review-ul din prima încercare (care durează în medie 3-5 zile lucrătoare), asigură-te că ai rezolvat aceste trei chestiuni critice:
- GDPR Webhooks Mandatory: Aplicația trebuie să răspundă corect pe endpoint-urile de
CUSTOMERS_DATA_REQUEST,CUSTOMERS_REDACTșiSHOP_REDACT. Dacă returnezi 500 sau 404 acolo, rejection-ul e garantat. - Stările de încărcare și eroare: Dacă pică un query GraphQL, nu lăsa pagina goală sau cu ecran alb. Polaris are
<SkeletonPage>și<Banner status="critical">. Reviewerul va testa aplicația tăind conexiunea sau trimitând date invalide. - Billing API Integration: Orice plan plătit trebuie procesat exclusiv prin Shopify Billing API. Am economisit 30% din timpul de scriere de cod folosind funcția
billing.requirefurnizată direct în loader-ul de Remix.
Dacă mergi pe mâna Remix + Polaris și nu reinventezi roata la auth și layout, treci de review în maximum 4 zile. Voi ce stack folosiți pentru aplicațiile de Shopify — ați rămas pe Node/React separat sau ați trecut toți pe Remix?