DOKÜMANTASYON

nuvinode ile geliştir

Hızlı başlangıçlar, kavramlar, entegrasyon kılavuzları, geçiş playbook'ları ve SDK örnekleri — nuvinode destekli bir mağazayı baştan sona yayınlamak için ihtiyacın olan her şey.

HIZLI BAŞLANGIÇ

Beş dakikalık başlangıç

Kayıttan canlı mağazaya, baştan sona.

nuvinode, dakikalar içinde şık ve production'a hazır bir mağazayı çalışır hale getirmek üzere kurgulandı (domain/DNS daha uzun sürebilir). Beş adım:

  1. Kaydol nuvinode.com/register — e-posta + parola, kart yok.
  2. Tema seç. Her tema örnek ürünler ve 8–12 önceden yapılandırılmış bölümle gelir. İçeriğini kaybetmeden istediğin zaman tema değiştirebilirsin.
  3. Domain bağla (opsiyonel ama önerilir). Panelden ara ya da elindeki domaini yapıştır — DNS otomatik kurulabilir; SSL genellikle dakikalar içinde inişer.
  4. Stripe ya da Iyzico bağla. Tek tıkla OAuth ya da nuvinode üzerinden taze merchant hesabı aç.
  5. Hero'nu düzenle Tema Editöründe — yeni bölüm sürükle, başlığı değiştir, renkleri ayarla. Yayınla'ya bas.

Hepsi bu. Artık checkout, müşteri hesabı, blog ve AI asistanlı tam çalışan bir mağazan var.

TIP
22 modülün hepsi ilk günden dahil — ücretsiz ve sınırsız, Starter'dan Enterprise'a her planda. Blog'u veya form yapıcıyı "açmak" için plan seçmiyorsun — panelinde seni bekliyorlar. Her planda işlem ücreti %0 ve 24 AI yeteneğinin tümü aynı şekilde çalışır; planlar yalnızca site sayısı ve performansta farklılaşır.
HIZLI BAŞLANGIÇ

Temel kavramlar

Modüller, temalar, bölümler ve sayfalar nasıl birleşir.

nuvinode dört kavramsal katmandan oluşur. Aralarındaki ilişkiyi anlamak her şeyi kolaylaştırır:

Modüller

Platformun yetenekleri: blog, sayfa, teklif, arama, tema, para birimi, vs. 22 tane var, her planda dahil. Modül = bir yetenek için veri + API + admin UI. Modülleri kurmazsın ya da yapılandırmazsın — her zaman açıklar.

Temalar

Mağazanın görünüşü. Tema; tasarım token'larını (renk, font, boşluk), bölüm tanımlarını ve varsayılan ayarları paketler. Tema değiştirmek içeriği kaybetmeden görünümü değiştirir.

Bölümler

Birleştirilebilir görsel bloklar: hero, özellik grid'i, fiyat, referanslar, SSS, CTA. Her bölüm içeriğini JSON ayarlarından okuyan bir React komponenti. Editör üzerinden sürükleyip sıralarsın.

Sayfalar

Storefront'undaki rotalar. Ana sayfa, ürün detayı, blog yazısı ve özel sayfalar (hakkında, kariyer vs.) sayfadır. Sayfa = bölüm listesi + içerik verisi (başlık, slug, SEO meta). Sayfalar page modülünde tutulur.

NOTE
Aynı bölüm bileşeni anasayfada, özel bir landing page'de veya blog yazısının içinde render olur. Beğendiğin bir hero'yu bir kez yapılandırınca her yere bırakabilirsin.
KAVRAMLAR

Modüller nasıl çalışır

Mimari, bağımlılık, yaşam döngüsü.

Her modül bağımsız bir NPM paketidir — @nuvi/module-blog, @nuvi/module-quote, vs. Kendi veri modeli, servis sınıfı, manifest ve admin route'ları ile gelirler.

Modüller standartları paylaşır ama bağımsızdır: birini etkinleştirmek/kapatmak (module-setting üzerinden) diğerlerini bozmaz. Çoğu modülün sıkı bağımlılığı yoktur; olanlar bunu manifest.json'da belirtir.

Yaşam döngüsü

Platform boot olduğunda module loader ENABLED_MODULES env değişkenini okur, her modülün MikroORM entity'lerini kaydeder, admin ve storefront API route'larını mount eder ve servis sınıfını cross-module çağrılar için açar.

Cross-module çağrılar

Bir modül başka modülün servisini Medusa container üzerinden çağırabilir; örn. quote modülü page modülünden veri okuyup template render eder. HTTP atlama yok — servisler DI container'ından çözülen JS sınıfları.

TIP
Modüller indeksini tek sayfa özet için, /modules/<slug> daha derin pazarlama sayfaları için oku.
KAVRAMLAR

Kimlik doğrulama

API anahtarları, müşteri JWT, admin token.

Üç kimlik bağlamı ile çalışırsın:

Publishable API anahtarı

Her storefront isteğinde x-publishable-api-key olarak gönderilir. Çağrının hangi mağaza / bölgeye ait olduğunu belirler; istemci kodda paylaşmak güvenli. Her site için otomatik oluşturulur — Panel'inde bulabilirsin.

Müşteri JWT

POST /auth/customer/emailpass ile alınır. Giriş yapmış alıcıyı tanımlar. /store/customers/me, /store/orders/me, /store/subscriptions uçları için gerekli. Authorization: Bearer ... olarak gönder.

Admin token

Sunucu tarafı admin araçları ve entegrasyonlar için. İstemci kodda asla paylaşma. Sadece kendi backend'inden ya da CLI'dan kullan.

Yetkili storefront çağrısı
curl https://nuvinode.com/api/store/customers/me \
  -H "x-publishable-api-key: pk_live_..." \
  -H "Authorization: Bearer <customer-jwt>"
WARNING
Frontend'e asla admin token'ı gömme. Sunucu-sadece işlemler (fiyat override, toplu güncelleme) gerekiyorsa kendi backend'inden proxy yap.
KILAVUZLAR

İlk ürününü ekle

Ürün oluşturmadan canlı PDP'ye.

En hızlı yol: Panel → Ürünler → Yeni ürün. Dolduracağın alanlar:

  • Başlık + handle. Handle URL slug olur (/products/your-handle).
  • Açıklama. Görsel gömme destekli rich-text editör. PDP'de olduğu gibi render olur.
  • Varyantlar. Ürünün seçenekleri varsa (boy, renk) varyant satırları olarak ekle. Her varyantın kendi fiyatı ve SKU'su var.
  • Görseller. Sürükle-bırak yükleme. İlk görsel kapak olur; sürükle ile sırala.
  • SEO. Opsiyonel meta başlık + açıklama. Boşsa ürün başlığı + ilk 160 karakter açıklamaya düşer.

Yayınla'ya bas. Ürün https://magazan.com/products/your-handle'de saniyeler ila birkaç dakika içinde canlı — Next.js sayfayı statik olarak regenerate eder.

TIP
Import modülünü CSV'den toplu ürün eklemek ya da mevcut Shopify / WooCommerce mağazandan çekmek için kullan. Yaygın kolonlar için alan eşleştirme otomatik.
KILAVUZLAR

Özel domain bağla

magazan.usenuvi.com'dan markaadi.com'a adım adım geç.

İki yol var:

nuvinode üzerinden satın al

Panel → Domain'ler'de domain ara. 500+ TLD arasından seç. Yıllık $15–30 (fiyatlara bak). Ödeme onaylandıktan sonra DNS otomatik kurulabilir; SSL genellikle dakikalar içinde inişer.

Kendi domainini getir

Zaten başka yerde domainin var mı? Aynı ekrandan ekle. Registrar'ında eklemen gereken CNAME / A kayıtlarını gösteririz. Yayılma tamamlanınca (genellikle 10–30 dk) SSL otomatik kurulur.

NOTE
Hem www.markaadi.com hem markaadi.com kutudan çıkar çıkmaz çalışır — apex (www-suz) kanoniktir, www 301 ile ona yönlendirilir.

Başka platformdan taşınıyorsan, Redirect modülü eski URL'lerine 301 önceden üretir; SEO değeri yeni URL'lere akar.

KILAVUZLAR

E-postanı kur

Kendi domain'inde mailbox — webmail + her mail uygulaması.

Kendi domain'inde profesyonel e-posta (sen@markaadi.com) — 15 GB alan, tam IMAP/SMTP/POP3, webmail, takvim & kişiler.

1. Mailbox oluştur

Panel → Ayarlar → E-posta'dan domain'ini ekle ve mailbox oluştur. Mailbox $5/ay ek hizmettir (hizmete bak). DNS kayıtları (MX, SPF, DKIM, DMARC) nuvinode-yönetilen domain'lerde otomatik eklenir; harici domain'de registrar'ına yapıştıracağın kayıtları gösteririz.

2. Webmail

mail.nuvinode.com'u aç ve tam e-posta adresin + şifrenle giriş yap. Webmail'de mail, takvim, kişiler, filtreler ve spam kontrolü var.

3. Kendi uygulamana bağla

Apple Mail, Outlook, Gmail ya da telefonunun mail uygulamasını mı tercih ediyorsun? Şu ayarları kullan:

Gelen — IMAP
Sunucu:   mail.op-email.eu
Port:     993
Güvenlik: SSL/TLS
Kullanıcı: sen@markaadi.com
Şifre:    mailbox şifren
Giden — SMTP
Sunucu:   mail.op-email.eu
Port:     587
Güvenlik: STARTTLS
Kullanıcı: sen@markaadi.com
Şifre:    mailbox şifren

iPhone / iPad: Ayarlar → Mail → Hesaplar → Hesap Ekle → Diğer → Posta Hesabı Ekle, sonra yukarıdaki değerleri gir. Apple Mail / Outlook / Gmail app / Android: "Diğer" / "IMAP" seç, aynı ayarları kullan. POP3 da 995 (SSL) portunda mevcut.

TIP
Çoğu kişi kendi mail uygulamasını kullanır — bağlanınca mailbox'ın diğer hesaplarının yanında, tamamen kendi markanda görünür.

4. Şifre, 2FA & alias

Mailbox panelinden şifreni değiştir, iki adımlı doğrulamayı aç ya da uygulama-başı şifre oluştur. Alias'lar (örn. satis@ → gelen kutun) ücretsizAyarlar → E-posta → Yönlendirme'den ekle.

NOTE
Mail gelmiyor mu? Kurulumdan sonra DNS yayılması için bir saate kadar bekle ve MX/SPF/DKIM kayıtlarının olduğunu doğrula (Ayarlar → E-posta'da listeli).
KILAVUZLAR

Tema özelleştir

Token, bölüm, düzen — kodsuz.

Panelden Tema Editörü'nü aç. Genelden özele üç katman özelleştirme:

1. Token'lar (site geneli)

Vurgu rengini, font ailesini, köşe yuvarlamayı değiştir. var(--color-primary) kullanan her bölüm anında güncellenir. Inspector'da bir renge tıkla ya da hex yapıştır.

2. Bölümler (sayfa bazlı)

Her sayfa bir bölüm yığınıdır. Sol panelden yeni bölüm sürükle; sırayla taşı; satır menüsünden çoğalt ya da gizle. Bölümlerin kendi ayarları var (başlık, görsel, hizalama, vs.).

3. Bölüm ayarları (bölüm bazlı)

Bölüme tıkla, inspector açılsın. Başlığı düzenle, görsel değiştir, padding ayarla. Canlı önizleme yazdıkça güncellenir. Değişiklikler taslak olarak otomatik kaydedilir; Yayınla'ya basınca canlıya gider.

TIP
Editördeki AI asistan butonunu kullan — değişikliği düz dille anlat ("hero'yu daha kalın yap", "basın logoları stripi ekle") ve sana onaylayabileceğin bölüm + token düzenlemeleri önerir.
KILAVUZLAR

Webhook'larla event tüketimi

Bugün yerleşik workflow'lar, yarın imzalı outbound webhook'lar.

WARNING
Outbound webhook'lar (nuvinode'nin senin URL'ine POST atması) henüz hazır değil — yakın vadeli yol haritasında. API referansı / Webhook bölümü planlanan event şeklini gösterir. Bugün event'lere gerçek zamanlı tepki vermenin yolu workflow motoru.

Bugün: yerleşik workflow'lar

Her nuvinode tenant'ı gömülü bir workflow motoru ile gelir. Panel → Workflows altında açılır. Bir nuvinode trigger'ı seç — sipariş oluştu, ödeme alındı, müşteri oluştu, teklif gönderildi — ve action bloklarından birini bağla (HTTP, Slack, Sheets, özel kod).

Arka planda workflow motoru, ileride outbound webhook'ları besleyecek aynı Medusa event bus'ına abone olur — bugün kurduğun akışlar gerçek webhook çıkışı şipşırlanınca da çalışmaya devam eder.

Yarın: imzalı outbound webhook'lar

Planlanan event'ler:

  • order.placed — sepet siparişe dönüşür.
  • order.payment_captured — ödeme alındı.
  • order.fulfilment_shipped — hazırlama kargolandı.
  • customer.created, subscription.renewed, quote.submitted.

Her teslimat x-nuvi-signature header'ı taşıyacak — endpoint'inin imza secret'ı ile raw body'nin HMAC-SHA256'sı. Node.js alıcısında doğrulama:

x-nuvi-signature doğrulama (planlanan)
import crypto from 'node:crypto'

export function verifyNuviSignature(rawBody: Buffer, header: string, secret: string) {
  const expected = crypto
    .createHmac('sha256', secret)
    .update(rawBody)
    .digest('hex')
  // Yanıt süresinden sızdırmamak için timingSafeEqual kullan
  const a = Buffer.from(expected, 'hex')
  const b = Buffer.from(header, 'hex')
  return a.length === b.length && crypto.timingSafeEqual(a, b)
}
NOTE
Alıcılar, herhangi bir JSON parser dokunmadan ÖNCE raw body'yi okumalı — parse edilmiş objeyi yeniden serialize etmek HMAC'i bozar. Express'te express.raw({ type: 'application/json' }); Next.js route handler'ında JSON.parse yerine önce await req.text().
GEÇİŞ

Shopify'dan geç

Ürün, müşteri, sipariş, içerik, yönlendirme.

Import modülü Shopify export'unu okur ve her şeyi içeri çeker. Adımlar:

  1. Shopify'dan export al: Ayarlar → Hesap → Mağaza verisini dışa aktar (ya da ürünler için Storefront API'yi, siparişler için Admin API'yi kullan).
  2. nuvinode'de: Panel → Import → Yeni import → Shopify. Dosyayı yükle ya da doğrudan çekme için API bilgilerini yapıştır.
  3. Alan eşleştirmesi otomatik. Önizlemeyi gözden geçir, çakışmaları (örn. tekrarlayan handle'lar) düzelt.
  4. Import'u çalıştır'a bas. Ürünler, varyantlar, müşteriler ve siparişler import edilir. Medya nuvinode storage'a yeniden yüklenir.
  5. Redirect modülü eski Shopify URL'lerinden otomatik 301 üretir (/products/foo → nuvinode'de aynı path) — SEO korunur.
WARNING
Domainini nuvinode'ye yönlendirmeden önce test subdomaininde soft launch yap. Ürün sayfalarının render olduğunu, checkout'un baştan sona tamamlandığını ve redirect haritasının en çok trafiğin geldiği 50 URL'i kapsadığını doğrula.

Yardım gerekir mi? Premium Destek birebir geçiş yardımı içerir.

GEÇİŞ

WooCommerce'dan geç

WP export → nuvinode import.

WooCommerce geçişi Shopify ile aynı şekilde ilerler, bir farkla: WordPress hem storefront'u hem blog içeriğini barındırır, ikisini de import edersin.

  1. WordPress admin'den Customer / Order / Coupon export eklentisini kur ve tam export çalıştır.
  2. Blog yazılarını WP REST API ile çek: /wp-json/wp/v2/posts.
  3. nuvinode'de: Panel → Import → Yeni import → WooCommerce. Her iki dosyayı yükle.
  4. Import çalıştır. Ürün + siparişler ticarete; yazılar yazar + kategori korunarak Blog modülüne gider.
  5. Hem /product/slug hem /blog/slug kalıpları için redirect'ler otomatik üretilir.
NOTE
Özel eklenti özellikleri (Yoast meta, Elementor sayfaları, Advanced Custom Fields) otomatik çevrilmez. Import modülü veriyi korur; Yoast meta'yı nuvinode SEO ayarı olarak yeniden yazarsın, Elementor sayfaları nuvinode bölümleri ile yeniden inşa edilmeli.
AI

AI Asistan

AI asistanla mağazanı yönet, içerik taslakları hazırla ve görevleri doğal dille otomatikleştir.

AI asistan panelinde yaşar: mağazanı yönet, içerik taslakları hazırla ve görevleri doğal dille otomatikleştir. Komut ya da API bilgisi gerekmez — ne istediğini yaz, asistan doğru yeteneği seçip çalıştırır.

Neler yapar

  • Mağaza yönetimi — ürün, sipariş ve müşteri verisinde doğal dille sorgu ve güncelleme ("düşük stoklu ürünleri listele").
  • İçerik taslakları — asistan taslağı hazırlar; sen gözden geçirip yayınlarsın.
  • Tema düzenleme — Tema Editörü'ndeki AI asistan butonu, "hero'yu daha kalın yap" gibi istekleri onaylayabileceğin bölüm + token düzenlemelerine çevirir.
NOTE
24 AI yeteneğinin tümü her planda aynı şekilde çalışır — AI yetenekleri indeksine bak. Geliştiriciler kendi yeteneğini ekleyebilir: bir sonraki makale, Özel bir AI yeteneği yazmak.
TARİFLER

Quote modülü ile B2B mağaza kurmak

Talepten tahsilata akış: müşteri talebi, admin incelemesi, PDF + e-posta, ISG fiyatlandırma.

Çoğu B2B satıcı fiyatı açıkça listelemez — pazarlık eder. @nuvi/module-quote paketi tüm teklif-tahsilat döngüsünü sarar: genel talep endpoint'i, admin inceleme ekranı, markalı PDF'ler ve e-posta gönderimi. Veri modeli quote, quote-item, service-template, service-category ve isg-config olarak yaşar.

1. Müşteri talebi gönderir

Herhangi bir sayfaya teklif-talep formu koy (modül quote-request storefront bölümünü hazır verir) ve genel endpoint'e POST at. Handler ad, e-posta ve telefonu sunucuda doğrular, fiyatları hizmet şablonlarından yeniden hesaplar, benzersiz quote_number üretir ve quoteRequestWorkflow ile taslağı kaydeder.

POST /store/quote-requests
await fetch('/store/quote-requests', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    customer_name: 'Acme Ltd',
    customer_email: 'buyer@acme.com',
    customer_phone: '+90 555 000 00 00',
    customer_company: 'Acme Ltd',
    items: [
      { service_template_id: 'st_01H...', title: 'Risk Analizi', quantity: 1, unit_price: 2500 },
    ],
  }),
})

2. Admin inceler ve fiyatlandırır

Admin /app/quotes'u açar, satır kalemlerini düzenler ve durumu günceller (draft → sent → accepted). Yaşam döngüsü durumları quote modelindeki status enum'unda: draft, sent, accepted, rejected, expired. Süre valid_until ile yönetilir.

3. PDF + e-posta gönderimi

GET /admin/quotes/:id/pdf markalı PDF'i render eder. Mağaza-tarafı paylaşım linki workflow'da üretilen imzalı pdf_token'u kullanır — müşteri giriş yapmadan teklifini çekebilir. Bildirim alıcıları POST /admin/quotes/notification-recipients ile yapılandırılır.

4. ISG fiyatlandırma — çalışılmış örnek

Türk İSG firmaları çalışan sayısı ve tehlike sınıfına göre ücretlendirir. isg-config modeli service_durations, fulltime_thresholds, nurse_durations ve default_tax_rate'i tutar. Talep risk_class + employee_count içeriyorsa rota calculateIsgPrice()'ı sunucu tarafında çağırır — frontend fiyatları yok sayılır. Matrisi /app/services'ten ya da PUT /admin/quotes/isg-config ile düzenle.

5. Teklif-tahsilat devri

Teklif accepted olduğunda, quote.metadata ile Medusa order veya subscription'a bağla. Yaygın desen: quote_items'ı taslak order satırlarına kopyala, sonra Stripe / Iyzico ödeme linki gönder. Tekrarlanan servis sözleşmeleri — kabul edilen teklifi subscription modülünün subscription_plan'ı ile eşleştirip aylık tahsilata geç.

WARNING
Store endpoint ISG fiyatlarını her zaman DB'deki isg-config'den yeniden hesaplar. Client'tan gelen unit_price'a güvenme — handler sadece ISG-dışı satırlarda ipucu olarak kullanır.
TARİFLER

Abonelik ticareti — tekrarlayan tahsilat

Planlar, deneme süresi, dunning, yaşam döngüsü ve müşteri portalı — Stripe bağlı.

@nuvi/module-subscription paketi Medusa üzerine tekrarlayan tahsilat, müşteri portalı ve yaşam döngüsü hook'ları ekler. Her şeyi üç model yönetir: subscription_plan, customer_subscription ve subscription_payment (geçmiş). Stripe varsayılan sağlayıcı — plan üzerindeki stripe_price_id iki sistemi bağlar.

1. Plan oluştur

Planlar /app/subscriptions'tan ya da POST /admin/subscriptions/plans ile yönetilir. interval enum'u daily | weekly | monthly | yearly, interval_count ile çarpılır. trial_days deneme süresini, billing_cycles toplam yenileme sayısını sınırlar (sürekli için null).

POST /admin/subscriptions/plans
{
  "name": "Pro Aylık",
  "price": 49,
  "currency": "USD",
  "interval": "monthly",
  "interval_count": 1,
  "trial_days": 14,
  "stripe_price_id": "price_1Ox..."
}

2. Müşteri kaydolur

Storefront POST /store/subscriptions/checkout'a plan_id, success_url, cancel_url ile çağrı yapar. Handler yönlendirme URL'lerini STORE_CORS / ADMIN_CORS'a karşı doğrular (açık-yönlendirme koruması) ve Stripe Checkout Session açar. Ödeme sonrası Stripe webhook'u customer_subscription kaydını trialing veya active durumunda ekler.

3. Deneme ve dunning

Müşteri deneme süresindeyken trial_end set edilir. Başarısız yenilemelerde durum past_due'a döner ve dunning politikası (varsayılan Stripe smart retries) devreye girer. Tükendiğinde durum canceled ya da expired olur.

4. Yaşam döngüsü endpoint'leri — müşteri portalı

Müşteri portalı dört yaşam döngüsü rotasını çağırır:

Müşteri-tarafı rotalar
POST /store/subscriptions/:id/pause
POST /store/subscriptions/:id/resume
POST /store/subscriptions/:id/change-plan   { plan_id }
POST /store/subscriptions/:id/cancel        { at_period_end?: boolean }

at_period_end: true ile iptal kayıtta cancel_at_period_end'i set eder — abonelik current_period_end'e kadar active kalır, sonra canceled'a döner. Pause paused_at'ı set eder; resume temizler ve sonraki tahsilat tarihini yeniden verir.

5. Yenileme webhook'ları

Her başarılı yenileme bir subscription_payment kaydı yazar. Modülün event bus'ında subscription.payment.succeeded olayını dinleyerek kendi mantığını ekle — e-posta gönder, kullanım kredisi yükle ya da kendi ledger'ını mutabakat et.

6. Ürünlerle eşleme

subscription_plan.product_id Medusa ürününü işaret edebilir, böylece aynı SKU hem tek seferlik hem tekrarlayan satışı destekler. Plan'ın features JSON sütunu serbest bir torba — site_limit, mailbox_limit vb. — uygulamanın diğer yerlerinde yetkilendirme kontrolü için kullanılır.

TIP
Webhook imza doğrulaması fail-closed. STRIPE_WEBHOOK_SECRET set değilse rota 500 döner. Staging dahil her ortamda ayarla.
TARİFLER

Travel modülü ile tur platformu

Turlar, destinasyonlar, rezervasyonlar ve yorumlar — travel teması ile.

@nuvi/module-travel nuvinode'yi tur operatör platformuna dönüştürür. Veri modeli tur işletmelerinin düşünüş şeklini yansıtır: bir tour itinerary günlerine, included / excluded dizilerine, highlights'a, rehber bloğuna ve fiyatlandırmaya sahiptir. Turlar destination kayıtlarına (çoktan-çoğa, tour-destination üzerinden) ve tour-category taksonomisine bağlanır.

1. Tour varlığı

Önemli alanlar: slug (mağaza başına benzersiz), duration_days, max_group_size, price_from, price_per_guest ve itinerary, included, excluded, quick_facts için zengin JSON sütunları. Durum enum'u draft | published | archived.

2. Destinasyonlar ve kategoriler

Destinasyonlar tekrar kullanılabilir yerler — Kapadokya, Patagonya, Fuji. Genel listeleme GET /store/destinations, detay GET /store/destinations/:slug. Kategoriler (şehir turu, macera, aile) kenar çubuğu filtrelerini GET /store/tour-categories ile besler.

3. Rezervasyon akışı

Rezervasyonlar Medusa sepetini yeniden kullanır. Adanmış cart line endpoint'i ile bir tur ekle:

Sepete tur ekle
POST /store/carts/:id/tour-items
{
  "tour_id": "tour_01H...",
  "departure_date": "2026-07-15",
  "guest_count": 2,
  "options": { "transfer": true }
}

Satır kalemi tur verisini standart Medusa checkout'undan geçirir — ödeme, adres, onay. Sipariş verildikten sonra siparişin metadata'sını tur kaydına bağlayıp rezervasyon onayını render edebilirsin.

4. Yorumlar

Storefront onaylanmış yorumları GET /store/tours/:slug/reviews ile çeker. Handler yalnızca status: 'approved' filtreler — taslak ya da reddedilmiş yorumlar asla sızmaz. Tour üzerindeki rating ve review_count moderasyon akışıyla güncellenen denormalize toplamlardır.

5. Admin tarafında içerik

/app/travel editörü sağlar. Slug benzersizliği GET /admin/tours/check-slug ile kontrol edilir. Fiyatlandırma ve kalkış-bazlı override'lar /admin/tours/:id/pricing altında; moderasyon kuyruğu /admin/tours/:id/reviews'da.

6. Travel teması ile eşleme

Travel teması bu veriye uyan bölüm bileşenlerini hazır verir: destinasyon aramalı hero, tour grid, gün-gün itinerary, dahil/dahil-değil checklist'leri ve rehber kartı. Manifest'te listelenen tour-grid bölümü editörde hazır gelir.

NOTE
Reviews endpoint'i sayfa boyutunda 1–100 sınırı ve varsayılan 20 uygular — storefront tarafında dump-all yerine sonsuz kaydırma kullan.
TARİFLER

Etkinlik + biletleme platformu

Etkinlik, bilet türleri, kayıtlar, katılımcı listesi ve müşteri portalı.

@nuvi/module-events etkinlik yayını ve biletleme verir. Üç temel model: event (etkinlik), event-ticket-type (fiyat seviyeleri + kapasite) ve event-registration (satılan koltuk). Storefront genel etkinlik sayfasını görür; admin katılımcı listesi, satış raporu ve check-in görür.

1. Event varlığı

Model zamanlama (starts_at, ends_at, timezone, is_all_day), mekan (venue_name, venue_address, venue_city), online_url ile online flag ve üst-seviye capacity taşır. Durum: draft | published | cancelled | completed. registration_enabled sayfayı yayından kaldırmadan bilet satışını kapatır.

2. Bilet türleri

Her etkinlik birden çok event_ticket_type'a sahip: Early Bird, Genel Giriş, VIP. Her seviyenin price, capacity ve registered_count'u stok hesaplar. sales_start_at ve sales_end_at satış pencerelerini uygular. Store-tarafı endpoint türetilmiş flag'leri storefront yerine kendisi hesaplar:

GET /store/events/:slug/tickets
{
  "registration_enabled": true,
  "ticket_types": [
    {
      "id": "ett_01H...",
      "name": "Early Bird",
      "price": 49,
      "available": 23,
      "is_sold_out": false,
      "is_within_sales_window": true
    }
  ]
}

3. Sepet + checkout

Biletler standart Medusa sepetinden geçer, adanmış event-line endpoint'i ile:

Sepete bilet ekle
POST /store/carts/:id/event-items
{
  "event_id": "evt_01H...",
  "ticket_type_id": "ett_01H...",
  "quantity": 2,
  "attendee_name": "Ayşe Yılmaz",
  "attendee_email": "ayse@example.com"
}

Sipariş tamamlandığında modül her bilet için benzersiz confirmation_number ile bir event_registration oluşturur. Durum akışı: pending_payment → confirmed → checked_in (ya da cancelled).

4. Katılımcı listesi ve giriş

Admin katılımcı listesini GET /admin/events/:id/registrations, satış toplamlarını GET /admin/events/:id/stats ile çeker. Kapı görevlileri check-in endpoint'ine basar — durum checked_in'e döner ve checked_in_at damgalanır.

5. Müşteri portalı — biletlerim

Giriş yapmış müşteriler tüm biletlerini — geçmiş ve gelecek — tek endpoint'ten görür:

GET /store/events/my-registrations
// Auth gerekli. Sunucu müşterinin e-postasını oturumdan
// çözer, sonra attendee_email ile kayıtları arar.
{
  "registrations": [
    {
      "id": "reg_01H...",
      "confirmation_number": "EVT-2026-00042",
      "status": "confirmed",
      "event": { "title": "Spring Summit", "starts_at": "..." },
      "ticket_type": { "name": "VIP" }
    }
  ]
}

6. Etkinlik sonrası iletişim

Email-marketing modülü ile birleştirip katılımcılara mesaj at: event_registrationsevent_id ve status: 'checked_in' ile filtrele, sonra kayıt linki veya geri bildirim anketi gönder. Etkinliği iptal etmek için status'u cancelled'a çevir — my-registrations endpoint'i yeni durumu anında yansıtır.

TIP
my-registrations rotası fail-closed: istek auth_context.actor_id taşımıyorsa 401 döner, asla boş liste değil. Client'ta her zaman authenticated fetch ile sar.

Endpoint detayları mı arıyorsun?

Tam REST API referansı her storefront ucunu method etiketi, istek şekli ve cURL örnekleri ile kapsar.

API referansını aç

Aradığını bulamadın mı?

Destek ekibimiz her sorunda yardımcı olmaktan mutluluk duyar.