Skip to main content

Developer Page Specifications

QC Checklist

Per-page acceptance gates. Severity-tagged test cases for listing, details, and cross-page integration.

Complete

Concrete QC checklist for both pages. Every item is observable from the outside and asserts an Expected state per Section 11 · test-case-format. Severity: blocker (release-stopping) · critical (must-fix this sprint) · major (should-fix) · minor (polish).

Listing page checklist

  • OR-LIST-001 · blocker · Page returns 200 in EN + AR. Both /en/opportunity-radar and /ar/opportunity-radar.
  • OR-LIST-002 · blocker · All 4 status tabs render with correct computed counts matching the active dataset.
  • OR-LIST-003 · blocker · Country, type, stage, sector, status filters work independently AND in combination. Multi-select adds to the query, removing a chip removes from the query.
  • OR-LIST-004 · critical · Search (q ≥ 2 chars) debounces 300ms and matches across title, shortDescription, organizer, country, type, sector.
  • OR-LIST-005 · critical · Sort dropdown values applied correctly: deadline-soonest sorts by DeadlineDate ASC, newest by PublishedAt DESC, etc.
  • OR-LIST-006 · critical · Empty state appears when (filters → 0 results). Active filters quoted back, "Clear filters" CTA functional.
  • OR-LIST-007 · critical · Each card displays all required fields (title, type, status, deadline, country, organizer, short description) without overflow.
  • OR-LIST-008 · critical · Apply CTA opens OfficialUrl in new tab with noopener,noreferrer. Disabled state when OfficialUrl is null.
  • OR-LIST-009 · major · View Opportunity CTA navigates to /:lang/opportunity-radar/{slug} and the right details page renders.
  • OR-LIST-010 · major · Subscription form: email validation, required consent gate, submit POSTs to /api/subscriptions/opportunity-digest, success toast renders.
  • OR-LIST-011 · major · All 4 cross-module cards (G) render with correct titles + routes.
  • OR-LIST-012 · blocker · Mobile layout (320px / 375px / 640px): no horizontal scroll, filter drawer opens correctly, cards single-column.
  • OR-LIST-013 · blocker · RTL (/ar/*) — filter drawer slides from left, cards mirror correctly, deadline pills mirror, chevrons reverse.

Details page checklist

  • OR-DTL-001 · blocker · Correct opportunity loads by slug. Unknown slug returns 404 with the documented not-found layout (not a 500).
  • OR-DTL-002 · blocker · Breadcrumb renders Home → Opportunity Radar → current title. Current title is non-clickable.
  • OR-DTL-003 · blocker · Header section B shows status badges, title (only H1), short description, deadline, country, stage(s), value signal.
  • OR-DTL-004 · critical · Apply box C: button opens OfficialUrl in new tab. Disabled state when OfficialUrl is null OR Status = Closed. Last-verified note shows N days correctly.
  • OR-DTL-005 · critical · Should-You-Apply section D shows urgency, best-for, time required, value signal, application requirements, eligibility count.
  • OR-DTL-006 · critical · Sections E (description), F (audience), G (why it matters), H (benefits), I (eligibility), J (application requirements), K (timeline), L (organizer) render only when their underlying data exists. No empty sections.
  • OR-DTL-007 · critical · Timeline (K) sorted by date ASC. Past items desaturated.
  • OR-DTL-008 · critical · Related Opportunities (M) — manual links first, auto-fill second, capped at 6. Section hides entirely when both return 0.
  • OR-DTL-009 · critical · Connected Signals (N) — capped at 8 cards. "See all" link appears when more exist. Each card routes correctly per sourceRoute.
  • OR-DTL-010 · major · Subscription block O preselects Opportunity Radar interest + tracks opportunityIdContext.
  • OR-DTL-011 · critical · Closed opportunities: Apply button disabled, "This opportunity is closed" banner above the apply box, JSON-LD eventStatus reflects closed state when migrated.
  • OR-DTL-012 · blocker · SEO/AEO: canonical, hreflang triplet, OG quartet, robots tag, CreativeWork JSON-LD validates against Rich Results Test.
  • OR-DTL-013 · blocker · Mobile layout: CTAs full-width stacked, sidebar moves below main, no horizontal scroll, sticky Apply button at bottom on Status ≠ Closed.
  • OR-DTL-014 · blocker · RTL (/ar/*) — timeline mirrors (date column moves to right), sidebar moves to left, all chevrons reverse, status pills mirror.

Cross-page / integration checks

  • OR-INT-001 · blocker · The integrity sweep (§10.8) reports 0 broken cross-module references involving any Opportunity row.
  • OR-INT-002 · critical · Sitemap.xml contains every IsActive=true opportunity URL in both locales.
  • OR-INT-003 · critical · All 9 listing-page + 6 details-page analytics events fire with correct properties (validated via GA4 DebugView during release QC).
  • OR-INT-004 · major · Cache headers honoured at the CDN: summary cache 60s, listing cache 120s, details cache 300s.
  • OR-INT-005 · major · Performance: Listing LCP ≤ 2.5s at 3G Fast, details LCP ≤ 2.0s, CLS ≤ 0.1 on both, hydration mismatch count = 0.