Skip to content

Storefront Publishing, Versioning & Rollback

Academy storefront için draft/published ayrımı, publish (deploy) akışı, optimistic locking, deploy geçmişi ve rollback tasarımı.

Bu doküman, Achidemy academy storefront’unda yapılan tasarım/içerik değişikliklerinin taslak (draft) olarak tutulup, “Yayınla” ile canlıya (published) alınmasını; yayınlama sırasında deploy geçmişi oluşturulmasını ve istenirse rollback ile geriye dönülmesini açıklar.

Hedef: Öğrenciye giden storefront’un en hafif ve en stabil şekilde çalışması (builder/editör kodları public bundle’a girmeden), eğitmen tarafında ise güvenli sürümleme ve geri dönüş.


  • Academy storefront theme (global): Navbar/Footer + site theme ayarları (academies.themeConfig*)
  • Academy pages (per-page): /p/:slug dinamik sayfaları (academy_pages.*)
  • Deploy history: Publish snapshot’ları (academy_deployments, academy_deployment_pages)

Bu doküman kurs publishing (marketplace/academy visibility) gibi ayrı kavramları kapsamaz.


  • Draft: Eğitmenin builder’da yaptığı, henüz öğrenciye yansımayan değişiklikler.
  • Published: Öğrencinin gördüğü canlı içerik/tema.
  • Deploy: Publish anında alınan snapshot; sürüm numarası ve geçmiş kayıtları.
  • Rollback: Seçilen deploy snapshot’ına geri dönüş (tema + sayfalar).
  • Optimistic locking: Aynı içeriğin farklı tablardan/kişilerden güncellenmesini güvenli yönetmek için sürüm kontrolü.

  • Builder: /:lang/instructor/academy/builder
    • Anasayfa: themeConfigDraft.blocks güncellenir
    • Sayfa: ?pageId= → yalnızca academy_pages.draftContent (navbar/footer ana sayfayı ezmez)
  • Pages: /:lang/instructor/academy/pages (liste; düzenleme builder’a yönlendirir)
  • Builder Sayfalar sekmesi: aynı sayfa listesi + intent=create-page (iframe senkronu)
  • Deploy history / Rollback: /:lang/instructor/academy/deployments
  • Önizleme (iframe, taslak UI): /:lang/builder-preview, /:lang/builder-preview-auth

Detaylı liste için Route Haritası ve Builder Preview sayfalarına bakın.


  • Draft: academies.themeConfigDraft
  • Published: academies.themeConfig
  • Versioning:
    • academies.draftVersion
    • academies.publishedVersion

Storefront render sadece themeConfig okur. Builder UI ise themeConfigDraft üzerinden çalışır.

  • Draft:
    • academy_pages.draftContent
    • academy_pages.draftMetaTitle, draftMetaDescription, draftOgImageUrl
    • academy_pages.draftVersion
  • Published:
    • academy_pages.publishedContent
    • academy_pages.publishedMetaTitle, publishedMetaDescription, publishedOgImageUrl
    • academy_pages.publishedAt
    • academy_pages.publishedVersion
  • Visibility: academy_pages.isPublished (public sayfada görünsün mü)

Public render (/p/:slug) öncelikle published alanları okur (fallback: legacy content/meta*).

  • academy_deployments
    • academyId, version, publishedThemeConfig, createdBy, message, createdAt
  • academy_deployment_pages
    • deploymentId, pageId, slug, title, content, metaTitle, metaDescription, ogImageUrl

  • Builder taslağı kaydeder:
    • themeConfigDraft güncellenir
    • (page edit modunda) draftContent + draftMeta* güncellenir
  • Canlı site değişmez.

Publish tek bir işlem gibi görünse de içeride şu adımlar yapılır:

  • Draft → Published taşıma
    • themeConfigDraftthemeConfig
    • Page edit modunda draft*published*
  • Deploy snapshot yazma
    • academy_deployments içine bir kayıt (sürüm = publishedVersion)
    • academy_deployment_pages içine yayınlı sayfaların snapshot’ları

Bu sayede deploy geçmişi “yayın anındaki gerçek durum”u temsil eder.

Idempotency (retry/çift submit güvenliği)

Section titled “Idempotency (retry/çift submit güvenliği)”

Publish isteği network retry veya kullanıcı çift tıklaması gibi nedenlerle tekrar gelirse:

  • Aynı academyId + version için ikinci kez snapshot yazılmaya çalışılmaz.
  • DB tarafında ayrıca academy_deployments_academy_version_unique unique index’i bulunur.

Bu iki katman birlikte, “Yayınla” akışını pratikte idempotent yapar.


Builder her POST’ta mevcut sürümü gönderir:

  • academyDraftVersion
  • (sayfa edit modunda) pageDraftVersion

DB update’leri şu mantıkla yapılır:

  • WHERE academies.draftVersion = academyDraftVersion
  • WHERE academy_pages.draftVersion = pageDraftVersion

Eğer update 0 satır etkilerse 409 Conflict döner. Bu, “başka bir yerde değişmiş, sayfayı yenile” anlamına gelir.


Deploy history ekranından seçilen bir deploy için:

  • academies.themeConfig ve themeConfigDraft deploy’daki publishedThemeConfig ile güncellenir
  • Deploy’daki sayfalar:
    • published + draft alanlarına snapshot yazılır
    • snapshot’ta olmayan ama şu an yayında olan sayfalar isPublished=false yapılır

Rollback de bir çeşit publish gibi düşünülebilir: sistemin published halini farklı bir snapshot’a set eder.

Rollback işlemi, sistemde yeni bir publishedVersion üretir. Bu nedenle rollback tamamlandığında:

  • Yeni aktif version için yeni bir academy_deployments kaydı oluşturulur (message örn. Rollback: #3 → #4)
  • Snapshot’taki sayfalar da academy_deployment_pages içine tekrar yazılır

Böylece deploy geçmişi “publish” ve “rollback” aksiyonlarının tamamını kapsar ve aktif sürüm her zaman geçmişte bulunabilir.


  • Pure content rendering: Public route’lar builder/editör bağımlılıklarını import etmez; sadece “content → component render” yapar.
  • Stability: Public taraf, draft alanlara asla bakmadığı için “yarım kalmış” düzenlemeler öğrenciye yansımaz.
  • Auditability: Deploy history, “hangi sürüm ne zaman yayınlandı” izlenebilirliğini sağlar.