# 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) - JSON-based data storage under `data/` - Daily automated exports (`scripts/daily_export.php` and `export.php?type=…`) - Mobile-friendly interface ## Setup 1. Clone this repository to your web server. 2. **Configure the environment** - With a browser, open the app URL (for example `http://your-server/familyHub/`). If `.env` is missing, you are redirected to **`install.php`**, which builds `.env` from **`env.example`**. - Alternatively, copy `env.example` to `.env` and edit `.env` by hand. - See [Environment variables](#environment-variables) below for where to get each value. 3. Ensure proper permissions on the `data` directory (and that the web server can create or write JSON files there). 4. Set up the daily cron job for exports (see `scripts/daily_export.php`). It writes one JSON file per type into `exports/` (for example `chores`, `groceries`, `meals`, **`meal_plans`**, `expenses`, `stores`, `grocery_lists`, `grocery_catalog`). From the command line, the script exits with an error if `.env` is missing; complete browser setup first or copy `env.example` manually. 5. 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](https://console.cloud.google.com/)**. 1. Create or select a **project**. 2. 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). 3. 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). 4. Open **APIs & Services → Credentials → Create credentials → OAuth client ID**. Choose **Web application** if your app uses a browser redirect. 5. Under **Authorized redirect URIs**, add the exact URL you will put in **`GOOGLE_REDIRECT_URI`** in `.env` (scheme, host, path, no trailing slash unless your app uses one). Use the official [Google Cloud OAuth documentation](https://developers.google.com/identity/protocols/oauth2) 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](https://calendar.google.com/)** → 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](https://drive.google.com/)** → 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 `; 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): ```json { "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. ## Directory Structure ``` familyHub/ ├── api/ # JSON POST endpoints (chores, groceries, meals, people, settings, expenses, calendar_events, …) ├── 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 │ ├── 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) ```