@rackmarten/ui-kit
| Install | |
|---|---|
npm install @rackmarten/ui-kit |
|
| Latest Version: | 0.10.0 |
| Vue: | 3 |
| License: | MIT |
| Last Updated: | Oct 17, 2026 |
| Links: | GitHub · npm |
@rackmarten/ui-kit
Vue 3 + Vuetify 3 building blocks for the frontend of a small self-hosted
web app: an app shell, a shared theme, routing, notifications, global search
and identity helpers. Its backend counterpart is
@rackmarten/server-kit.
Heads-up: this kit exists to serve the maintainer's own self-hosted apps, and new features land when one of those apps needs them. It is published in case it is useful to you too, but the API may change between 0.x minor versions. Pin a version range and read
CHANGELOG.mdbefore bumping.
npm i @rackmarten/ui-kit
No .npmrc or token is needed; it is public on the npm registry.
Usage
Vue 3 + Vuetify 3 + TypeScript, built as an ES module. vue, vuetify and
vue-router are peer dependencies, so your app's own instances are used.
import { createApp } from "vue";
import { createHomelabRouter, createHomelabVuetify, homelabAccents } from "@rackmarten/ui-kit";
import "@mdi/font/css/materialdesignicons.css";
import "vuetify/styles";
const router = createHomelabRouter([
{ path: "/", component: DashboardPage },
{ path: "/items/:id", component: ItemPage },
]);
createApp(App)
.use(router)
.use(createHomelabVuetify({ accent: homelabAccents.blue }))
.mount("#app");
<AppShell title="My app" :nav-items="navItems" me-url="/api/me">
<template #app-bar-actions>
<GlobalSearch :provider="search" placeholder="Search..." />
<NotificationBell :source="notifications" see-all-to="/notifications" />
</template>
<router-view />
</AppShell>
What it exports:
AppShell: responsive layout. A permanent nav drawer on desktop; on mobile a bottom navigation bar, or a slide-out drawer when there are more than 5navItems. The account button shows the user's avatar (fromme-url, or theuserprop) and opens a menu with name, device, an "Admin" chip, a light/dark toggle, an optional "Profile" link (profile-to) and anaccount-menu-itemsslot. Avatars are<avatar-base-url><user id>(no default, so initials until you set one) oruser.avatarUrl./opens the global search unless focus is in a form field.DashboardView,SettingsView: placeholder pages you configure or replace through slots.- Theme (
createHomelabVuetify,homelabAccents,homelabGlow,glowBackground,preferredHomelabTheme,persistHomelabTheme): light/dark themes with the choice persisted inlocalStorage(falling back to the OS preference),@mdi/fonticons, and anaccentthe rest is derived from: app bar gradient, controls, and a background glow AppShell paints behind every page.homelabAccentsis a palette of tuned accents (green,coral,blue,amber,teal,violet); any hex works.overridesis deep-merged into the Vuetify options.tools/theme-tuner.htmlis a standalone page (no build step) for tuning these values. - Routing (
createHomelabRouter,redirectLegacyHashUrl): web history, matching server-kit'sregisterSpa. Old/#/pathlinks are rewritten to/pathat boot. useBackClose(openRef),installBackClose(router): the back button closes the topmost dialog/drawer/menu instead of leaving the page (or, on an installed PWA's first page, closing the app).NotificationBell,NotificationsView(+useNotificationBell,useNotificationHistory,createHttpNotificationSource): an app-bar bell and a full history page over a smallNotificationSourceadapter (list,unreadCount,markRead,markAllRead, optionalsubscribe).createHttpNotificationSource()is the whole adapter for an app using server-kit's notification routes.GlobalSearch(+useGlobalSearch): a debounced search dialog overprovider: (term) => Promise<SearchGroup[]>, ignoring stale answers.- Identity (
useHomelabUser,ViewingAsBanner,avatarSrc,initials): load the caller from server-kit's/api/meand show a "Viewing as" banner while an admin views as someone else.
Don't import ui-kit's .vue sources out of node_modules; use the built
package entry point.
Development
npm ci
npm run build
npm run typecheck
npm test
npm run lint # lint:fix and format apply the automatic fixes
Tests live in test/, mirroring src/ (src/auth/jwt.ts ->
test/auth/jwt.test.ts); shared test-only helpers go in test/helpers/.
They run on Vitest with jsdom. The build writes .d.ts files with vue-tsc
and the JS bundle with Vite into the same dist/, which is why
vite.config.ts sets build.emptyOutDir: false.
See CONTRIBUTING.md for how to contribute and CHANGELOG.md for what
changed in each release. Licensed under the MIT License.
Version History
| Version | Released | Vue | License |
|---|---|---|---|
| 0.10.0 | ^3.5.0 | MIT |