Preferences, layouts, and theming

initPreferences, layout modes, Pohon unstyled theme, and UnoCSS setup for Taman UI.

Preferences

Call initPreferences before mounting Vue (apps/web/src/main.ts):

const env = import.meta.env.PROD ? 'prod' : 'dev';
const namespace = `${import.meta.env.VITE_APP_NAMESPACE}-${appVersion}-${env}`;

await initPreferences({
  namespace,
  overrides: overridesPreferences,
});

namespace isolates StorageManager keys so two apps (or dev vs prod) do not share prefs.

apps/web/src/preferences.ts:

export const overridesPreferences = defineOverridesPreferences({
  app: {
    defaultHomePath: '/todos/manage',
    name: import.meta.env.VITE_APP_TITLE,
  },
});

taman-core defaults (when you do not override) include:

KeyDefault
app.accessMode'frontend'
app.defaultHomePath'/dashboard' — no such route in this template
app.timezone'Asia/Makassar'
app.layout'sidebar-nav'
app.locale'en-US'
app.name'Taman Admin'

Clear the cached preferences key after changing overrides or they may not apply (cache fills fields you did not set).

API (@vinicunca/taman-core/preferences)

import {
  clearCache,
  defineOverridesPreferences,
  getPreferences,
  initPreferences,
  preferences,
  preferencesManager,
  resetPreferences,
  updatePreferences,
  usePreferences,
} from '@vinicunca/taman-core/preferences';
  • updatePreferences(partial) — merge + persist (debounced 150 ms)
  • resetPreferences() — back to the init snapshot
  • usePreferences() — computed isDark, layout, locale, isMobile, shortcut flags, button placement, …

usePreferences().app is a snapshot of appPreferences.value at setup time, not a computed. Prefer getPreferences() or the dedicated computeds for reactive reads.

Layouts

TamanCoreLayout (@vinicunca/taman-ui/layout) is the admin chrome. The web app wraps it in apps/web/src/layouts/core.vue. Auth pages use layouts/auth.vue.

app.layout values (from preferences types): sidebar-nav, sidebar-mixed-nav, header-nav, header-mixed-nav, header-sidebar-nav, mixed-nav, full-content. On mobile, layout is forced to sidebar-nav.

Auth page layouts: panel-left | panel-right (default) | panel-center.

Theming

apps/web/vite.config.ts uses Pohon unstyled:

vitePohon({
  colorMode: false,
  theme: { unstyled: true },
  ui: { colors: { primary: 'blue', /* … */ }, ...ui },
  scanPackages: ['@vinicunca/taman-ui', '@taman/app-ui'],
});

@taman/designs supplies tokens and vitePohonTheme. Bootstrap imports virtual:uno.css, @taman/designs/styles, and virtual:pohon-theme.

For a standalone taman-ui consumer (the template already does all four in apps/web):

  1. vitePohon({ scanPackages: ['@vinicunca/taman-ui'] })
  2. optimizeDeps.exclude: ['pohon-ui', '@vinicunca/taman-ui']
  3. resolve.dedupe: ['pohon-ui', 'vue']
  4. UnoCSS content.pipeline.include must contain TAMAN_UI_CONTENT from @vinicunca/taman-ui/unocss (/@vinicunca[\\/]taman-ui[\\/]dist[\\/].*\.mjs$/)

Without TAMAN_UI_CONTENT, compiled components render without their utilities.

Color CSS variables are generated with generatorColorVariables (@vinicunca/taman-core/color) as --taman-color-<name>-<shade>.