The core of the ɳFamily stack. Defines your family members, their relationships, and the invitation flow that brings new members in — with a COPPA-compliant age gate for children.
nself-family is the required foundation for all other ɳFamily plugins. Install it first. Every other family plugin checks for a valid member record before allowing access.
nself license set nself_pro_...
nself plugin install family
nself build
nself startnself-family maintains a graph of people and their relationships. A person record holds a display name, profile photo, date of birth, and role (admin or member). Relationships are typed edges: parent, child, spouse, sibling, grandparent. The graph is undirected — adding a parent relationship automatically creates the reverse child edge.
Invitations work by email or invite link. The inviting member sets the relationship type, and the invited person accepts via a one-time link. On acceptance, both person records are linked and the new member gains access to all content visible to their role. Invite links expire after 7 days and can be revoked before acceptance.
The COPPA age gate applies to any member with a date of birth that puts them under 13. Child accounts cannot invite new members, cannot change their own privacy settings, and are only visible within the family graph — not in search. An admin (parent) must approve any change to a child account.
| Variable | Required | Default | Description |
|---|---|---|---|
PLUGIN_FAMILY_INVITE_EXPIRY_HOURS | No | 168 | How long an invite link remains valid (7 days) |
PLUGIN_FAMILY_COPPA_AGE_THRESHOLD | No | 13 | Age below which COPPA restrictions apply |
PLUGIN_FAMILY_MAX_MEMBERS | No | 500 | Hard cap on family graph size |
PLUGIN_FAMILY_RELATIONSHIP_TYPES | No | parent,child,spouse,sibling,grandparent,cousin,other | Allowed relationship types. Add custom types as needed. |
PLUGIN_FAMILY_REQUIRE_DOB | No | false | Require date of birth on member creation (needed for COPPA gate) |
| Endpoint | Method | Description |
|---|---|---|
/family/members | GET | List all family members visible to the authenticated user |
/family/members | POST | Create a member record (admin only — use invites for self-registration) |
/family/members/:id | GET / PATCH | Get or update a member profile |
/family/relationships | GET / POST | List or add relationship edges |
/family/graph | GET | Full graph as nodes + edges (for tree rendering) |
/family/invites | POST | Create an invite. Body: { email, relationship_type, role } |
/family/invites/:token/accept | POST | Accept an invite and create the member record |
/family/invites/:token/revoke | POST | Revoke an outstanding invite (inviter or admin) |
/health | GET | Plugin health check |
| Table | Purpose |
|---|---|
np_family_members | Person: display_name, dob, role, avatar_media_id, auth_user_id (nullable for unregistered ancestors) |
np_family_relationships | Directed edge: from_member_id, to_member_id, relationship_type |
np_family_invites | Token, inviter_id, email, relationship_type, role, expires_at, accepted_at |
np_family_groups | Named subsets of members for scoped visibility (grandparents, kids, etc.) |
np_family_group_members | Group membership join table |
| Event | Payload |
|---|---|
family.member.joined | Member ID, display name, relationship to inviter, joined_at |
family.invite.created | Invite token (hashed), inviter ID, email (hashed), relationship type |
family.relationship.added | From member ID, to member ID, relationship type |
Every other ɳFamily plugin checks np_family_members for a valid member record before granting access. If a user is in the nself auth system but not in the family graph, they are treated as unauthenticated by all family plugins. Run nself plugin install family and create the first admin member before installing any other ɳFamily plugin.
# Bootstrap the first family admin
curl -X POST http://127.0.0.1:3824/family/members \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{"display_name": "Admin", "role": "admin", "dob": "1980-01-01"}'
# Invite a family member
curl -X POST http://127.0.0.1:3824/family/invites \
-H "Authorization: Bearer <admin_token>" \
-H "Content-Type: application/json" \
-d '{"email": "grandma@example.com", "relationship_type": "grandparent", "role": "member"}'| Feature | nself-family | Ancestry.com | FamilyAlbum |
|---|---|---|---|
| Self-hosted graph | Yes | No | No |
| COPPA compliance | Age gate built-in | No account for under-13 | Parent-controlled profiles |
| Custom relationship types | Yes | Fixed set | No |
| Open data export | GEDCOM + JSON via API | GEDCOM (gated) | No |
| Symptom | Fix |
|---|---|
| All family plugin endpoints return 403 | The authenticated user has no member record. Create one via POST /family/members as admin. |
| Invite link expired | Revoke the old invite and create a new one. Expiry is set by PLUGIN_FAMILY_INVITE_EXPIRY_HOURS. |
| Child account cannot post | Expected behavior. COPPA gate blocks members under PLUGIN_FAMILY_COPPA_AGE_THRESHOLD from creating content. An admin must post on their behalf or verify age is set correctly. |
Port: 3824 | Bundle: ɳFamily ($0.99/mo) or ɳSelf+ ($3.99/mo) | Last Updated: May 2026 | Plugin Version 1.0.13