# Project pack: Homepage @ 44bf8c1

Facts about **Homepage** for an AI following the [BespokeAI handover guide](https://handoff.bespokeai.software/guide/v2.md). This pack is pinned to one version and never changes after publication.

> Homepage is a start page for your browser or a wall tablet. It gathers the links your household uses into tidy, labelled tiles, with the weather, the date, a search box and live numbers from your home apps, such as tonight's meal from Mealie or how many photos are in Immich. You set it up by editing a few simple text files, so an AI can write them for you. It runs on your own computer and keeps your app passwords out of the browser.

## Version and source
- Repository: https://github.com/gethomepage/homepage
- Pinned commit: `44bf8c196232592049d99275f7c58718d167e9e4`. Use exactly this version.
- Fresh checkout: use the setup below in an empty folder. If you already have this exact source checked out, keep your branch and use the development command instead; do not clone again or reset local changes.
- Or download a zip: https://github.com/gethomepage/homepage/archive/44bf8c196232592049d99275f7c58718d167e9e4.zip
- Official docs: https://gethomepage.dev
- Licence: **GPL-3.0-only**. Free to use and change. If you give a changed copy to other people, you must share your source code under the same licence. Running it for yourself or your household has no extra obligations.

## Running the pinned source
- Fresh pinned-source setup (skip clone and checkout in an existing worktree):

  ```sh
  git clone https://github.com/gethomepage/homepage bespoke-homepage
  cd bespoke-homepage
  git checkout --detach 44bf8c196232592049d99275f7c58718d167e9e4
  # Prepare development requirements and local configuration first.
  # Setup notes: http://localhost:3000; copy src/skeleton to config/ first
  pnpm install && pnpm dev
  ```

The commands below are a starting point from the reviewed source. Prepare the listed tools, local configuration and companion services before starting the app. These instructions have not yet been validated in participant sessions.

### Separate trial of the current release
This tries an upstream release, which may differ from the pinned source above. It does not run your source changes. Use only sample data and a separate data directory or volume. Check the upstream documentation before running it.

  ```sh
  docker run -d --name homepage -p 3000:3000 -e HOMEPAGE_ALLOWED_HOSTS=localhost:3000 -v /path/to/config:/app/config --restart unless-stopped ghcr.io/gethomepage/homepage:latest
  # then open http://localhost:3000; example config files appear in /path/to/config on first start.
  # Add the address you'll use (e.g. 192.168.1.20:3000) to HOMEPAGE_ALLOWED_HOSTS.
  ```

- Needs: Docker (AMD64 or ARM64, so a Raspberry Pi works), For development, Node.js 22 and pnpm
- Develop: `pnpm install && pnpm dev   # http://localhost:3000; copy src/skeleton to config/ first`
- Test: `pnpm test`
- Check/lint: `pnpm lint`
- Build: `pnpm build`
- Stack: javascript, yaml, css (Next.js 16, React 19, Tailwind CSS, next-i18next, NextAuth, Vitest). Difficulty for a non-developer with an AI: **easy**. Everything you see is defined in a handful of YAML files (services, bookmarks, widgets, settings), with custom.css and custom.js for looks. No database. A new service widget is a small, well-documented folder in src/widgets/ with many examples to copy.

## Customisation points (settings → extend → code)
- **services-and-bookmarks** [settings]: Groups of tiles with names, icons and links, plus plain bookmark lists. Sort them by room, person or purpose. → `services.yaml and bookmarks.yaml in the config folder (examples in src/skeleton/; docs/configs/services.md, docs/configs/bookmarks.md)`
- **look-and-layout** [settings]: Name the page, pick a background photo and colour, arrange groups in columns or tabs. → `settings.yaml (src/skeleton/settings.yaml; docs/configs/settings.md) → title, background, theme, colour, layout, tabs, card style, language`
- **info-widgets** [settings]: The top bar with "Good morning", the clock, today's weather and a search box. → `widgets.yaml (docs/widgets/info/, src/components/widgets/) → greeting, date and time, weather, search, resources`
- **custom-css-js** [settings]: Bigger text for a wall tablet, hide elements, or small tweaks without rebuilding. → `custom.css and custom.js in the config folder (docs/configs/custom-css-js.md)`
- **service-widgets** [extend]: Live numbers from your apps, a shared calendar, or any JSON API through the custom API widget. → `widget section of a service in services.yaml (docs/widgets/services/, e.g. homeassistant.md, mealie.md, immich.md, calendar.md, customapi.md, iframe.md)`
- **docker-discovery** [extend]: Tiles appear automatically for containers that carry homepage labels. → `docker.yaml and container labels (docs/configs/docker.md, src/utils/config/docker.js)`
- **mcp** [extend]: Let an AI assistant such as Claude read your setup and, if you allow it, add tiles for you. → `/api/mcp endpoint (docs/configs/mcp.md, src/utils/mcp/homepage-mcp.js)`
- **new-widget** [code]: A widget for an app that isn't supported yet. → `src/widgets/<name>/ (widget.js + component.jsx), registered in src/widgets/widgets.js and src/widgets/components.js; text in public/locales/en/common.json; guide in docs/widgets/authoring/`

## Must keep working
- The config folder. Copy it before experimenting; one YAML indentation mistake can blank the page.
- API keys stay on the server. Widgets must keep fetching through Homepage's proxy, never from the browser directly.
- HOMEPAGE_ALLOWED_HOSTS and login settings. Don't set allowed hosts to * on anything reachable from the internet.
- Existing widget names and options, so other people's config files keep working.

## Staying updatable
Nearly everything is configuration, so most people never need a fork. Homepage's contributing guide says it generally does not accept AI-generated pull requests, and any AI help must be stated clearly in the PR. Keep AI-written widgets in your own copy unless you have reviewed and understood them yourself.

## Data, costs and safety
- Personal data: **no**. Stored in: YAML files plus custom.css and custom.js in the config folder (/app/config in Docker). No database. The config folder holds API keys for your other apps, so treat it as private. Back it up or keep it in a private Git repository; restoring is just copying the files back. Use HOMEPAGE_VAR_ or HOMEPAGE_FILE_ variables to keep keys out of the YAML.
- Service: Your other self-hosted apps (Home Assistant, Mealie, Immich, Paperless and 150+ more) (optional, free): Service widgets show live numbers from these apps using API keys you put in the config.
- Service: Weather providers (Open-Meteo, OpenWeatherMap, WeatherAPI) (optional, free (Open-Meteo needs no key)): Weather in the top bar.
- Service: OIDC sign-in provider (Authentik, Authelia, Keycloak…) (optional, free (self-hosted) or varies): Optional login in front of the page instead of a simple password.
- Setting `HOMEPAGE_ALLOWED_HOSTS`: The addresses you open Homepage at, comma-separated (e.g. 192.168.1.20:3000). Needed for anything other than localhost.
- Setting `PUID`: Run as this user ID instead of root (PGID for the group). Make sure the config folder belongs to that user.
- Setting `HOMEPAGE_AUTH_ENABLED`: Set to true to require a login. Needs HOMEPAGE_AUTH_SECRET, HOMEPAGE_EXTERNAL_URL and a password or OIDC settings.
- Setting `HOMEPAGE_AUTH_SECRET` (**secret**: the person enters it themselves, never in chat): Random string of 32+ characters for signing login cookies (openssl rand -base64 32).
- Setting `HOMEPAGE_EXTERNAL_URL`: The full address people use to open Homepage, needed when login is enabled.
- Setting `HOMEPAGE_AUTH_PASSWORD` (**secret**: the person enters it themselves, never in chat): Password for the simple login. Never paste it into an AI chat.
- Setting `HOMEPAGE_MCP_ENABLED`: Turns on the optional AI assistant (MCP) endpoint at /api/mcp. Off by default.
- Setting `HOMEPAGE_MCP_TOKEN` (**secret**: the person enters it themselves, never in chat): Token (32+ characters) for AI assistants using the MCP endpoint. It can read every API key in your config.
- Setting `HOMEPAGE_MCP_ALLOW_WRITE`: Lets the MCP endpoint change your config files. Leave off unless you need it.
- Homepage has no login unless you turn one on. Keep it on your home network, or put it behind a reverse proxy with HTTPS and HOMEPAGE_AUTH_ENABLED.
- The config folder holds API keys for your other apps. Never paste it, or HOMEPAGE_* secrets, into an AI chat; share it with keys removed.
- Mounting the Docker socket gives Homepage a lot of power over your server. Use it read-only, or a socket proxy, or leave it out.
- The optional MCP endpoint can read every key in your config and, with writes on, change custom.js. Only enable it with a long token and on a trusted network.

---

# Customising Homepage

Homepage is configured, not programmed. Almost every change is an edit to a YAML file in your config folder,
and Homepage picks it up when you reload the page. Only write code for a widget that doesn't exist yet.

## Level 1: Settings (no code)
All files live in your config folder (`/app/config` in Docker). Homepage creates examples from `src/skeleton/` on first start.

- **`services.yaml`:** groups of tiles, each with a name, icon, link and description.
- **`bookmarks.yaml`:** simple lists of links with short abbreviations.
- **`widgets.yaml`:** the top bar: greeting, date and time, weather (Open-Meteo needs no key), search, server resources.
- **`settings.yaml`:** title, background image and blur, theme and colour, layout (columns, tabs, collapsible groups), card style, language, link targets. See `docs/configs/settings.md`.
- **`custom.css` / `custom.js`:** bigger text for a wall tablet, hidden elements and other small tweaks (`docs/configs/custom-css-js.md`).
- **Secrets:** write `{{HOMEPAGE_VAR_MEALIE_KEY}}` in YAML and set the value as an environment variable, so keys stay out of the files.

## Level 2: Extend (no fork)
- **Service widgets:** add a `widget:` block under a service for live numbers from Home Assistant, Mealie, Immich, Paperless, Photoprism and 150+ others (`docs/widgets/services/`).
- **Calendar widget:** show iCal feeds, such as a family Google calendar or bin collection dates (`docs/widgets/services/calendar.md`).
- **Custom API widget:** show fields from any JSON API (`docs/widgets/services/customapi.md`), or embed a page with the iframe widget.
- **Docker labels:** containers labelled `homepage.group`, `homepage.name` and so on appear automatically (`docs/configs/docker.md`).
- **MCP endpoint:** let an AI assistant read your setup and, if you allow writes, add services for you (`docs/configs/mcp.md`). Off by default.

## Level 3: Code

| Change | Where |
|---|---|
| New service widget | `src/widgets/<name>/widget.js` (API mapping) and `component.jsx` (display); register in `src/widgets/widgets.js` and `src/widgets/components.js` |
| Widget docs | `docs/widgets/services/<name>.md`; authoring guide in `docs/widgets/authoring/` |
| Wording | `public/locales/en/common.json` (other languages come from Crowdin) |
| New info widget | `src/components/widgets/` |
| Page layout | `src/pages/index.jsx`, `src/components/services/`, `src/components/bookmarks/` |
| Loading config | `src/utils/config/` |

## Running locally
- **Just use it:** the Docker command in `bespoke.yaml`, then open http://localhost:3000.
- **Develop:**
  1. Install Node.js 22 and pnpm.
  2. Run `pnpm install`.
  3. Copy `src/skeleton` to `config/`.
  4. Run `pnpm dev` and open http://localhost:3000.
- **Check:** `pnpm lint` and `pnpm test`.

## Pitfalls
- YAML is fussy about spaces. A broken file shows an error on the page; the logs say which line.
- "Host validation failed": add the exact address you use to `HOMEPAGE_ALLOWED_HOSTS`.
- Widgets need the app's address as Homepage's container sees it, which may differ from the address in your browser.
- Homepage generally does not accept AI-generated pull requests. Keep your own widgets in your copy unless you understand them fully.

---
Machine-readable: [bespoke.yaml](https://handoff.bespokeai.software/p/homepage/44bf8c1/r2/bespoke.yaml) · Hosting options: [hosting.md](https://handoff.bespokeai.software/p/homepage/44bf8c1/r2/hosting.md) · Agent skill: [SKILL.md](https://handoff.bespokeai.software/p/homepage/44bf8c1/r2/SKILL.md)
