feat(web): unify console + docs on @unom/ui; host OpenAPI via Scalar
apple / swift (push) Successful in 55s
ci / web (push) Successful in 45s
ci / docs-site (push) Successful in 1m18s
ci / rust (push) Successful in 4m14s
deb / build-publish (push) Successful in 2m16s
decky / build-publish (push) Successful in 12s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 23s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
ci / bench (push) Successful in 4m40s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 46s
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Successful in 8m35s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Successful in 8m18s
docker / deploy-docs (push) Successful in 19s
android / android (push) Successful in 3m12s

Move the management console (web/) off shadcn/ui to the shared @unom/ui
design system the marketing site + docs are built on, on the punktfunk
violet brand over dark chrome:

- Add @unom/ui/@unom/style/motion/radix-ui/zod + Geist; web/.npmrc maps the
  @unom scope (packages are public-read, so CI needs no npm auth).
- styles.css: one dark-violet palette (#141019/#1c1530, brand #6c5bf3 ->
  #a79ff8) exposed under BOTH the shadcn token names the routes use and
  @unom/ui's contract, so routes + components both resolve; pulls in
  @unom/ui's material gloss + easings.
- components/ui/* now back onto @unom/ui (AnimatedButton/InputText/Label/
  AnimatedCard); brand-mark/wordmark/logo replace the generic Radio icon in
  the shell + login.
- MaterialProvider (specular gloss) at the root. No UI sounds, like the site.

docs-site: new /api route renders the host management REST API as an
interactive Scalar reference (reads public/openapi.json, a snapshot of
docs/api/openapi.json), branded violet and linked from the top nav, the
docs sidebar, the landing page, and host-cli.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-21 12:00:46 +00:00
parent 75d5a6d7fb
commit f3555d5eb5
26 changed files with 3409 additions and 155 deletions
+1
View File
@@ -16,6 +16,7 @@ export function baseOptions(): BaseLayoutProps {
},
links: [
{ text: 'Docs', url: '/docs' },
{ text: 'API', url: '/api' },
{ text: 'Website', url: 'https://punktfunk.unom.io' },
{ text: 'Source code', url: 'https://git.unom.io/unom/punktfunk' },
],
+86
View File
@@ -0,0 +1,86 @@
import { createFileRoute, Link } from '@tanstack/react-router'
import { ApiReferenceReact } from '@scalar/api-reference-react'
import BrandMark from '@/components/BrandMark'
import Wordmark from '@/components/Wordmark'
export const Route = createFileRoute('/api/')({
component: ApiReference,
head: () => ({
meta: [
{ title: 'punktfunk — Management API reference' },
{
name: 'description',
content:
'Interactive reference for the punktfunk host management REST API (OpenAPI).',
},
],
}),
})
// Brand the Scalar reference to the punktfunk violet + Geist, in both light and
// dark. Scalar ignores unknown custom-property names, so this is forward-safe.
const SCALAR_CSS = `
:root {
--scalar-color-accent: #6c5bf3;
--scalar-font: 'Geist Variable', ui-sans-serif, system-ui, sans-serif;
}
.dark-mode {
--scalar-color-accent: #a79ff8;
--scalar-background-1: #141019;
--scalar-background-2: #1c1530;
--scalar-background-3: #221a36;
--scalar-border-color: #2a2148;
}
`
function ApiReference() {
return (
<div className="flex min-h-screen flex-col">
{/* Slim branded bar so the reference stays inside the punktfunk identity
and links back into the docs. */}
<header className="flex h-14 shrink-0 items-center justify-between border-b border-fd-border px-4 md:px-6">
<Link
to="/docs/$"
params={{ _splat: '' }}
aria-label="punktfunk documentation"
className="flex items-center gap-2 no-underline"
>
<BrandMark className="size-6" />
<Wordmark className="h-4" />
<span className="ml-2 hidden text-sm text-fd-muted-foreground sm:inline">
Management API
</span>
</Link>
<nav className="flex items-center gap-4 text-sm">
<Link
to="/docs/$"
params={{ _splat: '' }}
className="text-fd-muted-foreground transition-colors hover:text-fd-foreground"
>
Docs
</Link>
<a
href="/openapi.json"
className="text-fd-muted-foreground transition-colors hover:text-fd-foreground"
>
openapi.json
</a>
</nav>
</header>
{/* Scalar mounts a Vue app client-side in a useEffect (SSR-safe: the
server renders an empty container, the browser hydrates the reference). */}
<div className="min-h-0 flex-1">
<ApiReferenceReact
configuration={{
url: '/openapi.json',
darkMode: true,
metaData: { title: 'punktfunk Management API' },
hideDownloadButton: false,
customCss: SCALAR_CSS,
}}
/>
</div>
</div>
)
}