---
# https://gethomepage.dev/latest/configs/settings
title: ... all my base ...
# ⚠ `theme:` MUST STAY PINNED. REMOVING IT BREAKS THE WHOLE DASHBOARD.
#
# Unpinning this is the documented way to make Homepage render its own
# light/dark toggle, and it was tried on 2026-08-24 for exactly that reason.
# It does not work here: with the key absent, the page's data loader throws and
# its catch branch serves `initialSettings: {}` — no tab bar, no layout, no
# i18n, just a flat list of every group at once. Measured, not inferred: six
# force-recreates over seven minutes all came up empty with the key removed,
# and putting it back rendered correctly on the next recreate in 12 seconds.
# `/api/services` stays 200 and correct throughout, which is what makes this so
# easy to misdiagnose as a caching or warm-up problem.
#
# Light/dark still works — it just is not Homepage's switch. The stylesheet is
# dual-theme (Australis Skyfall ships both), driven by `data-theme` on <html>:
# conf/custom.js adds a toggle that writes it and remembers the choice, and
# theme/build.py also emits an OS-preference copy so an unset choice follows
# `prefers-color-scheme`. Dark stays Skyfall's first-class default.
#
# `color:` is pinned too, for a different reason: unpinning it adds a
# colour-ramp picker, and the ramp is not ours to choose — conf/custom.css
# carries the real palette. slate is the nearest cool neutral underneath it.
theme: dark
color: slate

# NO `background:` BLOCK — DELIBERATE, DO NOT RE-ADD WITHOUT ASKING.
#
# This carried a generated full-bleed aurora image (Arbo job 13f0891f4e42,
# seed 26, flux2-klein-9b) at opacity 30. It went in on an explicit request
# for an Arbo-generated background and came out on 2026-08-19 when the
# operator called the result ugly.
#
# The image was also against canon on its own terms: Skyfall says "flat
# semantic surfaces; no photography, no textures", and permits its one
# decorative motif — a subtle aurora gradient — on hero and empty-state areas
# only, "never behind body text blocks". A whole dashboard is a body text
# block. The predecessor knew and dialled the opacity down instead of dropping
# it, which is how you end up with a quiet version of the wrong thing. The
# asset is still in `images/` if this is ever revisited.
headerStyle: boxedWidgets

providers:
  openweathermap: openweathermapapikey
  weatherapi: weatherapiapikey

quicklaunch:
  searchDescriptions: true
  hideInternetSearch: true
  showSearchSuggestions: true
  hideVisitURL: true

showStats: false
statusStyle: ""

# Cards size to their own content. This was `true` to stop widget-bearing
# cards (Uptime Kuma's stat strip, Paperless's counts) standing taller than
# plain link cards and leaving the grid ragged — but the cure was worse than
# the disease: every short card in the row inflated into a hollow box to match
# the tall one. A ragged bottom edge reads as content; a stretched empty card
# reads as a rendering fault.
useEqualHeights: false

# ===========================================================================
# THE ORGANISING QUESTION IS "DO I OPEN THIS?" — NOT "WHAT IS IT?"
# (operator, 2026-08-24: "most of the issues are that tools I use and have a
# UI are interspersed with API endpoints which are largely informational
# only. They might even go in their own cards or start collapsed.")
#
# Every group on this board is one of two kinds, and they never mix:
#
#   TOOLS — you click the card and do something in the thing it opens.
#           Expanded, and placed at the TOP of its tab.
#   ENDPOINTS — an API, a broker, a background agent. Its href is a `/docs`
#           page, a `/ping`, or nothing at all. The only thing you want from
#           the card is "is it alive". `initiallyCollapsed: true`, and placed
#           at the BOTTOM of its tab.
#
# A collapsed group is not hidden — the eyebrow and its rule still render, so
# the tab still tells you the thing exists, and one click expands it. That is
# the whole point: presence without cost.
#
# When you add a service, ask "would I open this in a browser to get work
# done?" If no, it belongs in a collapsed endpoint group, no matter how
# central it is to the fleet. `AI - Inference` holds the seats the entire
# fleet runs on and it is collapsed, because you consume them through the
# gateway rather than by clicking them.
#
# Four tabs:
#   Main           - what you actually open day to day
#   AI             - AI tools up top, model/API seats collapsed below
#   Infrastructure - hardware, hypervisors, BMCs (per site) — all consoles
#   Toolchain      - the plumbing, split by kind of plumbing
#
# ---------------------------------------------------------------------------
# GROUP MEMBERSHIP LIVES ON THE CONTAINER, NOT HERE.
#
# This block controls tab, order, columns and collapse. WHICH services are in
# a group is set by `homepage.group=` on each container's compose file, and
# labels only apply at container CREATION — moving a service between groups
# means editing the label and running `docker compose up -d <service>`, not
# `restart`. The 2026-08-24 pass did 28 of those; the playbooks that did it
# are `playbooks/homepage-regroup-<host>.yaml` and they are rerunnable.
#
# ⚠ THE MODEL SEATS ARE DELIBERATELY STILL NAMED `AI - Inference`,
# `AI - Eval & Retrieval`, `AI - Speech (TTS)` AND `AI - Audio Tools`.
# Renaming them to something like "AI API - …" would be clearer, and it would
# cost a recreate on sixteen GPU-backed seats — multi-minute model reloads on
# endpoints peers reach through the gateway. Order and `initiallyCollapsed`
# buy the same separation for free. Do not spend that recreate on a label.
#
# ---------------------------------------------------------------------------
# COLUMNS ARE 4 EVERYWHERE. DO NOT TUNE THEM PER GROUP.
#
# `columns: N` is not a density dial — it sets `lg:grid-cols-N` on that one
# group, so it fixes the CARD WIDTH for that group alone. Varying it per group
# means the card width changes every time you cross a group boundary, and a
# page whose grid keeps resizing as you scroll reads as broken layout even when
# every individual group is fine.
#
# The predecessor rule here was "columns = the member count", written to avoid
# the dead cells a 1-member group leaves in a 4-wide row. It trades one flaw
# for a worse one: at columns:1 a single service becomes a 1500px-wide bar
# holding six words, and at columns:2 a three-member group orphans its third
# card onto a half-empty row. Measured on the live board 2026-08-24 — the
# Notes, News, Media, AI - Image & Media and AI - Audio Tools groups were all
# rendering cards two to four times wider than the groups above and below them.
#
# A short last row is what a grid looks like. A card that is wider than its
# neighbours is what a mistake looks like. Uniform wins.
#
# Homepage's own responsive ramp (`grid-cols-1 md:grid-cols-2 lg:grid-cols-N`)
# still collapses this to 2-up and 1-up on narrow viewports, so 4 is a desktop
# maximum, not a hard floor.
#
# ---------------------------------------------------------------------------
# GROUPS ARE ALSO KEPT UNIFORM IN CARD HEIGHT, WHICH IS WHY ADGUARD AND
# TRAEFIK GOT THEIR OWN GROUPS.
#
# A service with a widget (AdGuard's query counts, Traefik's router counts,
# Uptime Kuma's uptime) renders a stat strip that makes its card ~50px taller
# than a plain link card. Put one of those in a row of three plain cards and
# you get a void under the plain ones — which is what made the old 13-member
# `Service Networking` group look broken. Split so that a group's members all
# have widgets or all do not, and every row comes out flush. That is the real
# reason `DNS & Filtering` (3 widget cards) and `Reverse Proxies` (2 widget
# cards) are separate from `Compose Consoles` (5 plain cards).
#
# ---------------------------------------------------------------------------
# EVERY GROUP NEEDS A `tab:` — including bookmark groups, and including groups
# that arrive from a `homepage.group=` container label rather than from this
# file. A group with no tab assignment renders on ALL FOUR TABS. That is how
# UltraSeedbox ended up repeated at the bottom of every tab (fixed 2026-08-18)
# and how Scriberr's `AI Systems` label did the same from 2026-08-23 (fixed
# 2026-08-24). It is Homepage behaviour, not a bug, and it will happen again to
# the next container labelled with a group name that does not appear below.
# `GET /api/services` prints the live group list — anything in it that is not a
# key here is currently leaking onto all four tabs.
# ===========================================================================
layout:
  # ---- Main: what you actually open -------------------------------------
  # Replaces the old Notes (1 member) and News (2) bands, which each burned a
  # full 4-wide row on a single card.
  Daily:
    icon: mdi-coffee-outline
    tab: Main
    style: row
    columns: 4
  Monitoring:
    icon: mdi-chart-line
    tab: Main
    style: row
    columns: 4
  # Absorbed the old one-card Games band (Pterodactyl). Lost SearXNG to Daily,
  # the two chat frontends to the AI tab, and Mosquitto + the RustDesk relay to
  # Agents (no UI) — neither of those has a page to open.
  Apps:
    icon: mdi-apps
    tab: Main
    style: row
    columns: 4
  Media:
    icon: mdi-play-box-multiple
    tab: Main
    style: row
    columns: 4
  # Bookmarks. Listed here for the tab pin above all else — without it this
  # group appears on every tab. `style: row` also turns the eight entries
  # from full-width stacked bars into a compact grid.
  UltraSeedbox:
    icon: mdi-download-network
    tab: Main
    style: row
    columns: 4

  # ---- AI: tools, then collapsed endpoints ------------------------------
  # Chat frontends and the control plane — Lobe Chat and the ESH Open WebUI
  # joined from Main on 2026-08-24; they are chat frontends and belong with the
  # other chat frontends.
  AI - Gateways & Chat:
    icon: mdi-router-network
    tab: AI
    style: row
    columns: 4
  # Replaces `AI - Image & Media`. Everything here is a workspace you open and
  # produce something in: ComfyUI's node editor, Arbo, Waterland, the YT
  # Voice Clipper audition console, Scriberr's transcription UI.
  AI - Studios:
    icon: mdi-palette-outline
    tab: AI
    style: row
    columns: 4
  # ---- collapsed from here down: seats you call, not pages you open ------
  # Named `AI - Inference` rather than something clearer on purpose — see the
  # warning above about what renaming these costs.
  AI - Inference:
    icon: mdi-brain
    tab: AI
    style: row
    columns: 4
    initiallyCollapsed: true
  AI - Eval & Retrieval:
    icon: mdi-scale-balance
    tab: AI
    style: row
    columns: 4
    initiallyCollapsed: true
  AI - Speech (TTS):
    icon: mdi-account-voice
    tab: AI
    style: row
    columns: 4
    initiallyCollapsed: true
  # What is left of the old Audio Tools group after Scriberr and the YT Voice
  # Clipper moved to Studios: the two ASR API seats.
  AI - Audio Tools:
    icon: mdi-waveform
    tab: AI
    style: row
    columns: 4
    initiallyCollapsed: true
  # Stopped stacks kept for rollback / superseded seats / retired auditions.
  # They stay 'created' (not running) via `docker compose up --no-start`, so
  # they show here as offline cards and revive with `docker compose start`.
  AI - Dormant:
    icon: mdi-sleep
    tab: AI
    style: row
    columns: 4
    initiallyCollapsed: true

  # ---- Infrastructure: every card is a console --------------------------
  Infra - ANA:
    icon: si-proxmox
    tab: Infrastructure
    style: row
    columns: 4
  Infra - NH3:
    icon: si-proxmox
    tab: Infrastructure
    style: row
    columns: 4
  Infra - IRV:
    icon: mdi-brain
    tab: Infrastructure
    style: row
    columns: 4
  Infra - ESH:
    icon: si-proxmox
    tab: Infrastructure
    style: row
    columns: 4

  # ---- Toolchain: the plumbing, split by kind ---------------------------
  # The old `Service Networking` group was thirteen members mixing three
  # AdGuards, five Dockges, two Traefiks and four headless agents — widget
  # cards next to plain ones next to things with no href at all. Split four
  # ways on 2026-08-24.
  DNS & Filtering:
    icon: mdi-dns
    tab: Toolchain
    style: row
    columns: 4
  Reverse Proxies:
    icon: mdi-transit-connection-variant
    tab: Toolchain
    style: row
    columns: 4
  Compose Consoles:
    icon: mdi-docker
    tab: Toolchain
    style: row
    columns: 4
  Toolchain:
    icon: mdi-toolbox
    tab: Toolchain
    style: row
    columns: 4
  # No href, or an href that is an API. CrowdSec, Mailrise, the restic
  # rest-server, the Gitea Actions runner, the MQTT broker, the RustDesk relay.
  # You never open these; you only ever want to know they are up.
  Agents (no UI):
    icon: mdi-cog-transfer-outline
    tab: Toolchain
    style: row
    columns: 4
    initiallyCollapsed: true
