Church App — MVP Scope

Church App — MVP Scope

Ship the smallest thing that makes one denomination say “yes.” Everything else is Phase 2.


The MVP Question

The temptation: build everything we’ve designed. The architecture supports it. The domain model is ready. AI agents can generate code fast.

The reality: even with AI agents, a solo founder needs to ship something usable to real churches within 4-6 months. Every feature added to MVP is a feature that needs to be tested, polished, supported, and explained. The MVP isn’t about what you CAN build — it’s about what you MUST ship to close the first denomination deal.

The test: Would ICF or Chrischona/Viva sign a pilot agreement based on this feature set? If yes, it’s enough. If no, what’s missing?


What the First Pilot Church Needs

Put yourself in the shoes of an ICF Zürich campus pastor evaluating your app:

"We currently use [Communiapp / WhatsApp groups / email lists / nothing].
We need:

1. Our members can find and download OUR app (branded, in the store)
2. Members can sign up and see they belong to ICF Zürich
3. We can post news and announcements → members get push notifications
4. Members can see our groups and join them
5. Members can see upcoming events and RSVP
6. Members can find each other (directory)
7. Group leaders can message their groups
8. It looks good and works fast

That's it. If it does these things better than what we have, we'll try it."

Notice what’s NOT on the list: giving, Sunday live experience, chat, translation, ticketing, camp tenants, syndication, AI features. These are all differentiators — but they’re not blockers for the first pilot.


MVP Feature Set

✅ IN MVP

1. AUTHENTICATION & EMAIL
   ├── Zitadel (self-hosted): email/password, password reset, passkeys
   ├── Mailgun (paid): transactional email gateway
   │   ├── EU-hosted infrastructure (GDPR compliance — data stays in Europe)
   │   ├── Password reset emails
   │   ├── Invite emails ("Join FEG Winterthur")
   │   ├── Email verification
   │   └── Proven deliverability, you have working experience with it
   ├── JWT-based API authentication
   ├── Role-based access (admin, leader, member, guest)
   └── Organization access flows (see .ai/context/ORG_ACCESS_FLOWS.md)
       ├── Open join: auto-membership on first API call (DONE)
       ├── Org switching: GET /api/v1/me/organizations + org picker
       ├── Invite-only join: admin sends invite link/QR → member accepts
       ├── Leave org: member can leave, auto-removes group memberships
       ├── registrationMode per org (open, invite_only, by_request)
       └── by_request join: deferred to Phase 2 (approval workflow + notifications)

2. SELF-SERVICE TENANT CREATION
   ├── Admin backend wizard: name, type, denomination, branding
   ├── Auto-approve, live immediately
   ├── Subdomain: {slug}.yourapp.com
   ├── Free tier (≤ 50 members, no credit card)
   └── Demo tenant pre-populated for marketing site

3. ADMIN BACKEND
   ├── Symfony + Twig + Vue 3 islands
   ├── Tenant setup wizard (self-service)
   ├── Organization tree management (create, edit, reorder)
   ├── Member management (list, search, roles, invite)
   ├── Content management (news, events, groups)
   ├── Basic dashboard (member count, recent activity)
   └── Super admin panel (your internal tool: tenant overview, conflict detection)

4. MODULES:
   ├── Personal Profile
   │   ├── Edit name, photo, bio, contact info
   │   ├── Privacy settings (who sees what)
   │   ├── Language preference (DE, EN minimum)
   │   └── Notification preferences

   ├── People Directory
   │   ├── Searchable member directory (within org scope)
   │   ├── Member profile view (respecting privacy)
   │   └── Contact actions (email, phone — if visible)

   ├── Groups
   │   ├── Group directory (browse, search, filter by type)
   │   ├── Group detail (description, members, leader, schedule)
   │   ├── Join group (open / request / invite-only)
   │   ├── Group hierarchy (sub-groups)
   │   ├── "My Groups" view
   │   └── Admin: create, edit, archive, manage members

   ├── Events
   │   ├── Event list (upcoming, filtered by org/group)
   │   ├── Event detail (description, time, location, map)
   │   ├── RSVP Level 1 ("I'll be there") + Level 2 (registration + capacity)
   │   ├── Recurring events (RRULE)
   │   ├── Event ↔ Group relationship
   │   ├── "My Events" view
   │   ├── Calendar export (iCal)
   │   └── Admin: create, edit, cancel, view attendees

   ├── News
   │   ├── Multi-level feed (org-scoped, cascading down tree)
   │   ├── Rich text posts with images
   │   ├── Post targeting (all / specific org / specific group)
   │   └── Admin: create, edit, delete, schedule

   └── Push Notifications
       ├── Firebase FCM (Android) + APNs (iOS)
       ├── Web push (service worker, for PWA users)
       ├── Types: news post, event reminder, group update
       ├── Member preferences (enable/disable per type)
       └── Deep link from notification → relevant screen

5. INFRASTRUCTURE & PIPELINE
   ├── Symfony 7 (modular monolith, DDD structure)
   ├── PostgreSQL 16 + ltree + PgBouncer
   ├── Redis 7 (cache + Symfony Messenger transport)
   ├── Cloudflare R2 (media storage) + CDN
   ├── Mailgun (transactional email, EU-hosted)
   ├── Hetzner: CPX21 (app) + CPX11 (db)
   ├── Docker Compose (all environments)
   ├── Deptrac boundary enforcement
   ├── JSON-serializable domain events from day one
   ├── Observe & Protect Pipeline: audit + history consumers
   ├── REST API (OpenAPI documented)
   ├── OpenTofu for server provisioning
   └── Automated CI/CD (see below)

6. FRONTEND: DUAL DELIVERY
   ├── React Native (Expo): iOS + Android + Web (PWA)
   ├── Single codebase, three targets

   ├── WEB APP (PWA) — primary delivery for MVP
   │   ├── Expo Web build → Cloudflare Pages
   │   ├── Per-tenant subdomain: {slug}.yourapp.com
   │   ├── Service worker: offline support + web push
   │   ├── "Add to home screen" prompt
   │   ├── Responsive: works on mobile browsers + desktop
   │   └── This is how most users access the app initially

   └── NATIVE APP — demo/showcase in stores
       ├── One "demo" app published to App Store + Play Store
       ├── Points to the demo tenant (pre-populated data)
       ├── Purpose: let people see the native experience
       ├── Real denomination apps: published later per customer
       └── Expo EAS Build for iOS + Android binaries

7. AUTOMATED DEPLOYMENT (CI/CD)
   ├── GitLab CI/CD (free tier)

   ├── On every push:
   │   ├── PHP: lint + PHPStan (level 8) + Deptrac + unit tests
   │   ├── JS: ESLint + TypeScript check
   │   └── Fast feedback: < 3 minutes

   ├── On merge to main:
   │   ├── Full test suite (unit + integration)
   │   ├── Build Docker image → push to GitLab Container Registry
   │   ├── Build Expo Web → deploy to Cloudflare Pages (staging)
   │   ├── Deploy backend to staging server
   │   └── Auto: no manual step

   ├── On tag / release:
   │   ├── Deploy to production (backend + web app)
   │   ├── Expo EAS Build for native (when needed)
   │   └── OTA update push for existing native installs

   ├── Environments:
   │   ├── dev: Docker Compose on laptop (€0)
   │   ├── staging: Hetzner CPX11 (€4.50/mo) — auto-deployed on merge
   │   └── production: Hetzner CPX21 + CPX11 (€12/mo)

   └── Goal: push to main → live on staging in < 5 minutes
             tag a release → live in production in < 10 minutes
             pilot users on staging get features days before production

❌ NOT IN MVP

PHASE 2 (build next, after first pilots):
├── By-request org join (approval workflow, admin UI, notifications)
├── Giving (Stripe Connect, TWINT, recurring — the retention moat)
├── Chat (Centrifugo — members use WhatsApp until then)
├── Sunday Experience (live polls, prayer wall, sermon notes)
├── Registration Level 3-4 (custom fields, ticketing, scanning)
├── Translation (DeepL — multilingual churches can wait)
├── Tenant merge (build when first denomination consolidation happens)

PHASE 3+:
├── Pinboard
├── Event syndication (cross-tenant linking)
├── Camp/conference tenants
├── Cross-tenant org switching (multi-tenant native app)
├── ChMS adapters
├── AI Admin Pack
├── Public API
├── Seat selection / badge printing

MVP Technical Stack (Confirmed)

LayerTechnologyCost
BackendSymfony 7, PHP 8.3+Free
DatabasePostgreSQL 16 + ltree + PgBouncerIncluded in Hetzner
Cache/QueueRedis 7Included in Hetzner
IdentityZitadel (self-hosted Docker)Free
EmailMailgun (EU region)Free tier → ~€35/mo at scale
StorageCloudflare R2 + CDNFree tier
HostingHetzner CPX21 + CPX11€12/mo
FrontendReact Native (Expo) — iOS/Android/WebFree
Web hostingCloudflare Pages (PWA)Free
CI/CDGitLab CI/CDFree tier
IaCOpenTofuFree
MonitoringUptime Kuma + Prometheus/GrafanaFree (self-hosted)
PushFirebase FCM + APNsFree tier
Error trackingSentry (self-hosted)Free
Total MVP~€25-35/mo

MVP Build Plan

Phase 0: Foundation (Weeks 1-3)

INFRASTRUCTURE:
├── Hetzner servers provisioned via OpenTofu
├── Docker Compose: PostgreSQL, Redis, Symfony, Zitadel
├── GitLab repo with CI pipeline (lint, PHPStan, Deptrac, tests)
├── Staging environment auto-deploys on merge to main
├── Mailgun account (EU region) + Symfony Mailer integration
└── Cloudflare: DNS, R2 bucket, Pages project

SYMFONY PROJECT:
├── DDD directory structure (Core/, Module/, Pipeline/)
├── .ai/ directory with all guideline files
├── Deptrac configuration (all module boundaries)
├── Domain event bus (Symfony Messenger + Redis)
├── Tenant resolution middleware (subdomain → tenant context)
└── OpenAPI documentation setup

IDENTITY:
├── Zitadel deployment (Docker on Hetzner)
├── OIDC integration (Symfony JWT validation)
├── Password reset flow via Zitadel (emails via Mailgun)
├── Member auto-creation on first login
└── Role mapping

PIPELINE:
├── Audit log consumer (append-only, all events)
└── History tracker consumer (entity snapshots)

EXPO PROJECT:
├── React Native (Expo) project with Expo Router
├── Custom design system foundation (tokens, components)
├── Auth flow (OIDC → Zitadel)
├── Web build configuration (Cloudflare Pages deployment)
└── Navigation shell (tabs: Feed, Groups, Events, Directory, Profile)

Phase 1: Core Modules (Weeks 4-8)

BACKEND (API + Admin):
├── Org access flows (see .ai/context/ORG_ACCESS_FLOWS.md):
│   ├── GET /api/v1/me/organizations (cross-tenant org list for org picker)
│   ├── OrgInvitation entity + invite/accept endpoints
│   ├── DELETE /api/v1/me/organizations/{id} (leave org)
│   └── Admin UI: invitation management, registration mode config
├── People module (member CRUD, profile, privacy, directory search)
├── Groups module (group CRUD, hierarchy, membership, types, visibility)
├── Events module (event CRUD, RRULE recurrence, RSVP L1+L2, group linking)
├── News module (multi-level feed, rich text, targeting, scheduling)
├── Notification module (push via FCM/APNs, web push, preferences)
├── Self-service tenant creation wizard (admin backend)
└── Each module: Domain layer (pure PHP) → Application → Infrastructure → API

FRONTEND (parallel, starts when first APIs are stable):
├── Org access screens:
│   ├── Org picker / switcher (bottom sheet, grouped by tenant)
│   ├── Org landing page (before login — shows name, logo, registrationMode)
│   ├── Invite accept screen (resolve token → show org → accept)
│   └── Leave org flow (confirmation + auto-switch to next org)
├── Feed screen (news, pull-to-refresh, push deep link)
├── Groups screens (my groups, discovery, detail, join/leave)
├── Events screens (my events, detail, RSVP, calendar export)
├── Directory screens (search, profile view)
├── Profile screens (edit, privacy, notifications, language)
└── Basic settings (language toggle DE/EN)

Phase 2: Polish & Deployment (Weeks 8-12)

WEB APP:
├── Expo Web build → Cloudflare Pages
├── Per-tenant subdomain routing
├── Web push notifications
├── PWA manifest + "add to home screen"
├── Test on: Safari iOS, Chrome Android, Chrome/Firefox desktop
└── Demo tenant: pre-populated, linked from marketing site

NATIVE APP (demo):
├── Expo EAS Build: iOS + Android
├── Demo tenant configuration (app name, icon, splash)
├── TestFlight (iOS) + Internal testing (Android)
├── Submit to stores: one "demo" app
└── OTA update pipeline configured (Expo Updates)

ADMIN BACKEND:
├── Dashboard (member count, active users, recent activity)
├── Org tree visual editor
├── Bulk member invite (CSV or email list)
├── Content scheduling
└── Super admin: tenant overview, conflict detection

POLISH:
├── Empty states (new church, no content yet)
├── Onboarding screens (first launch)
├── Error handling, retry logic, offline states
├── Loading skeletons, animations
└── Accessibility basics

Phase 3: Pilot (Weeks 12-18)

├── Onboard 3-5 pilot churches from your network
├── Staging = beta channel (pilot users get features first)
├── Production = stable channel (after staging validation)
├── Weekly feedback calls with pilot admins
├── Rapid iteration: fix → push to staging → validate → tag release → production
├── Monitor: downloads, DAU, feature usage, crash reports
├── Success metric: >30% member adoption within 3 months
└── Decision: ready for first denomination pitch?

Onboarding & Sign-Up Process

The Funnel

MARKETING SITE                SELF-SERVICE                PILOT                    NATIVE APP
─────────────                 ────────────                ─────                    ──────────
Visitor lands on              Creates tenant              Church uses the          Denomination
website                       in 5 minutes                web app for              commits →
                                                          real with members        App Store
"Join waiting    ──────▶     "Set up your     ──────▶                  ──────▶    submission
 list"                        community"                  Proves value.            (manual,
                                                          Members engage.          2-3 weeks)
OR                            Self-service:               Feedback loop.
                              name, org type,
"Try the demo   ──────▶      branding, first             Decision point:
 tenant"                      admin account               "We want our
                              → live web app              own native app"
                              in minutes

Step 1: Marketing Site — Waiting List + Demo

WAITING LIST:
├── Simple form on the marketing site: name, email, church/org name, size
├── Stored in your DB (or simple tool like Loops, Buttondown, even a Google Sheet)
├── Purpose: gauge demand, collect leads, notify when ready
├── "We're launching soon. Be the first to try it."
└── You personally follow up with warm contacts (ICF, FEG, etc.)

DEMO TENANT:
├── A public, pre-populated tenant anyone can explore
├── Fake church: "Demo Community Zürich" with realistic data
│   ├── 3 org nodes (Demo Community → Zürich → Campus City)
│   ├── 8 groups (small groups, teams, communities)
│   ├── 15 events (services, workshops, retreats)
│   ├── 30 fake members with profiles
│   └── News feed with sample posts
├── Accessible via web: demo.yourapp.com
├── Login: "Try as member" (pre-filled demo account) or "Try as admin"
├── Read-only for visitors OR sandboxed (reset every 24 hours)
├── Purpose: let church leaders experience the product without commitment
└── Link from marketing site: "See it in action →"

Step 2: Self-Service Tenant Creation (Auto-Approve, Flag Conflicts)

Every new tenant goes live immediately. No approval gate. No waiting. Growth > control.

The reality of adoption is bottom-up:

MONTH 1:  FEG Winterthur signs up. Creates tenant. Invites 80 members.
MONTH 2:  FEG Zuerich signs up independently. Creates tenant. 120 members.
MONTH 3:  FEG Bern signs up. 60 members.
MONTH 5:  FEG Schweiz (denomination HQ) notices three of their churches
          are already on the platform. They want a denomination tenant.
MONTH 6:  You create the FEG Schweiz denomination tenant.
          Winterthur, Zuerich, Bern merge as locations under FEG Schweiz.
          Members keep everything. Zero disruption.

Blocking churches with an approval gate would have killed months 1-3. Those 260 members are your traction, your social proof, and the reason the denomination HQ pays attention.

SELF-SERVICE FLOW (instant, no approval):

1. Marketing site -> "Set up your community" button

2. STEP 1: Basics (1 min)
   -- Organization name: "FEG Winterthur"
   -- Type: Church / Scout group / Youth org / Other
   -- Denomination / movement: [dropdown or free text]
      "Do you belong to a larger movement?"
      Options: ICF, FEG, Chrischona/Viva, EMK, Independent, Other
      NOT a gate. Just metadata for your dashboard.
   -- Your name + email
   -- Creates Zitadel account + Tenant (status: ACTIVE immediately)

3. STEP 2: Structure (1 min)
   -- How many locations? creates org tree
   -- Or: "Just one location" flat structure
   -- Pre-fills based on type

4. STEP 3: Branding (1 min)
   -- Upload logo
   -- Pick primary color
   -- Preview: "This is how your app will look"

5. STEP 4: Invite (1 min)
   -- Share link: "Join FEG Winterthur on [app name]"
   -- Copy link / QR code / send via email
   -- Members join immediately via web app

6. DONE. Live.
   -- Web app live: feg-winterthur.yourapp.com
   -- Members can join right now
   -- Admin backend ready
   -- Free tier for 50 members or fewer, no credit card
   -- 30-day trial of all paid features

TOTAL: 5 minutes from "I want to try this" to "my members are using it."
No approval. No waiting. No friction.

Your Super Admin Dashboard: Smart Conflict Detection

Instead of approving tenants, you monitor and consolidate. The dashboard flags potential conflicts automatically.

Conflict detection rules:

  • Same denomination selected: flag when 2+ independent tenants exist for same movement
  • Name similarity: flag “ICF Aarau” when “ICF Movement” tenant exists
  • Geography overlap: flag two churches in same city, same denomination
  • Run on every tenant creation + weekly batch check

Your workflow is reactive, not blocking:

  1. Church signs up, goes live immediately
  2. Dashboard flags potential conflicts
  3. You reach out proactively, or the denomination does
  4. When ready: create denomination tenant, merge the independents as locations
  5. This is also a sales trigger: “Three of your churches are already using us.”

Tenant Merge: Routine Operation, Not Edge Case

With bottom-up adoption, merge is one of the most common admin operations.

Merge scenarios by frequency:

COMMON (monthly at scale):

  • Independent church merges as location under denomination tenant
  • Multiple independent churches: denomination creates tenant, absorbs all

OCCASIONAL:

  • Two independent tenants merge (churches join forces)

RARE:

  • Denomination restructuring (church moves between denominations)

Merge flow:

MERGE: "FEG Winterthur" (independent) into "FEG Schweiz" (denomination)

1. INITIATION
   -- Superadmin triggers merge
   -- Select: source tenant, target tenant, target org node
   -- Both tenant admins confirm

2. PRE-MERGE CHECK
   -- Member overlap: "12 members exist in both tenants (same Zitadel ID)"
      These get OrgMembership added, not duplicated
   -- Data volume: "80 members, 8 groups, 45 events, 120 news posts"
   -- Preview shown to both admins

3. EXECUTION (automated)
   -- Create org node "Winterthur" under FEG Schweiz (if needed)
   -- Migrate members: new ones created, overlapping ones get OrgMembership
   -- Migrate groups: set organizationId to new Winterthur node
   -- Migrate events: set organizationId to new Winterthur node
   -- Migrate news: set organizationId to new Winterthur node
   -- Copy media assets to target tenant storage
   -- All domain events emitted (audit trail)

4. REDIRECT and NOTIFY
   -- Source tenant status: MERGED
   -- feg-winterthur.yourapp.com redirects to feg-schweiz.yourapp.com
   -- Push notification to migrated members:
      "FEG Winterthur has joined the FEG Schweiz family!
       All your groups, events, and content are here."
   -- Source tenant admin gets admin role in target tenant Winterthur node

5. GRACE PERIOD (30 days)
   -- Old URL still redirects
   -- Old data accessible in archived state
   -- After 30 days: old tenant data archived permanently

What members experience:

  • Push notification: “Your community has joined FEG Schweiz!”
  • Same web URL redirects seamlessly
  • Their groups, events, news: all there, now under a bigger umbrella
  • They now also see denomination-level news and events from sister churches
  • Login unchanged (Zitadel identity is the same)

Tenant Statuses

ACTIVE    -- live, members can join (default on creation)
SUSPENDED -- billing issue or policy violation
ARCHIVED  -- temporary tenant expired, or manually archived
MERGED    -- absorbed into another tenant, subdomain redirects

No PENDING status. No approval gate. Growth first, consolidate later.

App Delivery Strategy: Web Apps for Everyone, Native Apps for Denominations

The native app is the gate. Only denominations/movements get a native app in the stores. An individual church that belongs to a denomination does NOT get its own native app — they should call their denomination. But every church gets a web app instantly.

APP DELIVERY MATRIX:

                        WEB APP (PWA)          NATIVE APP
                        ─────────────          ──────────
Denomination            ✅ {slug}.app.com       ✅ Own app in stores
(ICF Movement)          (denomination-wide)     (CHF 2,000 setup)

Individual church       ✅ {slug}.app.com       ❌ Not available
within a denomination   (scoped to their        "Contact your
(ICF Zürich Oerlikon)   location)               denomination"

Independent church      ✅ {slug}.app.com       ✅ Own app in stores
(not part of a          (full tenant access)    (if they pay for it)
denomination)

Per-Location Web Apps (Within a Tenant)

This is the key insight: a web app doesn’t have to be tenant-wide. An individual location within a denomination tenant can have its own scoped web app entry point.

ICF MOVEMENT TENANT:

Tenant-level web app:
  icf.yourapp.com                    → full ICF Movement experience
                                       (all locations, all content)

Per-location web apps:
  icf-zurich.yourapp.com             → scoped to ICF Zürich
  icf-zurich-oerlikon.yourapp.com    → scoped to ICF Zürich Oerlikon
  icf-basel.yourapp.com              → scoped to ICF Basel
  icf-muenchen.yourapp.com           → scoped to ICF München

Each per-location web app:
├── Same tenant, same backend, same data
├── BUT: default view scoped to that location's org node
├── Member sees: their location's news, groups, events first
├── Content from parent orgs (ICF CH, ICF Movement) cascades down
├── Member CAN navigate up to see other locations (if they want)
├── "Add to home screen" → feels like their own church's app
└── Branded: same denomination branding (ICF), location name in header

How it works technically:

URL RESOLUTION:

Request: icf-zurich-oerlikon.yourapp.com

1. Cloudflare wildcard DNS: *.yourapp.com → your server
2. Symfony middleware extracts subdomain: "icf-zurich-oerlikon"
3. Lookup: subdomain → (tenantId, orgId)
   ├── Table: subdomain_mappings
   │   ├── "icf" → tenantId: icf-uuid, orgId: null (tenant root)
   │   ├── "icf-zurich" → tenantId: icf-uuid, orgId: zurich-uuid
   │   └── "icf-zurich-oerlikon" → tenantId: icf-uuid, orgId: oerlikon-uuid
   └── Result: tenant = ICF Movement, scoped to org = Oerlikon
4. API responses filtered to this org scope by default
5. Web app loads with Oerlikon as the "home" context
6. Content cascade: Oerlikon news + Zürich news + ICF CH news + ICF Movement news

Admin configures this in the admin backend:

  • Denomination admin goes to org tree → selects “ICF Zürich Oerlikon”
  • “Enable web app for this location” → generates subdomain
  • Custom slug optional (default: auto-generated from org name)
  • The location admin can share their specific web app link with their members

Why this matters for adoption:

  • ICF Oerlikon pastor doesn’t need to wait for the denomination to create their native app
  • They get icf-zurich-oerlikon.yourapp.com immediately
  • Members “add to home screen” → it looks and feels like their own app
  • When ICF Movement eventually publishes the native app, members can switch
  • Zero disruption: same account, same data, native app just has better push + UX

Step 3: Native App (Denomination Only)

The native app is a denomination commitment. It’s the premium tier — a branded app in the stores with the denomination’s name, icon, and identity.

NATIVE APP RULES:
├── Available to: denominations, movements, large independent churches
├── NOT available to: individual locations within a denomination
│   "ICF Zürich Oerlikon" does NOT get its own native app
│   They use the ICF Movement native app (scoped to their location)
│   OR their per-location web app
├── Requirement: paid subscription (Movement tier or denomination deal)
├── Setup fee: CHF 2,000 (covers build config + store submission)
└── The native app serves ALL locations within the denomination

NATIVE APP PROCESS:

1. Denomination decides: "We want our own app in the stores"

2. REQUIREMENTS:
   ├── Movement tier subscription or denomination deal
   ├── Apple Developer Account (€99/year — they create it)
   ├── Google Play Developer Account ($25 one-time — they create it)
   └── Setup fee: CHF 2,000

3. YOU DO:
   ├── Configure Expo build: app name, bundle ID, icons, splash screen
   ├── Tenant config: API endpoint, tenant slug, branding
   ├── EAS Build → iOS + Android binaries
   ├── Submit to stores (using their developer accounts)
   └── Turnaround: 1-3 weeks

4. THE NATIVE APP:
   ├── Member downloads "ICF" app from store
   ├── Signs up / logs in → selects their location (Zürich Oerlikon)
   ├── Home screen scoped to their location (same as web app)
   ├── Can navigate to other locations, denomination content
   ├── Full native push notifications
   ├── OTA updates via Expo (JS changes skip store review)
   └── Web app remains as fallback / desktop access

Self-Service vs. Sales-Assisted

                    SELF-SERVICE           SALES-ASSISTED
                    (website → web app)    (your network → deal)

Target:             Individual churches,   Denominations,
                    small orgs, curious    large churches,
                    leaders exploring      committed buyers

Entry:              Free tier, no          Demo call, pilot
                    credit card            agreement, setup fee

Onboarding:         5-min web wizard       Personalized: you set
                                           up the tenant, import
                                           data, configure the tree

App delivery:       Web app (instant)      Web app (immediate) +
                                           native app (1-3 weeks)

Billing:            Self-service Stripe    Invoice, denomination
                    checkout when ready    discount, annual contract

Support:            Docs + email           Direct line to you

Expected volume:    80% of tenants         20% of tenants
                    (many small churches)  (most of the revenue)

MVP Implication

The web app (PWA) MUST be in MVP. Without it, every new church requires manual App Store setup — which means you can’t self-service, can’t have a demo tenant, can’t onboard pilot churches quickly. The web app is the growth engine.

This changes the MVP technical scope slightly:

ADDED TO MVP:
├── Web build of the React Native app (Expo Web / PWA)
│   ├── Same codebase as native (React Native Web via Expo)
│   ├── Hosted on Cloudflare Pages: {slug}.yourapp.com
│   ├── Service worker for offline support + web push notifications
│   └── "Add to home screen" prompt for app-like experience

├── Self-service tenant creation wizard
│   ├── Web-based (part of marketing site or separate onboarding app)
│   ├── Creates: Zitadel org + tenant + first admin + org tree
│   ├── Generates subdomain
│   └── Redirects to admin backend

└── Demo tenant
    ├── Pre-populated with realistic data
    ├── Accessible from marketing site
    └── Reset daily or sandboxed per visitor

MVP Timeline Summary

Weeks 1-3:    Foundation (infra, Symfony, Zitadel, pipeline, Expo shell)
Weeks 4-8:    Core modules (people, groups, events, news, push — API + admin)
Weeks 8-12:   Frontend polish + web app (PWA) + native demo app + deployment pipeline
Weeks 12-18:  Pilot (3-5 churches on staging/beta, iterate fast)
Week 18:      Decision: ready for first denomination pitch?

TOTAL: ~3 months to working product. ~4.5 months to validated pilot.

The deployment pipeline is the force multiplier. Once staging auto-deploys on merge, the iteration loop is: code → push → live on staging in 5 minutes → pilot users test → tag release → production in 10 minutes. This is how a solo founder ships as fast as a team.


MVP Definition of Done

The MVP is “done” when a pilot church admin can:

  • Self-service create a tenant (wizard, live immediately)
  • Configure their org structure
  • Set registration mode per org (open, invite-only, by-request)
  • Invite members (via link, QR code, or email via Mailgun)
  • See and manage pending invitations
  • Post news that members see with a push notification
  • Create groups that members can browse and join
  • Create events that members can RSVP to
  • View a member directory
  • See basic dashboard (member count, recent activity)

And a pilot church member can:

  • Open the web app ({slug}.yourapp.com) on any device
  • Sign up with email/password (receive verification email via Mailgun)
  • Reset password (email flow via Zitadel + Resend)
  • Join an open org seamlessly on first login (auto-join)
  • Accept an invite link to join an invite-only org
  • Switch between orgs (if member of multiple)
  • Leave an org they no longer belong to
  • Set language preference (DE/EN)
  • See news from their church (and parent org)
  • Browse and join groups
  • See upcoming events and RSVP (Level 1 + 2)
  • Find other members in the directory
  • Receive push notifications (web push on PWA, native push on demo app)
  • Edit their profile and privacy settings

And the demo native app:

  • Available in App Store + Play Store
  • Points to demo tenant with realistic data
  • Showcases the full member experience
  • Proves native performance and push notifications work

And the deployment pipeline:

  • Push to main → staging auto-deploys in < 5 minutes
  • Tag release → production deploys in < 10 minutes
  • Pilot users on staging get features before production

If all checklists pass: ship it. Start onboarding pilots.


What Makes This MVP Enough

The MVP competes directly with Communiapp’s core offering (news, groups, events, directory, push) at a lower price with better architecture. It doesn’t yet compete on giving (Donkey Mobile’s strength) or church management (ChurchTools). That’s fine — the first pilot is about proving the member experience and the self-service onboarding, not the feature list.

The web app (PWA) is the growth engine: any church can be live in 5 minutes. The native demo app is the showcase: proves the quality. The automated pipeline is the iteration engine: ship improvements daily during pilot.

The architecture is ready for everything else. Giving, chat, Sunday, ticketing, translation, syndication — they all plug into the module system. The domain events are flowing. The Deptrac boundaries are enforced. The .ai/ directory guides every agent. When Phase 2 starts, it’s adding modules to a proven platform, not building from scratch.


Status: MVP Scope v2 — Ready to Build Next: Start coding. Scaffold the foundation. Read the .ai/ guidelines.