# Build an online store with AI: a small catalogue, not a Shopify clone

> Build an online store with AI in NorthernGo: Pro Shopify storefront, or a tiny catalogue you store yourself. Stripe checkout. Honest limits, not a full shop.

Source: https://northerngo.com/resources/build-an-online-store-with-ai/
Language: en
Updated: 2026-08-16

---
**NorthernGo does not replace Shopify. On Pro you connect a Shopify store you already own and build a storefront with window.NorthernGoShopify.getProducts() and .checkout(). Without Shopify you store a small catalogue in window.NorthernGoDB and send the buyer to Stripe. Either path is a focused page plus a hand-off. Neither is a full shop with tax, stock and fulfilment.**

### Say the quiet part first

An [AI app builder](/glossary/ai-app-builder/) will happily draw a shop: a grid of cards, a cart icon, a button that says Checkout. That drawing is not a shop. A shop calculates VAT, holds stock, takes card details without you ever seeing them, e-mails a receipt, and tells a warehouse what to pack. NorthernGo does none of that as a product.

Two honest paths exist.

**Path A, Pro only.** You already have a Shopify store. You connect it to the project. The generated app is a front end: `window.NorthernGoShopify.getProducts()` fills the grid, `window.NorthernGoShopify.checkout([{ variantId, quantity }])` sends the buyer to Shopify's own checkout. Shopify keeps payment, tax, discounts, shipping and the order admin. You replaced the theme, not the shop.

**Path B, any plan that can save data.** You have a handful of products — a print, a course, three jars of honey from a farm outside Lycksele — and you store them yourself with `window.NorthernGoDB.save()`. The cart is an array in the browser. Checkout is [your own Stripe account](/resources/integrate-stripe-payments-saas/), on Pro, via the Stripe guide. You are responsible for stock, VAT, receipts and shipping. The app is a catalogue plus a payment hand-off.

If someone promised you a full Shopify replacement from a paragraph of text, they promised something this platform does not sell. Read the rest only if one of those two paths is actually what you need.

### Step 1: Choose the shape before you prompt

Write the constraint into the first message. The model defaults to a generic fashion store with twelve navigation items and a size picker it cannot back with data.

Choose one:

> I already have a Shopify store. Build a storefront that fetches products with window.NorthernGoShopify.getProducts() and checks out with window.NorthernGoShopify.checkout(). One collection page, a product page, a cart. No fake size picker. Use the price field from each product.

or:

> I do not have Shopify. Build a small catalogue of at most twelve products I store with window.NorthernGoDB. Each product has id, name, priceSek, description, imageUrl. Cart is an array in memory. Checkout button starts Stripe — do not invent card fields.

Those two prompts produce different apps. Mixing them — "fetch from Shopify and also save products in the database and also take cards in a form" — is how you get a page that pretends to charge people and never does.

Cloud generation uses Gemini: five a month on Free, 25 on Premium (179 SEK / $19), 50 on Pro (299 SEK / $29). Local WebGPU (Qwen 3.5 4B, or larger Pro models) or Ollama is unlimited on every plan. The first scaffold of a shop is a reasonable cloud spend. Tweaking button labels is not.

### Step 2: If you have Shopify, connect it on Pro

Save the project first. The integration is keyed to a project id.

Then My projects, More on the project card, Shopify. Two fields: the shop domain as `your-store.myshopify.com`, and a Storefront API access token from Shopify admin — not an Admin API key, not your password. Save Shopify. The domain showing on the card is the confirmation it stored.

This is Pro at 299 SEK / $29. Free and Premium will not fetch products. There is no trial Shopify switch.

Ask the builder to call the real methods, not to invent a product array:

```javascript
async function loadCatalogue() {
  if (!window.NorthernGoShopify || typeof window.NorthernGoShopify.getProducts !== 'function') {
    showMessage('Shopify is not connected on this project.');
    return [];
  }
  const products = await window.NorthernGoShopify.getProducts();
  return products || [];
}

function checkoutCart(cart) {
  window.NorthernGoShopify.checkout(cart.map(line => ({
    variantId: line.variantId,
    quantity: line.quantity
  })));
}
```

Know the ceiling before you advertise a catalogue. The call returns the first 20 products, one image each, one variant each. A 200-product store with three sizes is the wrong shape. A landing page for one product, or a short collection, is the right one. Shopify still owns the rest of the catalogue behind its own checkout.

### Step 3: If you do not have Shopify, store a tiny catalogue yourself

Twelve products is a shop a person can curate. Two hundred is a job for a real commerce platform.

```javascript
async function saveProduct(product) {
  await window.NorthernGoDB.save('products', {
    id: product.id || crypto.randomUUID(),
    name: product.name,
    priceSek: Number(product.priceSek) || 0,
    description: product.description || '',
    imageUrl: product.imageUrl || '',
    active: product.active !== false
  });
}

async function loadProducts() {
  const all = (await window.NorthernGoDB.get('products')) || [];
  return all.filter(row => row.active !== false);
}
```

The [database is already wired](/resources/connect-supabase/). No schema. `priceSek` must be a number; the model will concatenate strings into "199199" the first time someone buys two.

Seed the catalogue from an admin screen you hide behind login, not from a loop that runs on every visit. A loop on load duplicates the honey jars every time a buyer refreshes.

Images are URLs you host somewhere else, or files you put on your own hosting after a ZIP export. There is no product-image CDN in the builder. A broken image is a broken product page. Check them.

Login on the storefront is optional. Login on the admin screen that can save products is not. An open `save('products')` on a public URL is how a stranger adds a product named after themselves. Gate writes on `getToken()`. If that admin account has login, it also needs a visible delete-account button that calls `window.NorthernGoDB.deleteAccount()` after confirm. That is GDPR article 17 for the shop owner too.

### Step 4: The cart is an array, not a platform

Whether the products came from Shopify or from your collection, the cart in the page is ordinary JavaScript.

```javascript
let cart = [];

function addToCart(product, quantity) {
  const qty = Math.max(1, Number(quantity) || 1);
  const existing = cart.find(line => line.id === product.id);
  if (existing) {
    existing.quantity += qty;
  } else {
    cart.push({
      id: product.id,
      name: product.name,
      priceSek: Number(product.priceSek) || 0,
      variantId: product.variantId || null,
      quantity: qty
    });
  }
  renderCart(cart);
}

function cartTotal(lines) {
  return lines.reduce((sum, line) => sum + Number(line.priceSek) * Number(line.quantity), 0);
}
```

For Shopify, what you must hand to checkout is `variantId` and `quantity`. Names and prices in your cart are for display. Shopify will charge its own price. If you show 199 SEK and Shopify has 249, the buyer sees 249 on the hosted checkout. That is correct and it surprises people. Do not invent a second price.

For a self-stored catalogue, the cart total is the amount you will send to Stripe. Round to whole kronor if that is how you sell. The cart does not survive a refresh unless you save it. `localStorage` is fine for a tiny shop and is not a stock system. Do not put card numbers or national identity numbers anywhere.

### Step 5: Hand off to checkout — Shopify or Stripe, never a card form

**Shopify path.** One call. The buyer leaves your page and finishes on Shopify. You do not see the card. You do not calculate shipping in the app. If checkout fails, the usual cause is a missing `variantId` or a store that is not connected on Pro.

**Stripe path.** Follow the Stripe guide. You paste your own secret key on Pro. The app opens a Checkout session with line items. Card and Klarna land on Stripe's page. NorthernGo never sees card details. You are the merchant: refunds, terms of sale, VAT, support.

There is no third path where the generated app draws card number, expiry and CVC fields and "just charges". If the model builds that form, delete it. You would be collecting payment data you are not allowed to store and cannot process.

A catalogue without checkout is still useful: a list with prices and a `window.NorthernGo.sendEmail` order request. That is a mail-order page, not a store. Call it that. After a successful Stripe or Shopify hand-off, do not invent an order admin unless you persist orders yourself. Shopify already has orders. On the Stripe path, a thin order record is how you know what to pack. Keep it thin. Buyer e-mail if they gave it; not a card number.

### Step 6: Publish a page you can leave

Publish from My projects. Premium and Pro get a subdomain; Pro can bind a custom domain, which is what a shop should use. Free always uses the fallback address — fine for a mock, wrong for a buyer.

ZIP export on Premium and Pro is the other half of [not being locked in](/glossary/vendor-lock-in/). The storefront is vanilla JS and Tailwind in one HTML file. Shopify and Stripe calls still point at this platform until you replace them. The layout, the copy and the cart logic come with you.

PWA is automatic. The shell can load on a slow train. Product fetches and checkout will not work offline. A buyer with no signal should see a clear empty state, not a cart that claims to have paid.

### What this will not become

- **Not a Shopify replacement.** Pro connects a store you already pay Shopify for. No theme editor, no 200-product catalogue with variants.
- **Not a full commerce platform.** No VAT engine, no shipping rates, no warehouse. Hosted checkout only — never card fields in the app.
- **Not size and colour pickers on the Shopify path.** One variant and one image per product from `getProducts()`.

### What it costs

Free: 0 SEK, five cloud generations, unlimited local. No Shopify, no Stripe key, no ZIP. Premium: 179 SEK / $19, 25 cloud, ZIP — still no Shopify or Stripe keys. Pro: 299 SEK / $29, 50 cloud, Shopify, Stripe keys, custom domains, SEO audits, webhooks and Fortnox. Shopify and Stripe are separate bills.

### Troubleshooting

**The grid is empty on Pro.** Store not connected, project not saved first, or `getProducts()` never called. Confirm the domain on the card.

**Checkout does nothing.** Missing `variantId`, not Pro, or a card form the model invented. Delete the card form. `Number(...)` before multiplying prices. A size picker that charges one variant is expected — one `variantId` comes back. Put login in front of catalogue writes; leave the storefront public.

## Frequently asked questions

### Can NorthernGo replace Shopify for my online store?

No. On Pro it can be a storefront in front of a Shopify store you already own, using getProducts and checkout, while Shopify keeps payments, tax and orders. Without Shopify you can store a small catalogue yourself and hand the buyer to Stripe. Neither path is a full commerce platform.

### Do I need the Pro plan to build a shop?

You need Pro to connect Shopify or to save Stripe keys. Free and Premium can generate a catalogue interface and, on Premium, export the ZIP, but they cannot complete a real checkout. Pro is 299 SEK / $29 a month. Shopify and Stripe are billed separately.

### How do payments work if I build a tiny catalogue without Shopify?

On Pro you connect your own Stripe account and open a hosted Checkout session with line items. Card details never touch the app. Follow the Stripe payments guide rather than letting the model draw card number fields. You remain the merchant for refunds, VAT and support.

### How many products can an AI-built NorthernGo store show?

The Shopify integration returns the first 20 products, one image and one variant each. A self-stored catalogue has no hard cap in the database, but a tiny curated list is the honest design. A 200-product shop with sizes belongs in Shopify, not in this builder.

### Should the generated app take card numbers in a form?

No. Delete that form if the model builds it. Card details belong on Stripe Checkout or Shopify checkout. NorthernGo never sees them, and the built-in database must not store card numbers or national identity numbers.

---

## Related

- [How to accept payments in an AI-built app with your own Stripe keys](https://northerngo.com/resources/integrate-stripe-payments-saas/)
- [Building GDPR-compliant apps: a practical checklist for EU founders](https://northerngo.com/resources/gdpr-compliant-app-building-eu/)
- [How to avoid vendor lock-in when building with an AI app builder](https://northerngo.com/resources/avoid-vendor-lock-in-ai-builders/)

---

NorthernGo is an AI-powered platform for building production-ready web apps with zero coding. Local AI generation via WebGPU is unlimited and free, and you own all generated source code. https://northerngo.com/
