← Back to Work

Apollo-mena

Marketing website and Payload CMS admin platform for a MENA influencer agency. Arabic-first RTL public site with ISR revalidation and Lexical rich-text editing.

Role
Senior Frontend Engineer
Published
أبريل ٢٠٢٥
Type
CMS + Site
Revalidation
ISR
Direction
RTL-first
Next.js 15React 19TypeScriptTailwind CSS v4Payload CMSSupabaseGSAPLexical
View live site →

Context

Apollo-mena is a marketing website and Payload CMS admin platform for a MENA-based influencer agency. The agency manages Arabic-first content for regional brands — the public site needs to load fast, rank in Arabic search, and let non-technical editors publish without engineering involvement.

Two distinct products, one codebase:

  1. Public site — Arabic-first RTL marketing site for brands and influencer discovery, SSR/ISR
  2. Admin platform — Payload CMS instance with Lexical rich-text editing and Supabase media storage

Problem

The core tension: a non-technical editorial team needs publishing autonomy, while the public site needs to be fast enough to clear Core Web Vitals and correctly indexed by Google in Arabic.

The architectural question was: CMS-first or code-first? Hardcoding content in JSX is faster to ship but creates a dependency on engineers for every copy change. A full headless CMS decouples content from code but adds infrastructure and latency.

The answer was Payload CMS + ISR: editors own content in Payload, the Next.js site statically generates pages at build time and revalidates them on save — no per-request CMS latency, no engineering bottleneck for content changes.

Architecture

Why ISR over SSR?

The public site's content changes when editors publish — not on every user request. Full SSR would re-query Payload on every page load, adding ~100–200ms of CMS latency to every user's LCP. ISR serves the statically generated HTML instantly from the edge cache and revalidates only when an editor clicks save (on-demand ISR via a Payload save hook calling res.revalidate(path)).

The tradeoff: content is stale until an editor publishes. For a marketing site, that's acceptable — changes are intentional, not real-time.

Implementation

Payload CMS schema

Payload's collection definitions are TypeScript-first, which means the frontend gets end-to-end type safety from CMS schema to rendered component.

// payload.config.ts (simplified)
const Influencers: CollectionConfig = {
  slug: 'influencers',
  fields: [
    { name: 'name', type: 'text', required: true, localized: true },
    { name: 'bio', type: 'richText', localized: true }, // Lexical
    { name: 'avatar', type: 'upload', relationTo: 'media' },
    { name: 'categories', type: 'relationship', relationTo: 'categories', hasMany: true },
  ],
}

The localized: true flag on text and rich-text fields means Payload stores both Arabic and English values per document — editors see a language toggle in the admin UI, not separate records.

Lexical over Draft.js

VNET uses Draft.js for rich text. Apollo-mena was built after VNET, and by then Draft.js's maintenance status was clear. Lexical (Meta's replacement for Draft.js) was chosen for its extensibility, smaller bundle, and first-class TypeScript support. Payload v2+ ships Lexical as its default editor.

GSAP — calibrated, not decorative

The public site uses GSAP for two animations:

  1. A hero headline stagger on page load (~200ms, single axis)
  2. Influencer card entrance on scroll-enter via ScrollTrigger

Both respect prefers-reduced-motion: reduce (wrapped in a useReducedMotion guard). The decision to use GSAP here — despite it conflicting with this portfolio's own "no GSAP" stance — came down to the client brief: the agency wanted motion as a brand differentiator. The portfolio avoids it because the portfolio's brand story is performance, not motion. Context determines the right tool.

Arabic-first RTL

All copy is authored in Arabic first in Payload, English second. dir="rtl" is set on <html> for the Arabic locale. Font: IBM Plex Sans Arabic for body, with Cairo as fallback. One issue encountered: Lexical's default toolbar renders LTR — required a custom toolbar plugin to respect dir for Arabic editors.

Outcome

← All case studies