Building Custom Shopify Apps with Remix and Polaris

Complete developer guide to building custom Shopify apps using Remix, Shopify CLI 3, Polaris design system, and App Bridge for embedded admin experiences.

E
ECOSIRE Research and Development Team
|19 मार्च 202612 मिनट पढ़ें2.6k शब्द|

रीमिक्स और पोलारिस के साथ कस्टम शॉपिफाई ऐप्स का निर्माण

डिफॉल्ट ऐप फ्रेमवर्क के रूप में शॉपिफाई का रीमिक्स में माइग्रेशन प्लेटफॉर्म पर प्रोडक्शन ऐप्स के निर्माण के तरीके में एक मौलिक बदलाव का प्रतीक है। रीमिक्स-आधारित शॉपिफाई ऐप टेम्प्लेट एक सुसंगत स्टैक में सर्वर-साइड रेंडरिंग, स्ट्रीमिंग, नेस्टेड रूटिंग और नेटिव शॉपिफाई सीएलआई एकीकरण प्रदान करता है - जो पुराने नोड/एक्सप्रेस + रिएक्ट पैटर्न की जगह लेता है जो 2023 तक ऐप डेवलपमेंट पर हावी रहा।

यह मार्गदर्शिका संपूर्ण विकास जीवनचक्र के माध्यम से चलती है: मचान, प्रमाणीकरण, ग्राफक्यूएल डेटा प्राप्त करना, पोलारिस घटक एकीकरण, वेबहुक, बिलिंग, और शॉपिफाई डेवलपर्स द्वारा अनुभव किए गए पैटर्न जो रखरखाव योग्य, प्रदर्शन करने वाले एम्बेडेड ऐप्स को शिप करने के लिए उपयोग करते हैं।

मुख्य बातें

  • Shopify CLI 3.x OAuth, सेशन स्टोरेज और पूर्व-कॉन्फ़िगर किए गए ऐप ब्रिज के साथ एक प्रोडक्शन-रेडी रीमिक्स ऐप तैयार करता है
  • authenticate.admin सहायक संपूर्ण OAuth प्रवाह को संभालता है - OAuth को मैन्युअल रूप से लागू न करें
  • रीमिक्स का लोडर/एक्शन पैटर्न Shopify के GraphQL अनुरोध/म्यूटेशन चक्र से पूरी तरह मेल खाता है
  • ऐप स्टोर अनुमोदन के लिए पोलारिस घटकों की आवश्यकता होती है - पोलारिस मानकों की अनदेखी करने वाला कस्टम यूआई समीक्षा में विफल रहता है
  • विश्वसनीयता के लिए वेबहुक को केवल एपीआई कॉल के अलावा ऐप कॉन्फ़िगरेशन के माध्यम से पंजीकृत किया जाना चाहिए
  • शॉपिफाई एडमिन ग्राफक्यूएल एपीआई पेजिनेटेड है - हमेशा डेटा लोडर में कर्सर-आधारित पेजिनेशन को संभालता है
  • ऐप ब्रिज क्रोम-रहित एम्बेडेड अनुभव प्रदान करता है; नेविगेशन के लिए useAppBridge हुक का उपयोग करें
  • सदस्यता शुल्क वसूलने वाले किसी भी ऐप के लिए बिलिंग एपीआई एकीकरण आवश्यक है

परियोजना सेटअप और मचान

ठीक से कॉन्फ़िगर किए गए रीमिक्स ऐप को तैयार करने के लिए Shopify CLI 3 से शुरुआत करें:

npm install -g @shopify/cli@latest
shopify app create node --template remix
cd your-app-name

उत्पन्न मचान में शामिल हैं:

  • Shopify-संगत सेटिंग्स के साथ remix.config.js
  • shopify.app.toml - आपकी ऐप कॉन्फ़िगरेशन फ़ाइल (ऐप सेटिंग्स के लिए .env को प्रतिस्थापित करती है)
  • app/shopify.server.ts - केंद्रीय प्रमाणीकरण और एपीआई क्लाइंट कॉन्फ़िगरेशन
  • app/routes/app.tsx - रूट एम्बेडेड ऐप लेआउट
  • prisma/schema.prisma - SQLite सत्र भंडारण (उत्पादन के लिए PostgreSQL से बदलें)

shopify.app.toml संरचना:

name = "your-app-name"
client_id = "your-api-key"
application_url = "https://your-app-url.com"
embedded = true

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

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

[webhooks]
api_version = "2025-01"

  [[webhooks.subscriptions]]
  topics = ["app/uninstalled"]
  uri = "/webhooks"

authenticate.admin के साथ प्रमाणीकरण

shopify.server.ts फ़ाइल एक authenticate ऑब्जेक्ट निर्यात करती है जो सभी प्रमाणीकरण चिंताओं को संभालती है। OAuth को कभी भी मैन्युअल रूप से लागू न करें - authenticate.admin सहायक संपूर्ण प्रवाह को प्रबंधित करता है जिसमें शामिल हैं:

  • OAuth कोड एक्सचेंज
  • सत्र दृढ़ता
  • टोकन ताज़ा करें
  • ऑनलाइन बनाम ऑफलाइन एक्सेस मोड
  • व्यापारी की सहमति संग्रह

रूट लोडर में प्रमाणीकरण का उपयोग करना:

// app/routes/app.products.tsx
import { json } from "@remix-run/node";
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 GetProducts($first: Int!) {
      products(first: $first) {
        nodes {
          id
          title
          status
          priceRangeV2 {
            minVariantPrice {
              amount
              currencyCode
            }
          }
          totalInventory
        }
        pageInfo {
          hasNextPage
          endCursor
        }
      }
    }
  `, {
    variables: { first: 50 }
  });

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

ऑनलाइन बनाम ऑफ़लाइन सत्र:

  • ऑफ़लाइन पहुंच: अधिकांश ऐप्स के लिए डिफ़ॉल्ट। सत्र व्यापारी लॉगिन से स्वतंत्र रूप से जारी रहता है। पृष्ठभूमि नौकरियों, वेबहुक, निर्धारित कार्यों के लिए उपयोग किया जाता है।
  • ऑनलाइन पहुंच: लॉग-इन किए गए व्यापारी उपयोगकर्ता से जुड़ा सत्र। तब आवश्यक होता है जब आपको किसी विशिष्ट उपयोगकर्ता की ओर से कार्य करने की आवश्यकता होती है (उदाहरण के लिए, यह ट्रैक करना कि किस स्टाफ सदस्य ने कोई कार्रवाई की है)।

shopify.server.ts में कॉन्फ़िगर करें:

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, // Token Exchange (2024+)
  },
});

टोकन एक्सचेंज (2026 के लिए अनुशंसित)

Shopify की नई टोकन एक्सचेंज प्रमाणीकरण रणनीति एम्बेडेड ऐप्स के लिए OAuth रीडायरेक्ट को समाप्त कर देती है। Shopify एडमिन के भीतर उपयोगकर्ताओं को छोड़ने और वापस लौटने की आवश्यकता नहीं है - ऐप ब्रिज से सत्र टोकन को सीधे एपीआई एक्सेस टोकन सर्वर-साइड के लिए एक्सचेंज किया जाता है। इसे unstable_newEmbeddedAuthStrategy: true के साथ सक्षम करें।


ग्राफक्यूएल डेटा फ़ेचिंग पैटर्न

Shopify का एडमिन API GraphQL-प्रथम है। उत्पादन-गुणवत्ता डेटा लाने के लिए इन पैटर्न में महारत हासिल करें।

कर्सर-आधारित पेजिनेशन:

export async function getAllProducts(admin: AdminApiContext) {
  let hasNextPage = true;
  let cursor: string | null = null;
  const allProducts = [];

  while (hasNextPage) {
    const response = await admin.graphql(`
      #graphql
      query GetProducts($first: Int!, $after: String) {
        products(first: $first, after: $after) {
          nodes {
            id
            title
            handle
          }
          pageInfo {
            hasNextPage
            endCursor
          }
        }
      }
    `, {
      variables: { first: 250, after: cursor }
    });

    const data = await response.json();
    const { nodes, pageInfo } = data.data.products;

    allProducts.push(...nodes);
    hasNextPage = pageInfo.hasNextPage;
    cursor = pageInfo.endCursor;
  }

  return allProducts;
}

त्रुटि प्रबंधन के साथ उत्परिवर्तन:

export const action = async ({ request }: ActionFunctionArgs) => {
  const { admin } = await authenticate.admin(request);
  const formData = await request.formData();

  const title = formData.get("title") as string;
  const price = formData.get("price") as string;

  const response = await admin.graphql(`
    #graphql
    mutation CreateProduct($input: ProductInput!) {
      productCreate(input: $input) {
        product {
          id
          title
        }
        userErrors {
          field
          message
        }
      }
    }
  `, {
    variables: {
      input: {
        title,
        variants: [{ price }]
      }
    }
  });

  const data = await response.json();

  if (data.data.productCreate.userErrors.length > 0) {
    return json({
      errors: data.data.productCreate.userErrors
    }, { status: 422 });
  }

  return json({ product: data.data.productCreate.product });
};

बड़े डेटासेट के लिए थोक संचालन:

हजारों रिकॉर्ड्स पर परिचालन के लिए, पृष्ठांकित क्वेरी के बजाय बल्क ऑपरेशंस एपीआई का उपयोग करें। बल्क क्वेरीज़ अतुल्यकालिक रूप से चलती हैं और एक JSONL फ़ाइल लौटाती हैं:

const bulkQuery = await admin.graphql(`
  mutation {
    bulkOperationRunQuery(
      query: """
        {
          products {
            edges {
              node {
                id
                title
                variants {
                  edges {
                    node {
                      id
                      price
                      inventoryQuantity
                    }
                  }
                }
              }
            }
          }
        }
      """
    ) {
      bulkOperation {
        id
        status
      }
      userErrors {
        field
        message
      }
    }
  }
`);

currentBulkOperation को status === "COMPLETED" तक पोल करें, फिर url से JSONL को डाउनलोड करें और पार्स करें।


पोलारिस डिज़ाइन सिस्टम एकीकरण

पोलारिस एम्बेडेड ऐप्स के लिए शॉपिफाई का डिज़ाइन सिस्टम है। ऐप स्टोर सबमिशन के लिए पोलारिस का उपयोग करना आवश्यक है - गैर-पोलारिस यूआई के परिणामस्वरूप समीक्षा अस्वीकृति होगी।

रीमिक्स में पोलारिस की स्थापना:

// app/root.tsx
import { AppProvider } from "@shopify/polaris";
import "@shopify/polaris/build/esm/styles.css";
import translations from "@shopify/polaris/locales/en.json";

export default function App() {
  return (
    <AppProvider i18n={translations}>
      <Outlet />
    </AppProvider>
  );
}

Shopify ऐप्स के लिए सामान्य पोलारिस घटक पैटर्न:

// Product listing with DataTable
import {
  Page,
  Card,
  DataTable,
  Button,
  Badge,
  Filters,
  EmptyState
} from "@shopify/polaris";

export default function ProductsPage() {
  const { products } = useLoaderData<typeof loader>();

  const rows = products.nodes.map(product => [
    product.title,
    <Badge tone={product.status === 'ACTIVE' ? 'success' : 'warning'}>
      {product.status}
    </Badge>,
    product.totalInventory,
    `${product.priceRangeV2.minVariantPrice.currencyCode} ${product.priceRangeV2.minVariantPrice.amount}`,
    <Button url={`/app/products/${product.id}`}>Edit</Button>
  ]);

  return (
    <Page
      title="Products"
      primaryAction={{ content: "Add product", url: "/app/products/new" }}
    >
      <Card>
        <DataTable
          columnContentTypes={['text', 'text', 'numeric', 'numeric', 'text']}
          headings={['Title', 'Status', 'Inventory', 'Price', 'Actions']}
          rows={rows}
        />
      </Card>
    </Page>
  );
}

पोलारिस और रीमिक्स के साथ फॉर्म हैंडलिंग:

import { Form, useNavigation, useActionData } from "@remix-run/react";
import { TextField, Select, FormLayout, Banner } from "@shopify/polaris";

export default function ProductForm() {
  const actionData = useActionData<typeof action>();
  const navigation = useNavigation();
  const isSubmitting = navigation.state === "submitting";

  return (
    <Form method="post">
      <FormLayout>
        {actionData?.errors && (
          <Banner tone="critical">
            {actionData.errors.map(e => <p key={e.field}>{e.message}</p>)}
          </Banner>
        )}
        <TextField
          label="Product title"
          name="title"
          autoComplete="off"
        />
        <TextField
          label="Price"
          name="price"
          type="number"
          prefix="$"
          autoComplete="off"
        />
        <Button submit loading={isSubmitting}>Save product</Button>
      </FormLayout>
    </Form>
  );
}

वेबहुक: पंजीकरण और प्रसंस्करण

विश्वसनीय वेबहुक हैंडलिंग उन ऐप्स के लिए महत्वपूर्ण है जो मर्चेंट स्टोर की घटनाओं पर प्रतिक्रिया करते हैं।

वेबहुक को shopify.app.toml के माध्यम से पंजीकृत करना:

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

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

वेबहुक को रीमिक्स रूट में संसाधित करना:

// app/routes/webhooks.tsx
import { authenticate } from "../shopify.server";
import db from "../db.server";

export const action = async ({ request }: ActionFunctionArgs) => {
  const { topic, shop, session, payload } = await authenticate.webhook(request);

  switch (topic) {
    case "PRODUCTS_CREATE":
      await db.product.create({
        data: {
          shopifyId: payload.id.toString(),
          title: payload.title,
          shop: shop,
        }
      });
      break;

    case "APP_UNINSTALLED":
      if (session) {
        await db.session.deleteMany({ where: { shop } });
      }
      break;

    default:
      throw new Response("Unhandled webhook topic", { status: 404 });
  }

  return new Response(null, { status: 200 });
};

वेबहुक विश्वसनीयता सर्वोत्तम अभ्यास:

  1. तुरंत 200 प्रतिक्रिया लौटाएं - यदि ऑपरेशन धीमा है तो पृष्ठभूमि कतार के माध्यम से अतुल्यकालिक रूप से प्रक्रिया करें
  2. वेबहुक के X-Shopify-Webhook-Id हेडर का उपयोग करके निष्क्रियता लागू करें
  3. HMAC हस्ताक्षर सत्यापित करें (authenticate.webhook द्वारा संचालित)
  4. पुनः प्रयास तर्क को संभालें - Shopify पुनः प्रयास विफल वेबहुक 48 घंटों में 19 बार तक
  5. डिबगिंग के लिए सभी वेबहुक पेलोड लॉग करें (लॉगिंग से पहले स्ट्रिप पीआईआई)

बिलिंग एपीआई: सदस्यता और उपयोग शुल्क

शुल्क वसूलने वाले किसी भी ऐप को Shopify की बिलिंग एपीआई का उपयोग करना होगा। इसे दरकिनार करना ऐप स्टोर नीतियों का उल्लंघन है।

एकमुश्त ऐप खरीदारी:

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const { billing, session } = await authenticate.admin(request);

  const { hasActivePayment, appSubscription } = await billing.check({
    plans: ["Professional Plan"],
    isTest: process.env.NODE_ENV !== "production",
  });

  if (!hasActivePayment) {
    await billing.request({
      plan: "Professional Plan",
      isTest: process.env.NODE_ENV !== "production",
    });
  }

  return json({ session });
};

बिलिंग योजनाओं को shopify.server.ts में कॉन्फ़िगर करें:

const shopify = shopifyApp({
  // ...other config
  billing: {
    "Professional Plan": {
      amount: 29.99,
      currencyCode: "USD",
      interval: BillingInterval.Every30Days,
    },
    "Enterprise Plan": {
      amount: 99.99,
      currencyCode: "USD",
      interval: BillingInterval.Every30Days,
    }
  }
});

ऐप ब्रिज और एंबेडेड नेविगेशन

ऐप ब्रिज जावास्क्रिप्ट लाइब्रेरी है जो शॉपिफाई एडमिन के भीतर एम्बेडेड आईफ्रेम अनुभव का प्रबंधन करती है।

मुख्य ऐप ब्रिज पैटर्न:

import { useAppBridge } from "@shopify/app-bridge-react";
import { Redirect } from "@shopify/app-bridge/actions";

// Navigate to an external URL from embedded context
function ExternalLinkButton() {
  const app = useAppBridge();

  const handleClick = () => {
    const redirect = Redirect.create(app);
    redirect.dispatch(Redirect.Action.REMOTE, {
      url: "https://your-docs-site.com",
      newContext: true
    });
  };

  return <Button onClick={handleClick}>View documentation</Button>;
}

// Toast notifications
import { useToast } from "@shopify/app-bridge-react";

function SaveButton() {
  const { show } = useToast();
  const fetcher = useFetcher();

  useEffect(() => {
    if (fetcher.state === "idle" && fetcher.data?.success) {
      show("Settings saved");
    }
  }, [fetcher.state, fetcher.data]);

  return (
    <Button
      onClick={() => fetcher.submit(formData, { method: "post" })}
      loading={fetcher.state !== "idle"}
    >
      Save
    </Button>
  );
}

परीक्षण और स्थानीय विकास

# Start the app in development mode
shopify app dev

# The CLI handles:
# - ngrok tunnel creation for webhook delivery
# - App installation on your development store
# - Hot module replacement for Remix routes
# - Shopify Partner Dashboard app URL updates

ग्राफक्यूएल प्रश्नों का परीक्षण:

कोड में लागू करने से पहले प्रश्नों का परीक्षण करने के लिए अपने डेवलपमेंट स्टोर एडमिन में Shopify GraphiQL ऐप का उपयोग करें। इसके माध्यम से प्रवेश: your-store.myshopify.com/admin/apps/graphiql

यूनिट परीक्षण मार्ग लोडर:

import { describe, it, expect, vi } from "vitest";
import { loader } from "~/routes/app.products";

vi.mock("~/shopify.server", () => ({
  authenticate: {
    admin: vi.fn().mockResolvedValue({
      admin: {
        graphql: vi.fn().mockResolvedValue({
          json: () => Promise.resolve({
            data: {
              products: {
                nodes: [{ id: "gid://shopify/Product/1", title: "Test Product" }],
                pageInfo: { hasNextPage: false, endCursor: null }
              }
            }
          })
        })
      },
      session: { shop: "test-shop.myshopify.com" }
    })
  }
}));

describe("Products loader", () => {
  it("returns product list", async () => {
    const request = new Request("https://test.com/app/products");
    const response = await loader({ request, params: {}, context: {} });
    const data = await response.json();

    expect(data.products.nodes).toHaveLength(1);
    expect(data.products.nodes[0].title).toBe("Test Product");
  });
});

अक्सर पूछे जाने वाले प्रश्न

क्या मुझे नए Shopify ऐप्स के लिए रीमिक्स टेम्पलेट या नोड/एक्सप्रेस टेम्पलेट का उपयोग करना चाहिए?

सभी नए ऐप्स के लिए रीमिक्स टेम्पलेट का उपयोग करें। शॉपिफाई ने अपने ऐप डेवलपमेंट टूलिंग के लिए रीमिक्स पर मानकीकरण किया है - शॉपिफाई सीएलआई, डॉक्यूमेंटेशन और ऐप ब्रिज रिएक्ट सभी रीमिक्स के लिए अनुकूलित हैं। नोड/एक्सप्रेस टेम्प्लेट अब सक्रिय रूप से विकसित नहीं हुआ है और इसमें टोकन एक्सचेंज सहित कई आधुनिक प्रमाणीकरण सुविधाओं का अभाव है। मौजूदा नोड/एक्सप्रेस ऐप्स को तुरंत माइग्रेट करने की आवश्यकता नहीं है, लेकिन सभी नए ऐप्स रीमिक्स से शुरू होने चाहिए।

क्या मैं पोलारिस के बजाय एक अलग फ्रंटएंड फ्रेमवर्क का उपयोग कर सकता हूं?

आप अपने ऐप के सार्वजनिक-सामना वाले हिस्सों (अपने स्वयं के डोमेन पर सेटिंग पेज, लैंडिंग पेज इत्यादि) के लिए अपने स्वयं के डिज़ाइन सिस्टम का उपयोग कर सकते हैं, लेकिन शॉपिफाई एडमिन के भीतर एम्बेडेड अनुभागों को पोलारिस का उपयोग करना होगा। ऐप समीक्षा दिशानिर्देशों में स्पष्ट रूप से एम्बेडेड यूआई के लिए पोलारिस की आवश्यकता होती है। कस्टम घटकों के साथ पोलारिस को दृश्य रूप से दोहराने का प्रयास आमतौर पर व्यवहार और पहुंच संबंधी विसंगतियों के कारण समीक्षा अस्वीकृति में परिणत होता है।

मैं अपने ऐप में Shopify API दर सीमा को कैसे प्रबंधित करूं?

Shopify का GraphQL एडमिन API एक "बकेट" दर सीमित मॉडल का उपयोग करता है। प्रत्येक दुकान आपके ऐप को प्रति बाल्टी 1,000 लागत अंक देती है, जो प्रति सेकंड 50 अंक पर पुन: उत्पन्न होती है। GraphQL प्रतिक्रियाओं में extensions.cost.throttleStatus फ़ील्ड की निगरानी करें। बल्क ऑपरेशंस (हजारों रिकॉर्ड को प्रभावित करने वाले) के लिए, बल्क ऑपरेशंस एपीआई का उपयोग करें, जिसमें अलग-अलग दर सीमाएं हैं। 429 प्रतिक्रियाएँ प्राप्त होने पर घबराहट के साथ घातीय बैकऑफ़ लागू करें।

उत्पादन में मुझे अपने Shopify ऐप के लिए किस डेटाबेस का उपयोग करना चाहिए?

उत्पादन के लिए डिफ़ॉल्ट SQLite को PostgreSQL से बदलें। प्रिज्मा सेशन स्टोरेज एडॉप्टर PostgreSQL के साथ काम करता है - अपने पर्यावरण चर में कनेक्शन स्ट्रिंग बदलें और postgresql प्रदाता का उपयोग करने के लिए prisma/schema.prisma को अपडेट करें। उच्च सत्र मात्रा वाले ऐप्स के लिए, हॉट प्रमाणीकरण पथ पर डेटाबेस लोड को कम करने के लिए PostgreSQL के बजाय सत्र भंडारण के लिए Redis पर विचार करें।

मैं रीमिक्स के साथ निर्मित Shopify ऐप को कैसे तैनात करूं?

Shopify उन प्लेटफ़ॉर्म पर तैनाती की अनुशंसा करता है जो Node.js रनटाइम का समर्थन करते हैं: Fly.io, रेंडर, रेलवे, AWS (EC2/ECS), या Google क्लाउड रन। Vercel और Netlify फ्रंटएंड के लिए काम करते हैं लेकिन Shopify के सेशन स्टोरेज के लिए आवश्यक लगातार Node.js सर्वर को नहीं चला सकते हैं। सुनिश्चित करें कि आपका परिनियोजन प्लेटफ़ॉर्म वेबहुक प्रसंस्करण और पृष्ठभूमि नौकरियों के लिए लंबी चलने वाली प्रक्रियाओं का समर्थन करता है।


अगले चरण

प्रमाणीकरण, ग्राफक्यूएल डेटा प्रबंधन, वेबहुक और बिलिंग को सही ढंग से संभालने वाले एक कस्टम शॉपिफाई ऐप का निर्माण करने के लिए गहन प्लेटफ़ॉर्म विशेषज्ञता की आवश्यकता होती है। गलत तरीके से कॉन्फ़िगर किया गया ऐप ऐप स्टोर की समीक्षा में विफल रहता है, मर्चेंट स्टोर को तोड़ देता है, या सुरक्षा कमजोरियों को उजागर करता है।

ECOSIRE की Shopify ऐप डेवलपमेंट सेवाएं पूर्ण विकास जीवनचक्र को कवर करती हैं: आर्किटेक्चर डिज़ाइन, रीमिक्स/पोलारिस कार्यान्वयन, ग्राफक्यूएल एपीआई एकीकरण, वेबहुक इंफ्रास्ट्रक्चर, बिलिंग सेटअप, ऐप स्टोर सबमिशन और लॉन्च के बाद का समर्थन।

अपनी कस्टम Shopify ऐप आवश्यकताओं पर चर्चा करें हमारी विकास टीम के साथ।

शेयर करें:
E

लेखक

ECOSIRE Research and Development Team

ECOSIRE में एंटरप्राइज़-ग्रेड डिजिटल उत्पाद बना रहे हैं। Odoo एकीकरण, ई-कॉमर्स ऑटोमेशन, और AI-संचालित व्यावसायिक समाधानों पर अंतर्दृष्टि साझा कर रहे हैं।

WhatsApp पर चैट करें