- Added a modal for editing person details, including name, role, favorite color, birthday, and description. - Implemented visibility toggling for PIN input based on role selection, ensuring security for Head of Household. - Introduced birthday reminder functionality in the calendar, generating events for upcoming birthdays with appropriate notifications. - Updated calendar and settings UI to accommodate new features, improving user experience and data management.
Family Hub
A centralized family organization system with tabs for chores, groceries, meal planning, family currency, and settings.
Features
- Tabbed interface for chores, groceries, meals, combined Calendar (Family Hub agenda plus optional Google embed), currency, and family settings (profiles, stores, preferences)
- Optional banking mode in the Currency tab: per-person checking, savings, and charity accounts with transfer rules and HoH controls
- Banking safeguards and reporting: irreversible transfers into charity, immutable transaction reversals, and monthly statements (JSON/CSV)
- JSON-based data storage under
data/ - Daily automated exports (
scripts/daily_export.phpandexport.php?type=…) - Mobile-friendly interface
Setup
- Clone this repository to your web server.
- Configure the environment
- With a browser, open the app URL (for example
http://your-server/familyHub/). If.envis missing, you are redirected toinstall.php, which builds.envfromenv.example. - Alternatively, copy
env.exampleto.envand edit.envby hand. - See Environment variables below for where to get each value.
- With a browser, open the app URL (for example
- Ensure proper permissions on the
datadirectory (and that the web server can create or write JSON files there). - Set up the daily cron job for exports (see
scripts/daily_export.php). It writes one JSON file per type intoexports/(for examplechores,groceries,meals,meal_plans,expenses,stores,grocery_lists,grocery_catalog,bank_transactions). From the command line, the script exits with an error if.envis missing; complete browser setup first or copyenv.examplemanually. - Access the hub at
http://your-local-ip/familyHub/(adjust path and host to match your deployment).
Google Cloud prerequisites (OAuth + APIs)
Most Google-related values come from Google Cloud Console.
- Create or select a project.
- Open APIs & Services → Library, then enable any APIs you rely on (for example Google Calendar API and Google Drive API if you use those integrations).
- Open APIs & Services → OAuth consent screen and complete it for your use case (Internal for Workspace-only, External for broader testing; test users may be required until published).
- Open APIs & Services → Credentials → Create credentials → OAuth client ID. Choose Web application if your app uses a browser redirect.
- Under Authorized redirect URIs, add the exact URL you will put in
GOOGLE_REDIRECT_URIin.env(scheme, host, path, no trailing slash unless your app uses one).
Use the official Google Cloud OAuth documentation for details if anything in the console changes.
Environment variables
Values are defined in env.example. The install wizard reads that file only; use this section to learn where to obtain each value.
Google API credentials
| Variable | What it is | Where to find it |
|---|---|---|
GOOGLE_CLIENT_ID |
Public OAuth 2.0 client ID for your app | Google Cloud Console → APIs & Services → Credentials. Open your OAuth 2.0 Client ID (Web application). Copy Client ID. |
GOOGLE_CLIENT_SECRET |
Secret for the same OAuth client | Same credential row. Copy Client secret (treat it like a password; never commit it). |
GOOGLE_REDIRECT_URI |
URL Google redirects to after OAuth | Must match exactly one of Authorized redirect URIs on that OAuth client. Set it to your real callback URL (e.g. https://yourdomain.com/family-hub/auth/google/callback). Use the same scheme and path your server exposes. |
Google Calendar
The Calendar tab embeds your family calendar in the hub using these values (HTTPS Google Calendar URLs only; optional iframe src is extracted from pasted HTML).
| Variable | What it is | Where to find it |
|---|---|---|
GOOGLE_CALENDAR_ID |
ID of the calendar to target (APIs, sharing, embeds) | Google Calendar → hover the calendar in the sidebar → ⋮ → Settings and sharing → scroll to Integrate calendar → Calendar ID (often an email or ...@group.calendar.google.com). If GOOGLE_CALENDAR_EMBED_CODE is unset, the tab builds a standard embed URL from this ID. |
GOOGLE_CALENDAR_EMBED_CODE |
Embed URL or full iframe HTML from Google | Same Settings and sharing page → Integrate calendar → copy the embed code (iframe) or the https://calendar.google.com/... URL from the src attribute. Prefer this when you want Google’s chosen view options. |
Google Drive
| Variable | What it is | Where to find it |
|---|---|---|
GOOGLE_DRIVE_FOLDER_ID |
Folder used as export or attachment root | Google Drive → open the folder in the browser. The URL looks like https://drive.google.com/drive/folders/THIS_PART_IS_THE_ID — copy THIS_PART_IS_THE_ID. |
Application settings
| Variable | What it is | Where to find it |
|---|---|---|
APP_ENV |
Logical environment name | Your choice (e.g. development, staging, production). Used for app behavior toggles if the code checks it. |
APP_DEBUG |
Verbose errors / debug mode | true or false (strings as in env.example). Only use true on trusted local or staging servers. |
APP_URL |
Base URL of this app | Same origin users use in the browser (e.g. https://example.com/family-hub), no trailing path beyond the app root unless your deployment requires it. Should align with GOOGLE_REDIRECT_URI host/path where applicable. |
Export settings
| Variable | What it is | Where to find it |
|---|---|---|
EXPORT_FREQUENCY |
How often exports are expected to run | Your choice (e.g. daily). Match how you schedule scripts/daily_export.php in cron. |
EXPORT_RETENTION_DAYS |
How long to keep export files (interpreted by app logic) | Integer number of days (e.g. 30). |
MCP / AI automation (optional)
These enable machine-to-machine access to the same JSON APIs the browser uses. When MCP_API_TOKEN is non-empty, API requests may send Authorization: Bearer <MCP_API_TOKEN>; the app then treats the request as the Head of household identified by MCP_ACTOR_PERSON_ID (PIN-verified semantics), without a browser session.
| Variable | What it is | Where to find it |
|---|---|---|
MCP_API_TOKEN |
Shared secret for automation (Cursor MCP, scripts, etc.) | Generate locally (treat like a password). Example: openssl rand -hex 32. Paste into .env. Never commit the real value. If left empty, Bearer impersonation is disabled and only normal browser sessions work. |
MCP_ACTOR_PERSON_ID |
Which person the token impersonates | Open data/people.json (after setup) and copy the id field for your Head of household profile. Must match a person whose role is head_of_household. Wrong or non-head IDs are ignored and the token will not authenticate. |
Security: The token grants the same power as a logged-in, HoH-verified session (create chores, manage people, grocery data, etc.). Use HTTPS in production. Rotate the token by changing .env and restarting anything that caches env.
Cursor MCP: The MCP server is plain PHP (no Node): mcp/familyhub/server.php. Register it in Cursor Settings → MCP with the absolute path to PHP and the script, and set environment variables FAMILYHUB_BASE_URL (your hub’s …/api URL, e.g. http://localhost/family-hub/api) and FAMILYHUB_MCP_TOKEN (same value as MCP_API_TOKEN). Tools exposed: familyhub_health, familyhub_get_snapshot, familyhub_calendar_events, familyhub_post_api (allowlisted POST endpoints only).
Example mcp.json server entry (adjust paths and env):
{
"mcpServers": {
"familyhub": {
"command": "php",
"args": ["/full/path/to/familyHub/mcp/familyhub/server.php"],
"env": {
"FAMILYHUB_BASE_URL": "http://localhost/family-hub/api",
"FAMILYHUB_MCP_TOKEN": "paste-the-same-secret-as-MCP_API_TOKEN"
}
}
}
}
Calendar preferences (family settings)
These are not in .env; they live in data/family_settings.json and are edited under Family settings → Calendar and dates.
| Key / UI | Purpose | Notes |
|---|---|---|
| Family timezone | US IANA zone (e.g. America/Denver) |
Dropdown of US zones only. Drives today and date ranges on the Calendar tab agenda. Options are the standard PHP US timezone identifiers (e.g. America/*, Pacific/Honolulu). |
| Enable two-way Google Calendar sync | Opt-in for future OAuth sync with Google | Default off. When off, the Calendar tab uses the Google embed from .env (if set) and the local agenda only—no merge API. When on, the app may show sync messaging; full OAuth is not required for the embed. |
| Monthly bill reminders | calendar_bill_days |
JSON array of { "dayOfMonth": 1–31, "title": "Rent" }. Shown on the agenda on that calendar day each month. |
API: GET api/calendar_events.php?from=YYYY-MM-DD&to=YYYY-MM-DD returns { success, events, rangeStart, rangeEnd, today } for the signed-in profile (same session rules as other APIs). Omit from/to to use the default two-week window from today in the family timezone.
Banking mode (optional)
Enable this in Family settings → Chore economy → Banking system.
- Accounts per person
checking_balance: primary spendable chore income balance.savings_balance: earns the configured monthly rate, compounded daily via lazy apply when balances are read/written.charity_pending_balance: funds committed to charity and not transferable back out.charity_donated_total: historical amount already logged as donated by HoH.
- Income routing
- Approved chore payouts and HoH manual credits flow through checking.
- Optional auto split sends a percent of each incoming credit to savings and charity.
- Optional round-up rule moves each income credit’s fractional remainder to either savings or charity.
- Permissions
- Any active person can move their own funds between checking/savings/charity, but cannot transfer out of charity.
- Verified HoH can add checking credits/debits, log charity outflows, and reverse transactions with immutable compensating entries.
- Donation goals
- Per-person monthly donation goals with progress based on current-month charity outflow totals.
- Statements
GET api/bank_statement.php?month=YYYY-MM&format=json|csv[&person_id=...]- Non-HoH users can fetch only their own statement; verified HoH can request any person.
NFC chore submission (HoH)
NFC support uses per-chore tokens plus per-person submitter tokens so a scan can submit as a specific person and credit that person after HoH approval.
Family settings for NFC
In Family settings → Chore economy:
- NFC base URL override (
nfc_base_url): optional app base URL used when generating NFC links. Leave blank to auto-detect from the current request. - NFC scan cooldown seconds (
nfc_scan_cooldown_seconds): optional soft replay dampener (0-600 seconds). - Show NFC confirmation page after scan (
nfc_show_confirmation): when off, NFC scans redirect directly to chores. - Emergency NFC actions:
- Disable all chore NFC links
- Rotate all person NFC submitter tokens
HoH setup checklist (per chore)
- Open Chores as a verified Head of household.
- For a chore, optionally enable Allow anyone to complete this chore.
- Click Generate NFC links.
- Copy each person-specific URL and write it to that person’s NFC card/tag (NDEF URI).
- Label tags physically (name + chore).
- Test scan once per person.
NFC URL format
Generated links use:
/api/chore_submit_nfc.php?id=<chore_id>&token=<chore_token>&person_token=<person_token>
tokenidentifies the chore NFC token.person_tokenidentifies who is submitting (credit recipient on approval).
Completion and credit rules
- Assignee-only chore (
anyone_can_complete = false): only assignees may submit, even with valid person tokens. - Anyone-can-complete chore (
anyone_can_complete = true): any valid person token holder may submit. - Credit is always applied only on HoH approval (not at scan time), to the
submitted_byperson on the pending submission.
Troubleshooting
- Invalid chore token: regenerate chore NFC links and rewrite tags.
- Invalid submitter token: rotate that person token and regenerate links.
- Already pending review: wait for HoH approve/reject.
- Chore inactive: reactivate/update chore before scanning again.
- Lost/shared card: rotate token(s) or disable chore NFC immediately.
Security notes
- NFC links are bearer-style secrets. Anyone with a valid URL can submit as that URL’s person token.
- Use HTTPS in production and rotate tokens on loss/suspected leakage.
- Keep HoH approval enabled as the payout gate.
Directory Structure
familyHub/
├── api/ # JSON endpoints (chores, groceries, meals, people, settings, expenses, banking, calendar_events, NFC helpers, …)
├── assets/ # Static assets
│ ├── css/ # CSS files
│ │ └── style.css
│ ├── js/ # JavaScript files
│ │ └── main.js
│ └── img/ # Images
├── config/ # Configuration files
│ ├── config.php
│ └── env.php # Loads .env
├── data/ # JSON data storage (not tracked in git)
│ ├── chores.json # Chores, assignments, submissions, reviews
│ ├── people.json # Profiles, roles, PIN hashes, currency balances
│ ├── family_settings.json # Currency labels, US timezone, week start, calendar merge flag, bill reminders, etc.
│ ├── expenses.json # Head-of-household expense log
│ ├── bank_transactions.json # Banking ledger (credits, debits, transfers, outflows, reversals)
│ ├── stores.json # Grocery store definitions
│ ├── grocery_lists.json # Per-store shopping lines
│ ├── grocery_catalog.json # Deduped catalog / recurring metadata
│ ├── groceries.json # Legacy single-file groceries; migrated when detected
│ ├── meals.json # Meal library (titles, tags, ingredients, shopping items)
│ └── meal_plans.json # Active weekly plan: `weekStart` (Monday YYYY-MM-DD) and `slots` 0–6 × breakfast/lunch/dinner → meal id or empty
├── includes/ # PHP includes (db, persona, tab helpers, `api_bootstrap.php`, …)
│ ├── header.php
│ ├── footer.php
│ ├── db.php # JSON file I/O (flock)
│ └── utils.php # Shared helpers
├── exports/ # Export output (not tracked in git)
├── scripts/ # Cron / CLI helpers
│ └── daily_export.php
├── mcp/familyhub/ # Optional MCP stdio server (PHP only): `server.php`
├── tabs/ # Tab views included by `index.php`
│ ├── chores.php
│ ├── groceries.php
│ ├── meals.php
│ ├── calendar.php
│ ├── currency.php
│ └── settings.php
├── env.example # Environment template (parsed by install.php)
├── install.php # Web wizard to create .env when missing
├── .gitignore
├── .cursor/ # Cursor editor configuration and rules
├── readme.md
├── index.php # Main entry point
├── AGENTS.md # Agent / contributor notes
└── export.php # `?type=` JSON export (same types as daily script)