Vue 3 composable adapter for @polargold/pg-frontend-core — the shared, framework-agnostic utility layer.
Vue 3 composables built on top of @polargold/pg-frontend-core: reactive/lifecycle-aware wrappers
(useApi, useLocalStorage, useDateTime, useCurrency, useColorGradient, useBreakpoint) and
router/permission composables (useKeyboardEvent, useRouterGo, useRouterPush, usePermission, useRoutePermission,
useCheckTokenValidity).
Extracted from the near-duplicate composables found across luv-ui-tools, bws-ui-tools, and the
luv-autoq-frontend/ama-deep/data-sheet-portal app repos during the September 2026 frontend tooling
audit. Brand-specific composables (useSeminarType, useHomeLink, useSnackbarMethods/useSnackbarRetrieval)
are not here — they live in each brand's own *-ui-library package instead. See
What belongs here.
nvm use && npm install
# Configure access to the polargold registry (once, globally). Token in Bitwarden under "[NPM Registry] pg-admin"
npm config set -- //npm.white-lan.de/:_authToken=${token}
cd your-project/
echo "@polargold:registry=https://npm.white-lan.de" >> .npmrc
npm install -S @polargold/pg-frontend-vue
Peer dependencies: vue ^3.5. vue-router (^4 or ^5) is only required if you use useRouterGo or
useRoutePermission — declared as an optional peer dependency.
npm run lint
npm run lint:fix
npm run type-check
npm run vitest:run
npm run test
npm run docs:build
npm run docs:serve
npm run vite:build
| Service | URL |
|---|---|
| Package registry | Package registry |
| TypeDoc | Not deployed yet — run npm run docs:serve locally. See the note in bitbucket-pipelines.yml. |
Vue-specific composables only — anything using ref/computed/onMounted/useRouter/etc. Framework-agnostic
logic (classes, plain functions, error types) belongs in @polargold/pg-frontend-core instead, which this
package depends on and wraps. Brand-specific composables belong in that brand's *-ui-library package.
useApiPorted unchanged from luv-ui-tools/bws-ui-tools — reactive isLoading/apiData wrapper around an async
callback, throwing ApiCallError (re-exported from pg-frontend-core) on failure.
import { useApi } from "@polargold/pg-frontend-vue";
const { isLoading, apiData, callApi } = useApi({
callback: () => apiLibrary.myFeature.getItems(),
onError: (error) => console.error(error),
});
useLocalStorageThin wrapper around pg-frontend-core's LocalStorage class.
import { useLocalStorage } from "@polargold/pg-frontend-vue";
const { write, read, remove } = useLocalStorage("accessToken", { mode: import.meta.env.MODE });
useDateTime, useCurrency, useColorGradient, useBreakpointPorted from luv-ui-tools/bws-ui-tools — thin wrappers around pg-frontend-core's DateFormatter/
CurrencyFormatter/ColorGradient, and a window-width-driven set of breakpoint computeds.
import { useDateTime, useCurrency, useColorGradient, useBreakpoint } from "@polargold/pg-frontend-vue";
const { internationalDate } = useDateTime();
const { transformCurrency } = useCurrency(); // or useCurrency("USD", "en-US")
const { generateColorGradient } = useColorGradient();
const { isMdAndUp } = useBreakpoint();
useKeyboardEventReplaces the copies in luv-autoq-frontend, ama-deep, bws-checkout-service-spa. Exposes raw
addEventListener/removeEventListener rather than wiring its own onMounted/onUnmounted — wire it to
whatever lifecycle fits your use case.
import { onMounted, onUnmounted } from "vue";
import { useKeyboardEvent } from "@polargold/pg-frontend-vue";
const { addEventListener, removeEventListener } = useKeyboardEvent(() => close(), ["Escape"]);
onMounted(addEventListener);
onUnmounted(removeEventListener);
useRouterGoReplaces the copies in luv-autoq-frontend, ama-deep, data-sheet-portal. The hardcoded
console.group-logging + redirect-to-error-page behavior from the ama-deep/data-sheet-portal copies
becomes an opt-in onError callback.
import { useRouterGo } from "@polargold/pg-frontend-vue";
import router from "@/router";
import { ROUTE } from "@/router/routeDefinitions";
const { routerGo } = useRouterGo({
onError: async () => router.push({ name: ROUTE.PUBLIC_ERROR_PAGE.NAME }),
});
useRouterPushReplaces the copies in luv-autoq-frontend, ama-deep, data-sheet-portal (ama-deep/data-sheet-portal
byte-identical; luv-autoq-frontend's also calls Sentry.captureException). Used internally by
useRoutePermission for its own permission-redirects — see its onNavigationError option.
import { useRouterPush } from "@polargold/pg-frontend-vue";
import { ROUTE } from "@/router/routeDefinitions";
const { routerPush } = useRouterPush({
onError: async (error) => {
console.error("Navigation failed", error);
await router.push({ name: ROUTE.PUBLIC_PAGE_NOT_FOUND.NAME });
},
});
usePermissionReplaces the copies in luv-autoq-frontend, ama-deep, data-sheet-portal. Takes getUserRoles/isAdmin
callbacks instead of importing an app-specific useAuthUserStore() directly.
import { usePermission } from "@polargold/pg-frontend-vue";
import { useAuthUserStore } from "@/stores/AppStartUp/AuthUserStore";
const authUserStore = useAuthUserStore();
const { hasAnyPermission, hasAllPermissions } = usePermission({
getUserRoles: () => authUserStore.roles,
isAdmin: () => authUserStore.isAdminUser,
});
useRoutePermissionReplaces the copies in ama-deep/data-sheet-portal (byte-identical between the two).
Bug fix carried over: requires
isAuthUserLoaded—luv-autoq-frontend's copy of this composable was missing that guard entirely (found during the audit), so it isn't one of the source copies here.
import { useRoutePermission } from "@polargold/pg-frontend-vue";
import { useAuthUserStore } from "@/stores/AppStartUp/AuthUserStore";
import { ROUTE } from "@/router/routeDefinitions";
import router from "@/router";
const authUserStore = useAuthUserStore();
const { initialize } = useRoutePermission({
getUserRoles: () => authUserStore.roles,
isAdmin: () => authUserStore.isAdminUser,
isAuthUserLoaded: () => authUserStore.authUserIsLoaded,
notAllowedRouteName: ROUTE.PUBLIC_PAGE_NOT_ALLOWED.NAME,
// optional - called if the permission-redirect itself fails (see useRouterPush above)
onNavigationError: async (error) => router.push({ name: ROUTE.PUBLIC_ERROR_PAGE.NAME }),
});
await initialize();
Route-level access is still declared the same way as before, via route.meta.hasAnyPermission /
hasAllPermissions / excludeRoles / customRedirectName (this package augments Vue Router's RouteMeta
type for these).
useCheckTokenValidityReplaces the copies in ama-deep/data-sheet-portal (byte-identical between the two).
import { useCheckTokenValidity } from "@polargold/pg-frontend-vue";
import { useAccessTokenStore } from "@/stores/AppStartUp/AccessTokenStore";
import { useOpenIdAuthenticationStore } from "@/stores/AppStartUp/OpenIdAuthenticationStore";
const accessTokenStore = useAccessTokenStore();
const authStore = useOpenIdAuthenticationStore();
const { initialize, reset } = useCheckTokenValidity({
isTokenValid: () => accessTokenStore.tokenIsValid,
onInvalid: () => authStore.logout(),
});
ApiCallError / LocalStorageErrorRe-exported from @polargold/pg-frontend-core for convenience, so a Vue app consuming only this package
doesn't need a separate pg-frontend-core import just for error handling.
Every symbol is re-exported through src/composables/index.ts and through src/main.ts — nothing is
auto-discovered. Follow this for anything new.
Same as pg-frontend-core — everything pushed as a tag is type-checked, linted, tested, has its TypeDoc
built, and is published to the internal package registry automatically. Versioning is manual:
npm version [major | minor | patch | x.x.x]
polargold GmbH, Lilienstraße 5-9 / Semperhaus C, 20095 Hamburg