5.9 KiB
AGENTS.md
PWA для менеджмента homelab: монорепозиторий Go-сервер + SPA-фронт, общаются через ConnectRPC. Таргет — iPhone «На экран Домой» (standalone PWA).
Стек
- Сервер: Go + echo +
connectrpc.com/connect. Отдаёт RPC на/homelab.v1.HomelabService/*и статику изdist/(SPA-fallback включён). Порт из envPORT(дефолт:8080). - Фронт: Preact + Vite + TypeScript, daisyUI v5 (tailwind v4), lucide-preact. Клиент —
@connectrpc/connect-web, same-origin transport, в dev — прокси на :8080. - Контракт:
proto/homelab/v1/homelab.proto→ кодоген вgen/(Go) иweb/src/gen/(TS). Сгенерённый код коммитится, buf CLI не используется — только protoc. - Конфиг:
config.yaml(секции → items → bash-скрипты). Мониторы гоняются по таймеру на сервере, response-скрипты запускаются по кнопке с аргументами.
Структура
proto/homelab/v1/ контракт (единственный источник правды)
gen/ сгенерённый Go-код (коммитим)
server/main.go весь сервер: конфиг, мониторы, RPC, статика, docs API
web/src/App.tsx layout, топбар + hamburger-drawer, 4 хардкод-таба, поллинг ListContent (3s)
web/src/components/ MonitorCard, ScriptCard, Docs (ридер + textarea-редактор)
web/src/docsStore.ts localStorage доков (hub:doc:*), dirty-флаги, syncDocs: pull по хэшам + flush раз в 5s
web/src/gen/ сгенерированный TS-клиент
web/public/ PWA-обвязка: manifest, sw.js, иконки
scripts/ bash-скрипты, пути из config.yaml
docs/ markdown-доки, НЕ в репо — живут только на сервере рядом с бинарьём
Категории
Хардкод в бандле (App.tsx CATEGORIES): Links (из config links), Monitor (config monitor), Exec (config exec), Docs (папка docs/, API ListDocs/GetDoc/SaveDoc). Оффлайн: контент-стейт держит последний ответ, доки — localStorage; правки в оффлайне помечаются dirty и флашатся на сервер каждые 5s (client authority — последняя запись побеждает, без base-hash check).
Команды (всё через make)
make dev— сервер :8080 + vite :5173 (работать на http://localhost:5173)make dev-srv/make dev-web— по отдельности в два терминалаmake proto— кодоген Go+TS из protomake web— сборка фронта вdist/(tsc --noEmit + vite build;tsc— линтер, падение = ошибка типов)make server— Go-бинарьbin/hub-apimake test— smoke-тест RPC (поднимает сервер на :8080, дергает curl'ом)
Никаких других способов сборки нет: CI делает ровно make web server.
Деплой (CI)
.gitea/workflows/deploy.yml: push в master → checkout → make web server → cp на бокс → systemctl --user restart hub-api.
На боксе юнит должен иметь WorkingDirectory=~/apps/hub — сервер ищет dist/, config.yaml, scripts/ относительно cwd. Локально всё то же самое из корня репо.
Конвенции
- Один корень статики:
dist/. Не вводить fallback-ов (web/distне существует послеmake web— vite собирает вweb/dist, make копирует в./dist). int64в proto →bigintв TS (неnumber!).- Поля protobuf в TS — camelCase (
arg_types→argTypes). - Новый item-тип или поле в yaml = обновить proto + валидацию в
loadConfig+ компонент на фронте. - Иконки: хардкод в компонентах из lucide-preact поимённо (не тянуть весь lucide через
icons— раздувает бандл в 5 раз). - Маркдаун:
marked(~10KB gzip) + dangerouslySetInnerHTML без санитайзера (контент свой). Если редактор перестанет нравиться — переход на MDXEditor ( agreed upgrade path, изолирован в компоненте Docs). - index.html и sw.js отдаются с
Cache-Control: no-cache— иначе iOS не подхватит новый бандл. - Логи сервера: monitors и RunScript пишут в stdout;
ListSections(поллинг-шум) исключён из HTTP-лога echo. - SW:
web/public/sw.js, версия кэшаhomelab-shell-vN— бампить при изменении офлайн-логики, иначе iOS не обновит. - Тесты:
make test(smoke RPC) +tsc --noEmitвнутриmake web. Не плодить фреймворки.
Подводные камни
- iOS PWA требует https (или localhost). Через Caddy-домен бокса — ок.
- SW на iOS у установленной PWA обновляется неохотно: правки SW → удалить иконку, открыть в Safari, добавить заново. Bump версии кэша в sw.js обязателен.
- Connect JSON:
int64сериализуется строкой — в smoke-тестах grep'ать с кавычками. - Джобы CI — host (не docker), user
homelab; не добавлять docker-шаги.