Files
2026-05-03 07:26:12 +00:00

17 KiB

Nuxt Workspace Template

Nuxt 4 template pre lokalny vyvoj vo VS Code na hoste. Repozitar obsahuje zakladnu aplikaciu s i18n, Nuxt UI, jednoduchym loggerom, volitelnou auth kostrou, OpenAPI-ready API vrstvou a predpripravenym workspace nastavenim pre lokalny vyvoj.

Dalsia dokumentacia:

  • quick_start.md: rychly postup po vytvoreni projektu z template
  • programing_guide.md: podrobny prehlad toho, co template poskytuje, ako sa to pouziva a ako sa to da rozsirovat

Co je pripravene

  • Nuxt 4.4.2
  • TypeScript 5.9.3
  • pnpm ako package manager
  • @nuxtjs/i18n s jazykmi sk a en
  • light, dark a system tema cez Nuxt color mode
  • klientsky logger dostupny cez composable
  • volitelna auth kostra s modmi disabled, mock a userinfo
  • OpenAPI-ready API vrstva s generator skriptmi a wrappermi
  • Nuxt UI ako predvolena komponentova vrstva
  • .vscode konfiguracia pre vyvoj vo VS Code
  • ESLint, Prettier a Vitest

Pre koho je template

Template je vhodny ako vychodiskovy bod pre:

  • dashboardy a interne aplikacie
  • portalove aplikacie
  • administracne rozhrania
  • mensie a stredne Nuxt projekty, kde chces zacat rychlo, ale nie od nuly

Struktura projektu

Najdolezitejsie casti repozitara:

  • app/pages: routovatelne stranky aplikacie
  • app/layouts: spolocny layout aplikacie
  • app/components: miesto pre vlastne feature alebo komplexne komponenty nad Nuxt UI
  • app/composables: zdielana klientska logika, napr. tema a logger
  • app/plugins: Nuxt pluginy dostupne v runtime
  • tests: Vitest testy pre store-y, pluginy, middleware a i18n konzistenciu
  • app/assets/styles: globalne SCSS styly, tokeny a tema
  • i18n/locales: preklady pre jednotlive jazyky
  • .vscode: odporucane rozsirrenia, settings a debug konfiguracia
  • nuxt.config.ts: hlavna konfiguracia Nuxtu, modulov, globalnych stylov a i18n
  • vitest.config.ts: Vitest aliasy pre ~, @, ~~ a @@, aby sa dali testovat Nuxt subory mimo runtime

Ako pouzit tento template

1. Vytvor projekt z template

Pouzi tento repozitar ako zaklad a uprav si aspon:

  • nazov projektu v package.json
  • titulok, meta a popis v nuxt.config.ts
  • texty v i18n/locales/sk.json a i18n/locales/en.json
  • uvodnu stranku v app/pages/index.vue
  • vizualny styl v app/assets/styles

2. Nastav prostredie

Skopiruj .env.example do .env a dopln vlastne hodnoty podla potreby.

Priklady:

cp .env.example .env
Copy-Item .env.example .env

Spustenie projektu

Lokalny vyvoj na hoste

Pozadovane je:

  • Node.js ^22.12.0 || >=24
  • corepack

Spustenie:

corepack enable
pnpm install
pnpm dev

Potom otvor http://localhost:3000.

Poznamky:

  • pri prvom starte moze Nuxt v dev rezime buildit pomalsie
  • ak je port 3000 obsadeny, Nuxt pouzije iny port, typicky 3001
  • po otvoreni stranky sa moze prvy Vite build spustit az na prvy request

Produkcny Docker image

Template obsahuje pripraveny:

Build image:

docker build -t nuxt-workspace-template:latest .

Spustenie kontajnera:

docker run --rm -p 3000:3000 nuxt-workspace-template:latest

Kontajner spusti hotovy Nitro server z .output/server/index.mjs a aplikacia bude dostupna na http://localhost:3000.

Ak potrebujes odovzdat runtime premenne:

docker run --rm -p 3000:3000 `
  -e NUXT_PUBLIC_API_BASE_URL=https://api.example.com `
  -e NUXT_PUBLIC_AUTH_MODE=userinfo `
  nuxt-workspace-template:latest

Poznamky:

  • image je urceny pre release a deploy, nie pre hot-reload vyvoj
  • build stage pouziva pnpm install --frozen-lockfile a pnpm build
  • runtime stage pouziva hardened distroless Node 24 image a publikuje port 3000
  • runtime image neobsahuje shell ani balast navyse, co pomaha znizit attack surface

Zakladne skripty

  • pnpm dev: spusti vyvojovy server
  • pnpm build: vytvori produkcny build
  • pnpm preview: spusti preview produkcneho buildu
  • pnpm generate:api: spusti pripraveny OpenAPI codegen workflow
  • pnpm generate:example-api: vygeneruje ukazkoveho klienta do openapi-client/example cez @hey-api/openapi-ts
  • pnpm lint: spusti ESLint
  • pnpm lint:fix: opravi cast lint problemov automaticky
  • pnpm typecheck: spusti Nuxt typecheck
  • pnpm test: spusti Vitest v beznom rezime
  • pnpm test:run: spusti Vitest jednorazovo
  • pnpm format: skontroluje formatovanie cez Prettier
  • pnpm format:fix: naformatuje subory cez Prettier

Automaticke Overenie

Template ma pripraveny automaticky test coverage pre najdolezitejsie stavebne casti:

  • store-y auth a ui
  • auth plugin pre mody disabled, mock a userinfo
  • auth middleware pre public, requiresAuth a roles
  • API wrapper a API plugin
  • logger plugin a useLogger()
  • konzistenciu i18n klucov medzi sk a en

Odporucany minimalny verify postup pred vacsou zmenou:

pnpm lint
pnpm typecheck
pnpm test:run
pnpm build

Ak chces spustit len novejsie infrastrukturalne testy template-u:

pnpm vitest run tests/auth.plugin.spec.ts tests/auth.middleware.spec.ts tests/i18n.locales.spec.ts tests/api.plugin.spec.ts tests/logger.plugin.spec.ts tests/use-logger.spec.ts

Ako v tomto template vyvijat

Kde upravovat stranky

Kazdy subor v app/pages reprezentuje route.

Priklad:

  • app/pages/index.vue: domovska stranka /

Ak chces pridat novu stranku, vytvor novy .vue subor v app/pages.

Kde upravovat spolocny layout

Hlavny layout aplikacie je v:

  • app/layouts/default.vue

Tu sa nachadza spolocna hlavicka, prepinac jazyka a prepinac temy. Vsetky stranky renderovane cez NuxtPage sa zobrazia v tomto layoute.

Layout je postaveny na Nuxt UI komponentoch, najma UBadge a USelect. Korektne obalenie aplikacie cez UApp je v app/app.vue.

Kde upravovat preklady

Preklady su v:

  • i18n/locales/sk.json
  • i18n/locales/en.json

Projekt pouziva @nuxtjs/i18n s jazykmi:

  • sk ako default
  • en ako druhy jazyk

Ak pridas novy text do komponentu, dopln ho do oboch JSON suborov.

Kde upravovat temu a vizual

Globalne styly su nacitane cez nuxt.config.ts z:

  • app/assets/styles/ui.css
  • app/assets/styles/main.scss

Subory stylov:

  • app/assets/styles/ui.css: nacitanie Tailwind CSS a Nuxt UI vrstvy
  • app/assets/styles/_tokens.scss: lahke app-level tokeny, napr. font, radius a layout rozmery
  • app/assets/styles/_theme.scss: volitelne theme override-y nad Nuxt UI tokenmi
  • app/assets/styles/_base.scss: globalne layout a app-specific styly

Theme runtime logika je v:

  • Nuxt UI a useColorMode()

Template rozlisuje:

  • preferenciu temy: light, dark, system
  • vyslednu aktivnu temu: light alebo dark

Odporucany pristup je nemenit cely design system rucne, ale nechat Nuxt UI ako zdroj pravdy a upravovat len:

  • nuxt.config.ts cez appConfig.ui.colors ako prvy krok pre semanticke farby ako primary a neutral
  • _theme.scss pre male vizualne doladenia nad Nuxt UI tokenmi

Prakticky to znamena:

  • v ui.css nechaj iba @import "tailwindcss" a @import "@nuxt/ui"
  • v nuxt.config.ts zacni semantickymi farbami a inymi Nuxt nastaveniami
  • v _tokens.scss men spolocne hodnoty ako --ui-radius, font alebo layout sirku
  • v _theme.scss men light/dark rozdiely cez Nuxt UI CSS premenne
  • v _base.scss rob app-level layout a globalne utility pre vlastne bloky ako .shell, .page-grid a podobne

Ako funguje prepnutie temy

Runtime prepnutie temy je postavene na useColorMode() a prepinaci v app/layouts/default.vue.

Aktualna preferencia moze byt:

  • light
  • dark
  • system

Pouzitie v komponente:

const colorMode = useColorMode()

colorMode.preference = 'dark'

Ak chces spravit vlastne tlacidlo na prepnutie temy:

<script setup lang="ts">
const colorMode = useColorMode()

function toggleTheme() {
  colorMode.preference = colorMode.value === 'dark' ? 'light' : 'dark'
}
</script>

<template>
  <UButton @click="toggleTheme">
    Prepnut temu
  </UButton>
</template>

Ako menit vizual bez vlastneho design systemu

Najcastejsie scenare:

  • chces inu primarnu farbu buttonov a aktivnych prvkov: najprv skus appConfig.ui.colors v nuxt.config.ts
  • chces jemnejsie texty, tmavsie pozadie alebo iny border v dark mode: zmen Nuxt UI CSS premenne v _theme.scss
  • chces iny radius alebo sirsu app shell: zmen hodnoty v _tokens.scss
  • chces iny layout alebo spacing vlastnych blokov: uprav _base.scss

Priklad zmeny radiusu a layoutu:

:root {
  --ui-radius: 1rem;
  --page-max-width: 1320px;
}

Priklad jemneho doladenia backgroundu a borderov:

:root,
.light {
  --ui-bg: #f8fafc;
  --ui-bg-muted: #f1f5f9;
  --ui-border: #dbe4ee;
}

.dark {
  --ui-bg: #0b1220;
  --ui-bg-muted: #111827;
  --ui-border: #1f2937;
}

Priklad zmeny intenzity primarnej farby medzi light a dark modom:

:root {
  --ui-primary: var(--ui-color-primary-600);
}

.dark {
  --ui-primary: var(--ui-color-primary-400);
}

To je vhodne hlavne vtedy, ked chces nechat Nuxt UI komponenty a ich logiku bez zmeny, ale potrebujes jemne upravit kontrast alebo ton farby.

Priklad konfiguracie v tomto template

Aktualny template drzi semanticke farby v nuxt.config.ts:

export default defineNuxtConfig({
  appConfig: {
    ui: {
      colors: {
        primary: 'blue',
        neutral: 'slate'
      }
    }
  }
})

Tento zapis hovori Nuxt UI, aku paletu ma ma preferovat pre:

  • color="primary"
  • color="neutral"
  • utility ako text-primary, bg-primary, text-muted, bg-default a podobne

Ak by si pri konkretnej verzii Nuxt UI potreboval jemnejsiu kontrolu nad realnym vysledkom, najspolahlivejsia cesta je doplnit CSS tokeny v _theme.scss, napr. --ui-primary, --ui-bg alebo --ui-border.

Kde upravovat komponenty

Template pouziva standardne Nuxt UI komponenty ako predvolenu UI vrstvu.

Najcastejsie pouzite v template:

  • UButton
  • UCard
  • UInput
  • USelect
  • UFormField
  • UAlert
  • UBadge

Pouzitie v komponente:

<UCard variant="soft">
  <template #header>
    <h2>Nadpis</h2>
  </template>

  <UFormField label="Meno">
    <UInput v-model="name" />
  </UFormField>

  <UButton>Ulozit</UButton>
</UCard>

Ak budes chciet rozsirit UI o vlastne komplexne komponenty, odporucany postup je skladat ich nad Nuxt UI, nie vytvarat paralelnu mini kniznicu zakladnych button/input/card komponentov.

Kde upravovat logger

Logger je pripraveny ako Nuxt plugin a composable:

  • app/plugins/logger.ts
  • app/composables/useLogger.ts

Pouzitie v komponente:

const logger = useLogger()

logger.info('Akcia vykonana', { section: 'home' })

Logy z klienta idu do konzoly prehliadaca.

Logger ma aj automaticke testy, ktore overuju prefix, timestamp a spravanie s payloadom aj bez neho.

Kde upravovat API a OpenAPI kontrakt

Zaklad API vrstvy je v:

  • app/plugins/api.client.ts
  • app/composables/useApi.ts
  • app/types/api.ts
  • api/wrappers

OpenAPI priprava je v:

  • openapi-spec
  • openapi-client
  • openapi-ts.config.ts

Template funguje aj bez generovaneho klienta. Predvoleny wrapper api/wrappers/example.ts pouziva bezny fetch styl cez $fetch, ale ma rovnaky tvar ako vrstva, ktoru vies neskor napojit na vygenerovany OpenAPI client.

API plugin a ukazkovy wrapper maju samostatne Vitest testy, takze zmeny v runtimeConfig alebo wrapper rozhrani vies zachytit automaticky.

Pouzitie v stranke alebo komponente:

const api = useApi()

const health = await api.example.getHealth()
const welcome = await api.example.getWelcome()

Odporucany vzor:

  • komponent alebo page vola useApi()
  • useApi() vracia klientov injectnutych z app/plugins/api.client.ts
  • konkretne HTTP volania alebo OpenAPI klient je schovany vo api/wrappers

Tymto sposobom ostane UI oddelene od detailov backend komunikacie.

Zakladne env pre API:

  • NUXT_PUBLIC_API_BASE_URL
  • NUXT_PUBLIC_API_TIMEOUT_MS

Zakladny generator prikaz:

pnpm generate:api

Odporucany postup:

  1. nahrad openapi-spec/example-api.yaml vlastnou specifikaciou
  2. uprav openapi-ts.config.ts
  3. spusti pnpm generate:api
  4. napoj vygenerovaneho klienta cez api/wrappers

Ak uz mas backend kontrakt cez OpenAPI, odporucany sposob integracie je:

  1. pridaj alebo aktualizuj .yaml specifikaciu v openapi-spec
  2. vygeneruj klienta do openapi-client
  3. v api/wrappers vytvor tenku vrstvu, ktora premapuje volania na domenove funkcie
  4. z komponentov volaj iba useApi(), nie vygenerovany klient priamo

Poznamka ku gitu:

  • obsah openapi-client je v template ignorovany, pretoze ide o generovane subory
  • v gite ostava len openapi-client/README.md, aby bolo jasne, na co adresar sluzi
  • ak bude tvoj tim chciet verzovat aj generovanych klientov, uprav .gitignore

Kde upravovat autorizaciu

Auth vrstva je zamerne volitelna. Ak ju projekt nepotrebuje, ostava vypnuta.

Zakladne casti su v:

  • app/plugins/auth.ts
  • app/composables/useAuth.ts
  • app/middleware/auth.global.ts
  • app/stores/auth.ts
  • app/types/auth.ts

Rezim auth sa nastavuje cez .env:

  • NUXT_PUBLIC_AUTH_MODE=disabled: auth je vypnuta a middleware nic nevynucuje
  • NUXT_PUBLIC_AUTH_MODE=mock: lokalny vyvoj s mock userom
  • NUXT_PUBLIC_AUTH_MODE=userinfo: nacitanie usera z endpointu NUXT_PUBLIC_AUTH_USERINFO_URL

Pouzitie v komponente:

const auth = useAuth()

await auth.ensureInitialized()

if (auth.isAuthenticated.value) {
  console.log(auth.user.value?.email)
}

Pouzitie cez store:

const authStore = useAuthStore()

if (authStore.hasRole('ADMIN')) {
  // zobraz admin cast rozhrania
}

Ak chces ochranit konkretnu stranku, pouzi route meta:

definePageMeta({
  requiresAuth: true
})

Alebo s rolami:

definePageMeta({
  requiresAuth: true,
  roles: ['ADMIN']
})

Bezny scenar:

  • pocas lokalneho vyvoja nastav NUXT_PUBLIC_AUTH_MODE=mock
  • pre projekt bez prihlasenia nechaj NUXT_PUBLIC_AUTH_MODE=disabled
  • pre realne SSO alebo proxy endpoint pouzi NUXT_PUBLIC_AUTH_MODE=userinfo

Auth middleware sa spusta globalne, ale zasahuje len na routach s requiresAuth alebo roles.

Kde upravovat globalny stav cez Pinia

Pinia sa hodi na stav, ktory je zdielany vo viacerych castiach aplikacie.

Pripravene store-y:

  • app/stores/auth.ts: user, role, session stav
  • app/stores/ui.ts: loading a notifikacie

Pouzitie ui store:

const uiStore = useUiStore()

uiStore.startLoading()

try {
  uiStore.pushNotification({
    title: 'Ulozene',
    message: 'Zmena bola uspesne ulozena.',
    tone: 'success'
  })
} finally {
  uiStore.stopLoading()
}

Pouzitie auth store:

const authStore = useAuthStore()

const userName = authStore.displayName
const isLoggedIn = authStore.isAuthenticated

Odporucanie:

  • lokalny stav formulára nechaj v komponente
  • zdielany stav typu user, loading, notifikacie alebo filtre dava zmysel drzat v store

Ako pouzit Nuxt UI v tomto template

Nuxt UI je zapojene ako Nuxt modul a je predvolenou UI vrstvou template.

Zakladne pouzitie:

  1. do page alebo komponentu pouzi U* komponenty priamo
  2. nebuduj dalsiu vrstvu BaseButton, BaseInput, BaseCard, ak na to nie je silny dovod
  3. vlastne komplikovane komponenty, napriklad diagramy alebo specialne editory, stavaj ako bezne Vue komponenty a Nuxt UI pouzi na ich okolie, toolbar, formulare a akcie

Priklad:

<template>
  <UCard>
    <template #header>
      <div class="stack">
        <p class="section-kicker">Demo</p>
        <h2>Nuxt UI komponent</h2>
      </div>
    </template>

    <UAlert
      color="info"
      variant="soft"
      title="Stav"
      description="Komponent je pripraveny."
    />
  </UCard>
</template>

Kde upravovat hlavnu konfiguraciu

Hlavne nastavenia su v:

  • nuxt.config.ts

Tu upravis napr.:

  • globalne CSS
  • Nuxt moduly
  • title a meta tagy
  • i18n konfiguraciu
  • devtools spravanie

Odporucany workflow

Pri beznej praci sa osvedci tento postup:

  1. Spusti pnpm dev.
  2. Otvor aplikaciu v prehliadaci.
  3. Men stranky v app/pages, layout v app/layouts a texty v i18n/locales.
  4. Priebežne kontroluj typy a lint:
pnpm typecheck
pnpm lint
  1. Pred odovzdanim alebo commitom over:
pnpm format
pnpm test:run
pnpm build

VS Code

Repozitar obsahuje:

  • .vscode/settings.json: workspace nastavenia
  • .vscode/extensions.json: odporucane rozsirrenia
  • .vscode/launch.json: jednoduche spustenie pnpm dev z VS Code

Predinstalovane a odporucane rozsirrenia su zamerane najma na:

  • Vue a TypeScript
  • ESLint a Prettier
  • i18n preklady
  • Vitest

Poznamky k dev rezimu

  • pnpm install spusta postinstall, ktory vola nuxt prepare
  • OpenAPI codegen ide cez @hey-api/openapi-ts, takze netreba Javu
  • prvy start po cistom install moze byt pomalsi
  • prvy Vite build sa moze spustit az pri prvom otvoreni stranky
  • ak sa objavi problem s viacerymi servermi, ukonci beziace Node alebo Nuxt procesy vo svojom terminali alebo cez Spravcu uloh a spusti iba jeden pnpm dev

Co typicky zmenit ako prve

Po vytvoreni noveho projektu z template sa obvykle meni:

  • branding a texty v prekladoch
  • titulky a meta udaje
  • farby, spacing a tokeny v stylech
  • obsah app/pages/index.vue
  • pouzitie a konfiguracia Nuxt UI komponentov podla potrieb projektu
  • vlastne feature komponenty v app/components
  • doplnenie dalsich stranok, API endpointov a testov