Przejdź do treści

Jak zbudować szybki sklep e-commerce w Astro

Zbuduj szybki sklep w Astro z Shopify albo Stripe. Poznaj architekturę, koszyk, checkout, webhooki, cache, SEO produktów i pułapki wdrożenia.

Maciej Sala

Founder StriveLab

10 min czytaniaOpublikowano 28 sierpnia 2026 (Aktualizacja 28 sierpnia 2026)

Jaką rolę pełni Astro w sklepie internetowym

Astro buduje warstwę prezentacji, czyli stronę główną, kategorie, karty produktów, poradniki oraz interfejs koszyka, podczas gdy silnik e-commerce pozostaje nadrzędnym źródłem informacji o wariantach, cenach, stanach magazynowych i zamówieniach. Poza tym operator płatności autoryzuje transakcje, a system logistyczny obsługuje wysyłkę, zwroty lub dostęp do produktów cyfrowych.

Diagram
Astro jest frontendem sklepu, a nie systemem zamówień. Dane płyną z silnika commerce do strony, natomiast potwierdzenie płatności wraca do backendu przez webhook.

Właściwe rozdzielenie odpowiedzialności między systemami ma znacznie większe znaczenie niż sam wybór biblioteki koszyka. W sytuacji, kiedy cena lub stan magazynowy są równolegle zarządzane w dwóch różnych miejscach, prędzej czy później dojdzie do sytuacji, w której klient ujrzy w sklepie zupełnie inną ofertę niż tę, którą finalnie zatwierdzi checkout.

Trzy sensowne architektury e-commerce w Astro

Astro z headless Shopify

Shopify przechowuje produkty, warianty, zapasy, koszyki i zamówienia. Astro pobiera dane przez Storefront API, a do obsługi koszyka używa aktualnego Cart API: cartCreate, cartLinesAdd, cartLinesUpdate i cartLinesRemove. Pole checkoutUrl z koszyka prowadzi do Shopify Web Checkout.

To najczęściej najlepszy wariant dla standardowego sklepu. Dostajesz własny frontend bez odtwarzania panelu zamówień i podstawowej logiki commerce. Nadal musisz bezpiecznie skonfigurować tokeny, integracje, podatki, wysyłkę i proces obsługi klienta — platforma nie usuwa odpowiedzialności sprzedawcy.

Astro z własnym backendem commerce i Stripe Checkout

W tym wariancie Stripe obsługuje hostowaną stronę płatności, lecz Twój backend pozostaje odpowiedzialny między innymi za:

  • katalog oraz mapowanie SKU na aktualne ceny;
  • rezerwowanie i zmniejszanie stanów magazynowych;
  • rekord zamówienia oraz jego przejścia między stanami;
  • reguły podatkowe i fakturowanie, wysyłkę oraz proces zwrotów i reklamacji;
  • komunikację transakcyjną oraz ponawianie nieudanych operacji.

Część tych zadań może technicznie realizować Stripe, na przykład obliczanie podatku, wystawianie faktur, wykonywanie zwrotów i wysyłanie potwierdzeń. Własny backend nadal musi jednak spinać te funkcje z zamówieniem oraz regułami biznesowymi sklepu.

Warto go wybrać wtedy, gdy model sprzedaży jest rzeczywiście nietypowy albo sklep musi zostać głęboko połączony z istniejącym ERP. Sam fakt, że checkout ma być „customowy”, rzadko uzasadnia koszt budowy systemu zamówień.

Astro jako katalog z przekierowaniem do zewnętrznego checkoutu

Przy kilku produktach przycisk „Kup teraz” może prowadzić bezpośrednio do Shopify Checkout albo Stripe Payment Link. Nie ma wtedy własnego koszyka w Astro. To dobry model dla prostego produktu, przedsprzedaży lub małego katalogu, ale trudniej w nim budować wielopozycyjne zamówienia i zaawansowane promocje.

KryteriumAstro + ShopifyAstro + własny backend + StripeKatalog + przekierowanie
Zakres systemu commerceShopifyBudujesz i utrzymujeszMinimalny
Typowy czas wdrożeniaTygodnieMiesiąceDni
Elastyczność logikiDuża w granicach APINajwiększaMała
Koszt utrzymaniaŚredniWysoki i ciągłyNiski
Odpowiedzialność PCIWspółdzielona, ograniczony zakresWspółdzielona ze StripeWspółdzielona, ograniczony zakres
Najlepsze zastosowanieTypowy sklepNietypowy model sprzedażyMały katalog

Jak wyrenderować produkty z Shopify w Astro

W domyślnym trybie Astro strony są generowane statycznie. Dynamiczny plik src/pages/produkty/[handle].astro nie może więc polegać wyłącznie na Astro.params — podczas budowania trzeba podać wszystkie ścieżki przez getStaticPaths():

Code
---
// src/pages/produkty/[handle].astro
import ProductLayout from '../../layouts/ProductLayout.astro'
import AddToCartButton from '../../components/AddToCartButton.tsx'
import { getAllProducts } from '../../lib/shopify'
 
export async function getStaticPaths() {
  const products = await getAllProducts()
 
  return products.map((product) => ({
    params: { handle: product.handle },
    props: { product },
  }))
}
 
const { product } = Astro.props
---
 
<ProductLayout title={product.title}>
  <h1>{product.title}</h1>
  <p>{product.description}</p>
  <p>{product.price.amount} {product.price.currencyCode}</p>
 
  <AddToCartButton
    client:load
    merchandiseId={product.selectedVariant.id}
  />
</ProductLayout>

client:load jest właściwe, jeżeli główny przycisk zakupu znajduje się nad linią zgięcia i powinien działać natychmiast. client:visible zostaw dla elementów niżej na stronie, które można uruchomić dopiero po zbliżeniu do viewportu. Więcej o tym rozróżnieniu przeczytasz w przewodniku po dyrektywach klienta w Astro.

Jeżeli liczba produktów jest bardzo duża albo ceny muszą być odczytywane przy każdym żądaniu, wyrenderuj trasę na żądanie:

Code
---
// Projekt musi mieć adapter serwerowy.
export const prerender = false
 
const { handle } = Astro.params
const product = await getProductByHandle(handle)
---

Statyczny i dynamiczny wariant nie muszą się wykluczać. W praktyce najlepiej sprawdza się podejście hybrydowe, łączące statyczny opis produktu, przebudowę strony wywoływaną webhookiem z Shopify oraz krótkoterminowo cache’owane dane o aktualnej ofercie. Kluczowe jest bowiem to, aby klient nigdy nie dokonał zakupu na podstawie nieaktualnej lub błędnej ceny.

Koszyk Shopify: przechowuj identyfikator, nie kopię prawdy

Przeglądarka może zapamiętać cartId, ale zawartość i wyceny koszyka powinny pozostać w Shopify. Dodanie pozycji odbywa się przez cartLinesAdd, a odpowiedź serwera jest nowym źródłem danych wyświetlanych w interfejsie. Nie sumuj cen na stałe na podstawie starego stanu w localStorage.

Publiczny token Storefront API może być używany w przeglądarce zgodnie z modelem Shopify, lecz powinien mieć wyłącznie konieczne zakresy. Prywatny token pozostaje sekretem i może działać tylko po stronie serwera. Przy zapytaniach serwerowych wykonywanych w imieniu kupującego należy przekazać jego adres IP w nagłówku Shopify-Storefront-Buyer-IP. Nie dotyczy to zapytań wykonywanych podczas statycznego budowania strony, które nie są powiązane z konkretnym kupującym.

Jak bezpiecznie utworzyć Stripe Checkout przez Astro Actions

Astro Action dobrze nadaje się do utworzenia sesji checkoutowej, ponieważ klucz Stripe i mapowanie cen pozostają na serwerze. Definicja trafia do src/actions/index.ts, a Zod importujesz z astro/zod:

Code
// src/actions/index.ts
import { ActionError, defineAction } from 'astro:actions'
import { z } from 'astro/zod'
import Stripe from 'stripe'
 
const stripe = new Stripe(import.meta.env.STRIPE_SECRET_KEY)
 
const catalog = {
  starter: import.meta.env.STRIPE_PRICE_STARTER,
  pro: import.meta.env.STRIPE_PRICE_PRO,
} as const
 
export const server = {
  createCheckoutSession: defineAction({
    input: z.object({
      sku: z.enum(['starter', 'pro']),
      quantity: z.number().int().min(1).max(10),
    }),
    handler: async ({ sku, quantity }) => {
      const session = await stripe.checkout.sessions.create({
        mode: 'payment',
        line_items: [{ price: catalog[sku], quantity }],
        success_url: `${import.meta.env.SITE_URL}/dziekujemy?session_id={CHECKOUT_SESSION_ID}`,
        cancel_url: `${import.meta.env.SITE_URL}/koszyk`,
      })
 
      if (!session.url) {
        throw new ActionError({
          code: 'INTERNAL_SERVER_ERROR',
          message: 'Nie udało się utworzyć sesji płatności.',
        })
      }
 
      return { url: session.url }
    },
  }),
}

Kluczowa różnica względem wielu internetowych poradników polega na tym, że klient przesyła wyłącznie SKU, a nigdy priceId, cenę czy dowolną kwotę. To serwer samodzielnie przypisuje identyfikator Stripe Price z zaufanego, wewnętrznego katalogu produktów – w przeciwnym razie atakujący mógłby łatwo podmienić identyfikator w żądaniu lub próbować sfinalizować zakup na nieautoryzowanych warunkach.

Actions wymagają środowiska serwerowego i adaptera, choć sama strona wywołująca akcję z JavaScriptu może pozostać prerenderowana. Pełne zasady opisuję w artykule jak bezpiecznie obsługiwać formularze w Astro.

Webhook Stripe jest źródłem prawdy o płatności

Strona /dziekujemy nie potwierdza płatności. Użytkownik może ją otworzyć ręcznie, zamknąć kartę przed powrotem albo skorzystać z metody płatności finalizowanej z opóźnieniem. Realizację zamówienia uruchamia dopiero zweryfikowany webhook Stripe.

Code
// src/pages/api/stripe-webhook.ts
import type { APIRoute } from 'astro'
import Stripe from 'stripe'
import { fulfillOrderOnce, markOrderPaymentFailed } from '../../lib/orders'
 
export const prerender = false
 
const stripe = new Stripe(import.meta.env.STRIPE_SECRET_KEY)
 
export const POST: APIRoute = async ({ request }) => {
  const body = await request.text()
  const signature = request.headers.get('stripe-signature')
 
  if (!signature) return new Response('Missing signature', { status: 400 })
 
  let event: Stripe.Event
 
  try {
    event = stripe.webhooks.constructEvent(
      body,
      signature,
      import.meta.env.STRIPE_WEBHOOK_SECRET,
    )
  } catch {
    return new Response('Invalid signature', { status: 400 })
  }
 
  if (
    event.type === 'checkout.session.completed' ||
    event.type === 'checkout.session.async_payment_succeeded'
  ) {
    const session = event.data.object
    await fulfillOrderOnce(session.id)
  }
 
  if (event.type === 'checkout.session.async_payment_failed') {
    const session = event.data.object
    await markOrderPaymentFailed(session.id)
  }
 
  return new Response(null, { status: 200 })
}

fulfillOrderOnce() pobiera aktualną sesję ze Stripe i realizuje zamówienie tylko wtedy, gdy payment_status ma wartość paid albo no_payment_required. Funkcja musi być idempotentna, czyli ponowne dostarczenie zdarzenia nie może drugi raz zmniejszyć stanu, wysłać produktu ani utworzyć faktury. Jako unikalny klucz realizacji zapisujesz session.id lub wewnętrzny identyfikator zamówienia w tej samej transakcji bazodanowej co zmianę stanu. event.id może dodatkowo chronić przed ponownym przetworzeniem identycznego zdarzenia, ale nie zastępuje klucza zamówienia, ponieważ różne zdarzenia mogą dotyczyć tej samej sesji. markOrderPaymentFailed() również musi działać idempotentnie i zmieniać stan tylko tego zamówienia, które nadal oczekuje na płatność.

Cache i aktualność cen oraz stanów magazynowych

SSG daje szybki HTML, ale build nie może zamrozić oferty na wiele dni. Wybierz jawny model aktualizacji:

  1. Build wyzwalany webhookiem — dobry przy małym katalogu i rzadkich zmianach.
  2. Renderowanie na żądanie z krótkim cache — dobre przy częstych zmianach i większym katalogu.
  3. Hybryda — statyczna treść marketingowa, a oferta pobierana lub odświeżana niezależnie.

Niezależnie od wariantu checkout powinien ponownie zweryfikować SKU, cenę, dostępność i dopuszczalną ilość. Cache poprawia czas odpowiedzi, ale nie może być mechanizmem blokowania zapasu. Przy ostatnich sztukach potrzebujesz rezerwacji albo atomowego sprawdzenia stanu w systemie commerce.

SEO produktów w Astro: HTML, JSON-LD i Merchant Center

Każda strona produktu powinna dostarczać w pełni indeksowalny opis oraz aktualną ofertę bezpośrednio w kodzie HTML. W danych strukturalnych Product i Offer umieść przynajmniej nazwę, zdjęcia, cenę, walutę, dostępność oraz link do oferty, dla wariantów stosując model zalecany w oficjalnej dokumentacji Google, a tam gdzie to możliwe – uzupełniając je o warunki wysyłki i zwrotów.

Najważniejszą zasadą jest spójność. Format JSON-LD ma wiernie odzwierciedlać to, co faktycznie widzi użytkownik na ekranie, więc unikaj publikowania nieaktualnych cen, zmyślonej dostępności czy ocen, których fizycznie nie ma w serwisie. Choć uporządkowane dane znacząco zwiększają szanse na uzyskanie atrakcyjnych wyników rozszerzonych, nigdy ich nie gwarantują, dlatego w przypadku sklepów internetowych najlepiej łączyć je bezpośrednio z feedem Google Merchant Center.

Poza JSON-LD dopilnuj:

  • osobnego, kanonicznego URL dla indeksowalnych produktów;
  • sensownej strategii dla wariantów, filtrów i parametrów;
  • mapy witryny bez nieaktywnych produktów oraz poprawnych przekierowań;
  • unikalnych tytułów i opisów zamiast kopii opisu producenta;
  • zdjęć o właściwych wymiarach, formacie i tekstach alternatywnych.

Więcej szczegółów znajduje się w przewodniku SEO w Astro: Core Web Vitals, structured data i techniczny fundament.

Wydajność sklepu: Astro pomaga, ale nie gwarantuje wyniku

Astro domyślnie nie wysyła zbędnego kodu JavaScript dla komponentów statycznych, jednak e-commerce wciąż może działać powoli przez gigantyczne zdjęcia produktów, osadzone skrypty marketingowe, widżety czatu, niewłaściwie dobraną strategię hydratacji czy opóźnienia po stronie zewnętrznego API. W praktyce największe efekty optymalizacyjne przynoszą:

  • priorytet dla obrazu LCP i responsywne warianty srcset/sizes;
  • małe wyspy dla koszyka, wyszukiwarki i wyboru wariantu;
  • budżet na JavaScript zewnętrzny oraz kontrola tagów analitycznych;
  • cache zapytań katalogowych i szybki region serwera;
  • pomiar Core Web Vitals na danych rzeczywistych, nie tylko w Lighthouse.

Lepsze Core Web Vitals wspierają doświadczenie użytkownika i są częścią technicznego SEO, ale sam wybór Astro nie gwarantuje wyższej konwersji ani pozycji w Google. Architektura wysp ma sens tylko wtedy, gdy naprawdę ograniczasz hydratację — szerzej opisuję to w artykule czym są wyspy w Astro.

Checklista wdrożenia sklepu w Astro

  • Jedno źródło prawdy. Produkty, ceny, waluty, warianty i stany mają właściciela; frontend nie utrzymuje konkurencyjnej kopii.

  • Bezpieczne sekrety. Prywatne tokeny Shopify i klucze Stripe nigdy nie trafiają do kodu przeglądarki ani publicznych zmiennych środowiskowych.

  • Walidacja po stronie serwera. Checkout ponownie sprawdza SKU, ilość, cenę, dostępność, walutę i uprawnienia do promocji.

  • Idempotentne webhooki. Powtórzone i dostarczone w innej kolejności zdarzenia nie realizują zamówienia dwukrotnie.

  • Pełny cykl zamówienia. Zdefiniowane są płatność, anulowanie, zwrot, brak towaru, ponowienie webhooka oraz kontakt z klientem.

  • Obserwowalność. Monitorujesz błędy API, opóźnienia webhooków, rozbieżności stanów i nieudane płatności bez logowania danych wrażliwych.

  • Zgodność oferty. Cena i dostępność w HTML, JSON-LD, feedzie produktowym, koszyku i checkoutcie są spójne.

  • Obowiązki prawne. Dla sprzedaży konsumenckiej w UE sprawdzasz informacje przed zakupem, całkowitą cenę, dostawę, zasady odstąpienia i wyjątki. Przy komunikowaniu obniżki w Polsce uwzględniasz najniższą cenę z 30 dni przed obniżką.

Ostatni punkt wymaga dokładnego dopasowania do specyfiki rynku, oferty oraz modelu biznesowego danej firmy, a niniejszy artykuł ma charakter wyłącznie informacyjny i nie zastępuje profesjonalnej porady prawnej. Warto pamiętać, że ustawowe prawo odstąpienia od umowy posiada szereg ważnych wyjactków – dotyczy to chociażby dostarczania niektórych treści cyfrowych, w przypadku których prawo to wygasa po spełnieniu dodatkowych warunków.

Kiedy nie wybierać Astro do e-commerce

Astro nie zawsze sprawdza się jako najlepszy wybór dla frontendu e-commerce. Gotowy motyw na Shopify lub dedykowany framework Hydrogen mogą zaoferować niższy całkowity koszt utrzymania, jeśli Twój biznes mocno opiera się na ekosystemie Shopify: aplikacjach, zaawansowanym koncie klienta, sprzedaży B2B, subskrypcjach, programach lojalnościowych czy integracjach z terminalami POS. Decydując się na własną warstwę prezentacji, musisz liczyć się z tym, że każdą kluczową funkcję trzeba dostosować do architektury headless i stale utrzymywać w zgodzie z aktualizacjami API.

Co więcej, budowanie własnego backendu ze Stripe mija się z celem, jeśli jedynym powodem jest chęć modyfikacji wyglądu procesu zakupu. W takich sytuacjach hostowany checkout od Shopify, gotowy Stripe Checkout czy dobrze dopasowany motyw pozwalają osiągnąć cel szybciej i przy znacznie mniejszym ryzyku operacyjnym.

Ultraszybkie projekty, łączące lekkość ze skalowalnością.
Astro

Często zadawane pytania

Czy Astro nadaje się do budowy sklepu internetowego?

Tak, jako szybka warstwa prezentacji sklepu. Astro nie dostarcza jednak katalogu, magazynu, koszyka, płatności ani obsługi zamówień. Te funkcje powinien zapewnić silnik commerce, na przykład Shopify, albo własny backend połączony ze Stripe.

Co wybrać do Astro — Shopify czy Stripe?

Shopify jest kompletnym silnikiem commerce i zwykle będzie lepszym wyborem dla standardowego sklepu. Stripe obsługuje płatności i oferuje między innymi narzędzia do podatków, faktur i zwrotów, ale nie zastępuje katalogu, magazynu ani pełnego procesu obsługi zamówień. Wariant ze Stripe ma sens, gdy niestandardowa logika uzasadnia budowę tych elementów.

Jak zachować aktualne ceny i stany na statycznej stronie Astro?

Można przebudowywać stronę po webhooku z platformy, renderować produkty na żądanie z kontrolowanym cache albo pobierać krytyczne dane dynamicznie. Cena i dostępność widoczne dla użytkownika muszą być zgodne z danymi Product i Offer w JSON-LD.

Czy Astro Actions wystarczą do obsługi płatności Stripe?

Action dobrze nadaje się do utworzenia sesji Stripe Checkout, ale webhook Stripe powinien trafić do zwykłego endpointu serwerowego. Dopiero zweryfikowany webhook jest wiarygodnym sygnałem do realizacji zamówienia.

Czy przekierowanie do Shopify lub Stripe usuwa obowiązki PCI DSS?

Nie całkowicie. Hostowany checkout istotnie ogranicza zakres techniczny, ponieważ dane karty obsługuje dostawca płatności, lecz PCI DSS pozostaje współdzieloną odpowiedzialnością i sprzedawca nadal musi spełnić właściwe dla swojej integracji wymagania.

O autorze

Maciej Sala

Maciej Sala — konsultant technologiczny produktów cyfrowych i web developer z bogatym doświadczeniem w marketingu internetowym oraz SEO. Na co dzień pracuje z Reactem, Next.js i TypeScriptem, a ostatnio także z Astro i narzędziami do automatyzacji procesów AI. Sprawnie łączy perspektywę produktową z praktycznym podejściem do kodu. Przez kilka lat był związany z branżą gier wideo jako project manager i game designer. Absolwent historii na Uniwersytecie Jagiellońskim oraz studiów podyplomowych z marketingu internetowego na AGH w Krakowie. Po godzinach trenuje na siłowni, maluje figurki i rozwija własne projekty.

Pomagam przekładać takie tematy na konkretne wdrożenia w frontendzie, SEO, analityce i procesie produktowym.

Skontaktuj się ze mną

Biblioteka wiedzy na temat Astro

Czytaj dalej

Zobacz więcej wpisów
Stripe w Next.js: Kompletny poradnik integracji

Płatności to moment, w którym aplikacja przestaje być demem. Tu błąd nie kończy się tylko błędem w konsoli, ale pieniędzmi, dostępem użytkownika albo chaosem w subskrypcjach. Stripe w Next.js App Router daje gotowe klocki: Checkout, Customer Portal i webhooki. Pokażę, jak je połączyć tak, żeby baza zgadzała się z tym, co naprawdę wydarzyło się w Stripe.

Maciej Sala

Maciej Sala

Founder StriveLab

Co zrobić, gdy WooCommerce zwalnia? Przewodnik decyzyjny

WooCommerce często bywa naturalnym wyborem na start, jednak wraz ze skalowaniem biznesu platforma ta potrafi stać się barierą technologiczną. Spowolniony proces zakupowy, pogarszające się wskaźniki PageSpeed i przeciążony panel administracyjny to sygnały, że system przestaje nadążać za wzrostem. W tym artykule analizujemy trzy strategiczne kierunki rozwoju: kiedy warto utrzymać klasyczną architekturę WooCommerce, w jakich sytuacjach optymalne będzie odcięcie frontendu Headless i Next.js , a kiedy jedynym słusznym krokiem jest migracja na inny silnik, taki jak Shopify czy Medusa. Całość wieńczy praktyczna matryca decyzyjna.

Maciej Sala

Maciej Sala

Founder StriveLab

Astro vs Next.js w 2026: porównanie frameworków

Astro czy Next.js? Wybór frameworka musi być dokładnie przemyślany, zanim pojawi się pierwszy commit. Jeśli stoisz przed takim właśnie wyborem, w tym artykule staram się wykazać, w jakich obszarach najlepiej sprawdza się Astro , a w jakich będzie dominował Next.js .

Maciej Sala

Maciej Sala

Founder StriveLab