Skip to main content

Modules Documentation

Validation rules

Required fields, formats, ranges.

Complete

A CalendarEvent passes through three validation tiers before publication: structural (required fields + format), editorial (3-gate verification), and integrity (cross-references resolve, timezones are valid, dates are coherent). All three must pass.

Structural validation

  • Required: id, slug, title.en + title.ar, shortDescription.en + .ar, organizerName, organizerType, country, mode, startDate, timezone, category, status, audiences (≥1), stageRelevance (≥1), verificationStatus.
  • At least one of: websiteUrl, registrationUrl, applyUrl, contactEmail. Without an outbound channel, the event cannot funnel and shouldn’t be published.
  • slug is unique across the entire dataset, kebab-case, ASCII only.
  • startDate, endDate, applicationDeadline, registrationDeadline are valid ISO 8601 with explicit timezone offset.
  • timezone is an IANA zone identifier (e.g. "Africa/Cairo", "Asia/Riyadh"). Not "GMT+3" — that loses DST awareness.

Editorial verification — the 3 gates

  1. Gate 1 — Source authority. sourceUrl points to an authoritative channel: organizer’s own domain, official social account (verified), or a confirmed press release. Aggregator pages do not count.
  2. Gate 2 — Detail accuracy. Date, city, venue, organizer name, deadlines are confirmed against the source. If the source URL’s content disagrees with the entry, the entry is wrong, not the source.
  3. Gate 3 — Ecosystem relevance. The event is genuinely about MENA startups / founders / investors / ecosystem operators. Generic tech conferences, corporate sales events, or non-MENA events fail this gate even if their facts are correct.

Integrity validation

  • endDate ≥ startDate (when endDate is set).
  • applicationDeadline ≤ startDate (you can’t apply after the event starts — except for rolling cohorts, where deadline can be missing).
  • mode='physical' requires venue OR (city+country). mode='online' requires onlineUrl. mode='hybrid' requires both.
  • Every relatedXxxId resolves to an existing record in its module. Stale IDs are stripped at render time.
  • lastVerifiedAt must be set whenever verificationStatus transitions to "verified".