fix(apps): classify by declared UI — UI apps to My Apps, headless to Websites (#45)

Per the rule that only front-end apps with a UI belong in "My Apps"
(databases/backends/headless go to Websites), make the manifest's
interfaces.main.ui the deciding signal. isWebsitePackage now treats any
package that declares a UI as an app even when it isn't in the curated
APP_CATEGORY_MAP, and falls through headless LAN-reachable packages to
Websites. Additive — service-by-name infra and curated known apps are
unchanged, so no currently-correct app moves.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
archipelago
2026-06-17 06:09:46 -04:00
co-authored by Claude Opus 4.8
parent 56752ebfc0
commit d2d2b9dd68
2 changed files with 32 additions and 1 deletions
+15
View File
@@ -78,10 +78,25 @@ export function isKnownApp(id: string, pkg?: PackageDataEntry): boolean {
return !!(APP_CATEGORY_MAP[id] || (manifestId && APP_CATEGORY_MAP[manifestId]) || isWebOnlyApp(id))
}
// True when the package's manifest declares a front-end UI interface. This is
// the authoritative "is this a user-facing app?" signal (#45): apps with a UI
// belong in "My Apps", while headless services (databases, backends, workers)
// declare no UI and belong in "Websites"/"Services".
export function hasFrontendUi(pkg?: PackageDataEntry): boolean {
return !!pkg?.manifest?.interfaces?.main?.ui
}
export function isWebsitePackage(id: string, pkg?: PackageDataEntry): boolean {
if (isInternalToolingPackage(id, pkg)) return false
// Headless infra (databases/backends/companions) keyed by container name are
// services regardless of any stray UI string.
if (isServicePackage(id, pkg)) return true
// A declared front-end UI is the deciding factor: it's an app, not a website.
if (hasFrontendUi(pkg)) return false
// Curated known apps stay in My Apps even if their manifest predates the UI
// interface field.
if (isKnownApp(id, pkg)) return false
// Fallback: reachable on the LAN but declares no UI → treat as a website.
return !!pkg && !!runtimeLanAddress(pkg)
}