Skip to main content
Jabal Al Noor Pharmacy Digital Commerce Platform
Case StudyWeb Development

A CMS the marketing team cannot break

Draft and published content in one row, optimistic concurrency, and a preview token that works exactly once.

Client
Jabal Al Noor Pharmacy
Industry
Pharmacy retail
Outcome
Homepage edits without a deploy

The problem

The client wanted to edit the homepage without a deploy, including curated product showcases — where the curated products can go inactive or out of stock between editing and publishing.

Draft and published in one row

A single row holds both draftContent and publishedContent as JSONB, with publish as an atomic draft-to-published copy.

Concurrent edits are caught by optimistic concurrency on an If-Match header carrying the ISO updatedAt, returning a 409 that reads *"Draft has changed since it was loaded — reload and try again."*

Publishing resolves curated product IDs against live products and returns non-blocking warnings for anything dropped as inactive or flagged as out of stock. Warnings inform; they do not block. The Publish button is disabled while the draft is dirty, so you cannot publish a state you have not saved.

Preview tokens

This is the piece worth highlighting. Editors need to view an unpublished draft on the real storefront, which means a token that survives leaving the admin app.

  • Signed with a key derived from JWT_SECRET via HMAC but distinct from it, so a preview token can never be replayed as an access token or vice versa — signature verification simply fails across keys
  • Carries a random jti recorded in Redis with a five-minute TTL
  • Verification consumes the nonce with DEL, which returns 1 only on first use

The token therefore works exactly once.

Revalidation that cannot fail a publish

Publishing fires an on-demand ISR revalidation at the storefront, deliberately fire-and-forget. If the shared secret is unset or the call fails, publish still succeeds and the page refreshes within its normal ISR window. A revalidation failure is logged as *content will refresh within the ISR window*, never surfaced as a failed publish.

The receiving route refuses with a 503 when unconfigured rather than revalidating unauthenticated, and compares the secret with timingSafeEqual — burning a same-length comparison even on a length mismatch, to reduce the timing signal.

A CMS the marketing team cannot break | Tuninbits