- TypeScript 57.7%
- Go 37.3%
- CSS 4.8%
|
|
||
|---|---|---|
| .forgejo/workflows | ||
| api-client | ||
| apibootstrap | ||
| authentication | ||
| dbpool | ||
| entity | ||
| forms | ||
| httpx | ||
| ide-deps | ||
| identityadmin | ||
| pagination | ||
| session | ||
| shell | ||
| types | ||
| ui | ||
| userprofile | ||
| .gitignore | ||
| .golangci.yml | ||
| go.work | ||
| Makefile | ||
| README.md | ||
| tsconfig.base.json | ||
Local development
Use the monorepo go.work (HomeLab repo root):
cd ArcaneDemesne/HomeLab
go work sync
cd backend && make run
go.mod keeps replace for local packages until Forgejo serves correct go-import meta tags. Public deps use the module proxy; no vendor/.
Extraction bar
Shared Package only when ≥2 apps use nearly identical code. Domain stays in apps. Prefer thin app wrappers over forking Packages.
Go modules
| Module | Purpose |
|---|---|
authentication/ |
OIDC BFF, session middleware, chi mount helpers, RequireActor for audit context |
entity/ |
Embeddable AuditableEntity (UUID id, UTC audit fields, soft delete); NotDeletedFilter, DefaultListOrder; WithActor / NowUTC |
pagination/ |
Page, Result[T], in-memory slice helper (tests/dev only); chi middleware in pagination/chi/ |
httpx/ |
JSON responses, StatusError, MapError, MapDomainErrors, ParseUUIDParam, DecodeJSON |
dbpool/ |
pgx pool Open; generic helpers ListPage, GetOne, InsertReturning, ExecOne, WrapNotFound — entity SQL stays in app repos |
userprofile/ |
Shared profile API types, PATCH validation, session identity merge; store layer when extracted; per-app user_profiles table |
identityadmin/ |
IdP directory Admin API interface; identityadmin/authentik/ Authentik adapter |
mail/ |
Transactional SMTP (SMTP_* env), NoopMailer when host unset |
apibootstrap/ |
Shared health, migrate CLI helpers, standard chi middleware (when present) |
Frontend packages
Source-only where noted; install peer deps in the consuming app. Docker builds copy Packages from monorepo root.
| Package | Purpose |
|---|---|
@arcanedemesne/ui |
Components, tokens, ApiErrorStack, avatars, test/setup-dom — source-only |
@arcanedemesne/forms |
Zod field builders |
@arcanedemesne/api-client |
Shared BFF HTTP (tls, client, cookies, errors, auth/profile helpers) |
@arcanedemesne/session |
Session store, auth handlers, expiry monitor/modal/seed |
@arcanedemesne/shell |
AppHeader / HeaderNavLink chrome slots |
Fourth app checklist (e.g. SeedSlinger)
- Depend on ui, forms, api-client, session, shell (
file:or workspace). - Thin
BaseLayout+ header slots; internal apps:base.css+theme-surfaces.css(shared themes via tokens). Brand apps (Cup):base.css+themes/<app>.css. - Go (if applicable): authentication + httpx + dbpool + entity;
replacePackages; health via apibootstrap. - Do not copy session/api-client/ui helpers into the app.
New Go API feature scaffold
Per entity under internal/{entity}/:
internal/{entity}/
{entity}.go # embed entity.AuditableEntity + domain fields
repository.go # CRUD interface using pagination.Page / Result[T]
service.go # use cases; validation; page.Normalize(...)
handler.go # chi routes + pagination/chi middleware + httpx
postgres.go # dbpool helpers + entity SQL + entity.NowUTC()
memory.go # in-memory repo (tests/dev)
Embed entity.AuditableEntity for UUID ids and UTC audit columns. Use entity.WithActor(ctx, userUUID) when auth is available; nil actor is safe for public routes.
Reference: HomeLab internal/article/.
Scale thresholds (sqlc, postgres Base embed): HomeLab/backend/REFACTOR.md.
Container builds
Compose builds from ArcaneDemesne/ context. The Dockerfile copies all Packages/* modules used by the app and runs go mod download for public modules.
When Forgejo module resolution works, remove replace from app go.mod, tag releases, and bump require versions.
Releases
Tag format: {module}/v0.x.y on Forgejo packages.
Examples: authentication/v0.1.2, entity/v0.1.1, pagination/v0.1.0, httpx/v0.1.1, dbpool/v0.2.1.