You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Parent epic for a cross-platform (iOS + Android) watch app using React Native and Expo. Content is fetched from Strapi (this monorepo's CMS) via GraphQL; layout is driven by Experience/sections. All implementation work is tracked in sub-issues linked below.
Context:
Product target: Watch-style app mirroring jesusfilm.org/watch and experience pages (e.g. Easter, Christmas)—streaming library, featured content, locale-specific experiences with sections.
CMS: Strapi in apps/cms; schema at apps/cms/schema.graphql. Same Experience and section types as web.
App location: Expo app under mobile/expo (alongside mobile/ios and mobile/android).
GraphQL: Apollo Client (JS/TS) for Strapi; types/operations from shared codegen (@forge/graphql) or Expo-specific codegen from same schema—to be decided in sub-issue.
Section types (schema-aligned)
The CMS schema defines 10 active section types in the ExperienceSectionsDynamicZone union (see apps/cms/schema.graphql line 693):
#
Component
Description
1
VideoHero
Hero banner with heading, subheading, linked Video, CTA button
2
MediaCollection
Collection of video/media items; variants: carousel, collection, grid, hero, player; supports showItemNumbers, linkToSectionKey, footer text
3
CTA
Call-to-action with heading, body, button (primary/secondary variants)
4
Text
Rich text block with heading (h1–h6), subtitle, content; variants: default, lead, small
5
Video
Embedded video player with title, subtitle, streaming URL, linked Video entity
Standalone card with title, description, media, link; variants: default, featured
9
Section
Wrapper with backgroundColor (dark/default/light/primary), blurHash, and nested content dynamic zone (recursive)
10
Container
Grid layout with slots; each slot has gridSpan and nested content dynamic zone (recursive)
Deprecated (do not implement):PromoBanner (superseded by VideoHero) and InfoBlocks (superseded by Text). These remain in the schema but are stubs in queries (id-only) and should be ignored.
Expected outcome
A single cross-platform (iOS + Android) React Native app under mobile/expo that builds and runs with Expo.
App fetches Experience(s) from Strapi via GraphQL and renders server-driven UI (section-based layout).
Watch home and experience-by-slug with locale; visual parity goal with jesusfilm.org/watch and experience pages.
All work tracked in sub-issues linked to this epic; repo workflow (issue first, branch, PR, conventional commits) and CI (lint, typecheck, build) applied.
Acceptance criteria
All sub-issues created and linked (dependency order below updated with issue numbers).
Expo app under mobile/expo; runs on iOS and Android.
App fetches Experience(s) and renders section-based UI for all 10 active section types (VideoHero, MediaCollection, CTA, Text, Video, BibleQuotesCarousel, RelatedQuestions, Card, Section, Container).
Nested content rendering works for Section and Container wrappers.
Watch home and at least one experience-by-slug with locale.
Lint/CI pass; dev/stage/prod config and README; tests as agreed.
Possible solution(s)
Scaffold with npx create-expo-app (or equivalent); TypeScript; folder structure by feature.
GraphQL: Reuse @forge/graphql if Metro-compatible, or dedicated codegen for Expo from apps/cms/schema.graphql.
Section renderers: RN components per section type; data layer maps API response to section models. Reference the iOS native app's GraphQL query (mobile/ios/GraphQL/Operations/GetWatchExperience.graphql) which already handles all 10 types.
Sample Experience: documentId lr6luew6oh4hurag4n8s0ddz (slug: easter) — mocks first two sections of the Easter page
Source reference (JesusFilm/core)
The original production Easter page lives in JesusFilm/core — the existing Next.js monorepo that powers jesusfilm.org. Use this as the ground-truth reference when building and testing features.
Production reference — compare visual output against this
How to use for testing:
Compare each section renderer's output (VideoHero, MediaCollection, Text, Video, BibleQuotesCarousel, RelatedQuestions, CTA, Card) against the live Easter page.
Check apps/watch source for layout logic, section ordering, responsive behavior, and interaction patterns (autoplay, accordion, carousel snap, CTA navigation).
The forge repo's Strapi CMS replicates the same content structure — section types and fields should map 1:1.
Nested content: Section and Container types contain their own content dynamic zones, which can recursively hold other section types. Container slots also have gridSpan for layout.
Routing: Watch home (homepage experience) and experience-by-slug (e.g. easter, christmas) with locale.
Background
Parent epic for a cross-platform (iOS + Android) watch app using React Native and Expo. Content is fetched from Strapi (this monorepo's CMS) via GraphQL; layout is driven by Experience/sections. All implementation work is tracked in sub-issues linked below.
Context:
apps/cms; schema atapps/cms/schema.graphql. Same Experience and section types as web.mobile/expo(alongsidemobile/iosandmobile/android).@forge/graphql) or Expo-specific codegen from same schema—to be decided in sub-issue.Section types (schema-aligned)
The CMS schema defines 10 active section types in the
ExperienceSectionsDynamicZoneunion (seeapps/cms/schema.graphqlline 693):showItemNumbers,linkToSectionKey, footer textbackgroundColor(dark/default/light/primary),blurHash, and nestedcontentdynamic zone (recursive)slots; each slot hasgridSpanand nestedcontentdynamic zone (recursive)Expected outcome
mobile/expothat builds and runs with Expo.Acceptance criteria
mobile/expo; runs on iOS and Android.Possible solution(s)
npx create-expo-app(or equivalent); TypeScript; folder structure by feature.@forge/graphqlif Metro-compatible, or dedicated codegen for Expo fromapps/cms/schema.graphql.mobile/ios/GraphQL/Operations/GetWatchExperience.graphql) which already handles all 10 types.References
ExperienceSectionsDynamicZoneunion (line 693)lr6luew6oh4hurag4n8s0ddz(slug:easter) — mocks first two sections of the Easter pageSource reference (JesusFilm/core)
The original production Easter page lives in JesusFilm/core — the existing Next.js monorepo that powers jesusfilm.org. Use this as the ground-truth reference when building and testing features.
/watchroutesHow to use for testing:
apps/watchsource for layout logic, section ordering, responsive behavior, and interaction patterns (autoplay, accordion, carousel snap, CTA navigation).forgerepo's Strapi CMS replicates the same content structure — section types and fields should map 1:1.Foundations (Expo/RN)
expo exportor EAS); follow repo workflow.Server-driven UI and content model
contentdynamic zones, which can recursively hold other section types. Container slots also havegridSpanfor layout.easter,christmas) with locale.Progress summary
Completed (6 of 9 sub-issues)
mobile/expoIn progress / Next up (3 of 9 sub-issues)
Current focus: #93 → in progress with #305 (SectionDispatcher scaffold)
Dependency order
Out of scope