Skip to main content

Overview

A church in Project Zoe is organised as a tree of groups. Every group belongs to a category that defines its level in the hierarchy. The default six-level hierarchy used by Worship Harvest looks like this:
This tree is modelled in PostgreSQL using a closure table via TypeORM’s @Tree('closure-table') decorator, which makes ancestor/descendant queries efficient at any depth.

Group entity

Key fields on a Group:

Group categories

GroupCategory records are created per tenant. The standard categories match the six hierarchy levels, but a tenant can define custom categories for auxiliary groups (e.g. “Choir”, “Youth Wing”) that sit outside the main pastoral hierarchy.

Memberships

A contact joins a group through a GroupMembership record: A contact can be a member of multiple groups simultaneously (e.g. a fellowship member who also leads a zone worship team).

Membership requests

Before being added to a group, a contact may go through a GroupMembershipRequest. Leaders can approve or reject pending requests.

Access scoping by hierarchy

Role-based access in Project Zoe scopes data to a leader’s position in the tree:
  • A Fellowship leader sees only their fellowship’s members and data.
  • A Zone leader sees all fellowships under their zone.
  • A Location pastor sees all zones and fellowships in their location.
  • A Movement leader sees the entire global hierarchy.
This scoping is enforced server-side on every API query by checking the requesting user’s group membership and role. See Authentication & Roles.

Demo hierarchy

The demo seed creates this 68-group structure across two networks: