# Programming Guide
Tento dokument sluzi ako prakticky sprievodca template-om. Pri kazdej casti popisuje:
- co template poskytuje
- ci sa dana cast musi pouzit
- ako sa pouziva
- kratky priklad
- ako sa da rozsirit
Poznamka:
- vsetko v tomto template je navrhnute tak, aby sa dalo pouzit postupne
- projekt nemusis prijat ako jeden velky balik
- niektore casti su povinne len technicky, nie architektonicky
## Prehlad
Template poskytuje tieto hlavne casti:
- Nuxt 4 aplikaciu
- TypeScript
- Nuxt UI ako predvolenu UI vrstvu
- i18n pre `sk` a `en`
- Pinia store-y
- volitelnu auth kostru
- API vrstvu pripravenu na OpenAPI
- logger composable a plugin
- globalne SCSS styly a tokeny
- VS Code konfiguraciu
- lint, format, typecheck a test skripty
- Vitest test harness pre store-y, pluginy, middleware a locale konzistenciu
## Nuxt 4 Aplikacia
Co poskytuje:
- zakladnu strukturu Nuxt 4 projektu
- `app/` adresar pre pages, layouts, plugins, stores a composables
- `nuxt.config.ts` pre centralnu konfiguraciu
Musi sa pouzit:
- ano
- je to jadro celeho template-u
Ako pouzit:
- vytvaraj routy v `app/pages`
- vytvaraj spolocne layouty v `app/layouts`
- pridavaj runtime logiku cez `app/plugins` a `app/composables`
Priklad:
```vue
About page
```
Moznosti rozsirenia:
- pridat dalsie Nuxt moduly do `nuxt.config.ts`
- doplnit server routes do `server/routes`
- doplnit middleware, plugins a composables podla potrieb projektu
## TypeScript
Co poskytuje:
- typovanie pre komponenty, composables, stores a plugin injections
- centralne rozsirene Nuxt typy v `app/types`
Musi sa pouzit:
- prakticky ano
- template je na TypeScripte postaveny
Ako pouzit:
- zapisuj nove composables a utility v `.ts`
- definuj domenove typy do `app/types`
Priklad:
```ts
export interface Customer {
id: string
name: string
}
```
Moznosti rozsirenia:
- pridat dalsie domenove typy
- rozsirit `RouteMeta` alebo `NuxtApp` injekcie
- doplnit typy pre generovane OpenAPI klienty
Odporucanie:
- pri rozsireni `NuxtApp` injekcii alebo aliasov udrzuj v synchronizacii aj `vitest.config.ts`, aby sa dali nove pluginy testovat mimo Nuxt runtime
## Nuxt UI
Co poskytuje:
- standardnu komponentovu vrstvu pre formularove a bezne aplikacne UI
- komponenty ako `UApp`, `UButton`, `UCard`, `UInput`, `USelect`, `UFormField`, `UAlert`
- integrovany color mode a konzistentne API komponentov
Musi sa pouzit:
- nie
- ale je to predvolena UI vrstva template-u
Ako pouzit:
- v page alebo komponente pouzi `U*` komponenty priamo
- nevytvaraj dalsiu vlastnu vrstvu zakladnych button/input/card komponentov, ak na to nie je silny dovod
Priklad:
```vue
Profil
Ulozit
```
Moznosti rozsirenia:
- vytvarat vlastne feature komponenty nad Nuxt UI
- doplnit komplexne custom komponenty, napriklad diagramy alebo editory
- zmenit vzhlad cez app config, CSS a globalne styly
Odporucany pristup:
- bezne app UI nech riesi Nuxt UI
- specializovane vizualizacie nech riesia vlastne Vue komponenty alebo specializovane kniznice
## i18n
Co poskytuje:
- lokalizaciu pre `sk` a `en`
- preklady v `i18n/locales/sk.json` a `i18n/locales/en.json`
- default locale `sk`
Musi sa pouzit:
- nie
- ale je uz zapojene a pripravene
Ako pouzit:
- texty zapisuj do locale JSON suborov
- v komponente pouzi `useI18n()`
Priklad:
```ts
const { t } = useI18n()
const title = t('app.title')
```
```json
{
"app": {
"title": "Moja aplikacia"
}
}
```
Moznosti rozsirenia:
- pridat dalsie jazyky do `nuxt.config.ts`
- doplnit dalsie namespace v locale JSON suboroch
- zaviest konvencie pre preklady podla modulov, napriklad `users.list.title`
Automaticke overenie:
- template obsahuje test, ktory porovnava strukturu klucov v `i18n/locales/sk.json` a `i18n/locales/en.json`
- pri pridani noveho textu ho dopln do oboch suborov, inak test zlyha
## Pinia
Co poskytuje:
- centralny stav aplikacie
- pripraveny `auth` store v `app/stores/auth.ts`
- pripraveny `ui` store v `app/stores/ui.ts`
Musi sa pouzit:
- nie
- ale je odporucany pre zdielany stav
Ako pouzit:
- lokalny stav formulara drz v komponente
- globalny alebo zdielany stav drz v store
Priklad auth store:
```ts
const authStore = useAuthStore()
if (authStore.isAuthenticated) {
console.log(authStore.displayName)
}
```
Priklad ui store:
```ts
const uiStore = useUiStore()
uiStore.startLoading()
try {
uiStore.pushNotification({
title: 'Hotovo',
message: 'Data boli ulozene.',
tone: 'success'
})
} finally {
uiStore.stopLoading()
}
```
Moznosti rozsirenia:
- pridat dalsie store-y, napriklad `filters`, `settings`, `drafts`
- napojit `ui` store na globalne toasty alebo loading overlay
- rozsirit `auth` store o session info alebo permission model
Automaticke overenie:
- existuju unit testy pre `auth` aj `ui` store, takze zmeny v ich API alebo vypocitavanych hodnotach vies chytit skor, nez sa dostanu do UI
## Autorizacia A Auth Kostra
Co poskytuje:
- vendor-neutral auth vrstvu
- `useAuth()` composable
- auth plugin v `app/plugins/auth.ts`
- globalny middleware v `app/middleware/auth.global.ts`
- route meta typy `public`, `requiresAuth`, `roles`
Musi sa pouzit:
- nie
- auth je volitelna
Ako pouzit:
- nastav mod cez `.env`
- route ochran len tam, kde to dava zmysel
Dostupne mody:
- `disabled`
- `mock`
- `userinfo`
Priklad `.env`:
```env
NUXT_PUBLIC_AUTH_MODE=mock
```
Priklad v komponente:
```ts
const auth = useAuth()
await auth.ensureInitialized()
if (auth.isAuthenticated.value) {
console.log(auth.user.value?.email)
}
```
Priklad ochrany route:
```ts
definePageMeta({
requiresAuth: true
})
```
Priklad ochrany podla role:
```ts
definePageMeta({
requiresAuth: true,
roles: ['ADMIN']
})
```
Moznosti rozsirenia:
- napojit `userinfo` mod na realny backend alebo oauth2-proxy endpoint
- doplnit mapovanie backend user modelu
- pridat jemnejsi access model typu `permissions` alebo `hasAccess(user)`
- doplnit login alebo logout UI do layoutu
Automaticke overenie:
- auth plugin ma testy pre `disabled`, `mock` a `userinfo`
- middleware ma testy pre `public`, `requiresAuth` a `roles`
- to znamena, ze zmeny v auth kostre vies overit bez browser manualu
## API Vrstva
Co poskytuje:
- centralnu API konfiguraciu v `nuxt.config.ts`
- API plugin v `app/plugins/api.client.ts`
- `useApi()` composable
- wrapper vrstvu v `api/wrappers`
Musi sa pouzit:
- nie
- ale je to odporucany sposob volania backendu
Ako pouzit:
- z komponentov volaj `useApi()`
- konkretne HTTP detaily drz vo wrapperoch
Priklad:
```ts
const api = useApi()
const health = await api.example.getHealth()
const welcome = await api.example.getWelcome()
```
Zakladne env:
```env
NUXT_PUBLIC_API_BASE_URL=/api
NUXT_PUBLIC_API_TIMEOUT_MS=10000
```
Moznosti rozsirenia:
- pridat dalsie API wrappery do `api/wrappers`
- rozdelit klientov podla domen, napriklad `users`, `projects`, `reports`
- doplnit error handling, retry alebo auth headers
Odporucanie:
- UI nema volat `fetch` napriamo, ak to nie je jednorazova drobnost
- preferuj centralnu API vrstvu pre konzistenciu
Automaticke overenie:
- ukazkovy wrapper `api/wrappers/example.ts` aj plugin `app/plugins/api.client.ts` maju Vitest testy
- pri pridani dalsieho wrappera je dobry standard doplnit rovnaky test hned s implementaciou
## OpenAPI Priprava
Co poskytuje:
- `openapi-spec` pre specifikacie a generator configy
- `openapi-client` pre generovanych klientov
- `openapi-ts.config.ts`
- skripty `pnpm generate:api` a `pnpm generate:example-api`
Musi sa pouzit:
- nie
- je to priprava pre projekty, kde FE alebo BE kontrakt existuje ako OpenAPI
Ako pouzit:
1. vloz alebo nahrad OpenAPI specifikaciu v `openapi-spec`
2. uprav `openapi-ts.config.ts`
3. spusti generator
4. napoj vysledok cez `api/wrappers`
Priklad:
```bash
pnpm generate:api
```
Moznosti rozsirenia:
- generovat viac klientov pre viac backendov
- verzovat alebo neverzovat generovany kod podla timovej dohody
- doplnit wrappery, ktore skryju rozdiely medzi backendmi
Odporucanie:
- negenerovany kod nech ostane v `api/wrappers` a `app/composables`
- komponenty nech nevolaju generovany OpenAPI klient priamo
- generator je Node-native, takze workflow funguje aj bez Javy
## Logger
Co poskytuje:
- jednoduchy logger plugin
- `useLogger()` composable
- dostupnost cez Nuxt inject
Musi sa pouzit:
- nie
Ako pouzit:
```ts
const logger = useLogger()
logger.info('User opened page', { section: 'dashboard' })
logger.error('Save failed', { id: '123' })
```
Moznosti rozsirenia:
- napojit logovanie na externe sluzby
- doplnit odlisne spravanie pre dev a production
- pridat korelacne ID alebo request context
Automaticke overenie:
- logger plugin ma test na format vystupu
- `useLogger()` ma test na spravne Nuxt inject spravanie
## Testovanie A Overenie
Co sa overuje automaticky:
- store-y
- pluginy
- middleware
- API wrappery
- i18n kluce
Zakladny verify workflow:
```bash
pnpm lint
pnpm typecheck
pnpm test:run
pnpm build
```
Cielene spustenie infrastructure testov template-u:
```bash
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
```
Poznamka:
- testy pre pluginy a middleware pouzivaju `vitest.config.ts`, kde su nastavene aliasy `~`, `@`, `~~` a `@@`
- ak pridas nove runtime injekcie alebo novu rozsirenu Nuxt vrstvu, je dobre doplnit test este v tom istom PR
## Globalne Styly A Tokeny
Co poskytuje:
- `app/assets/styles/ui.css`
- `app/assets/styles/_tokens.scss`
- `app/assets/styles/_theme.scss`
- `app/assets/styles/_base.scss`
- `app/assets/styles/main.scss`
Musi sa pouzit:
- ciastocne ano
- stylova vrstva je sucast template-u, ale mozes ju zmensit alebo vymenit
Ako pouzit:
- `ui.css` nechaj ako vstup pre `tailwindcss` a `@nuxt/ui`
- layoutove a globalne upravy rob v `_base.scss`
- Nuxt UI farby skus najprv nastavit v `nuxt.config.ts` cez `appConfig.ui.colors`
- `_theme.scss` pouzi len na male override-y nad Nuxt UI tokenmi
- zakladne app-level hodnoty drz v `_tokens.scss`
Priklad:
```ts
export default defineNuxtConfig({
appConfig: {
ui: {
colors: {
primary: 'blue',
neutral: 'slate'
}
}
}
})
```
Moznosti rozsirenia:
- doplnit branding projektu
- upravit typografiu, spacing a farby
- v pripade potreby jemne prepisat Nuxt UI tokeny bez budovania vlastneho design systemu
Odporucany mentalny model:
- Nuxt UI je zdroj pravdy pre komponentovy vizual
- `_tokens.scss` drzi male spolocne hodnoty pre app shell
- `_theme.scss` riesi rozdiel medzi light a dark vizualom
- `_base.scss` riesi vlastne layout triedy a app-specific CSS
### Co menit v ktorom subore
`nuxt.config.ts`
- semanticke farby pre Nuxt UI ako prvy krok
- ine Nuxt-level nastavenia
Priklad:
```ts
export default defineNuxtConfig({
appConfig: {
ui: {
colors: {
primary: 'blue',
neutral: 'slate'
}
}
}
})
```
`app/assets/styles/ui.css`
- nechaj len import Nuxt UI vrstvy
- tento subor nie je miesto na app-specific styling
Priklad:
```css
@import "tailwindcss";
@import "@nuxt/ui";
```
`app/assets/styles/_tokens.scss`
- radius
- font family
- layout max width
Priklad:
```scss
:root {
--font-family-base: 'Segoe UI', sans-serif;
--page-max-width: 1320px;
--ui-radius: 1rem;
}
```
`app/assets/styles/_theme.scss`
- jemne prepisy Nuxt UI CSS tokenov
- light/dark rozdiely bez stavania vlastnej komponentovej kniznice
Priklad:
```scss
:root,
.light {
--ui-primary: var(--ui-color-primary-600);
--ui-bg: #f8fafc;
}
.dark {
--ui-primary: var(--ui-color-primary-400);
--ui-bg: #0b1220;
}
```
`app/assets/styles/_base.scss`
- vlastne wrapper triedy
- spacing a layout pre shell
- app-specific utility a responzivne pravidla
Priklad:
```scss
.page-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 1.25rem;
}
```
### Ako funguje light, dark a system tema
Template pouziva `useColorMode()` a prepinac v `app/layouts/default.vue`.
Pouzivane hodnoty:
- `light`
- `dark`
- `system`
Priklad vlastneho prepinaca:
```vue
Zmenit temu
```
Kedy menit `preference` a kedy CSS premenne:
- `colorMode.preference` meni aktivny mod
- CSS premenne v `_theme.scss` menia, ako light a dark mod vyzera
### Typicke scenare uprav
1. Chces iny primary button color.
Najprv skus `appConfig.ui.colors` v `nuxt.config.ts`, a ak chces presnejsi vysledok, dolad `--ui-primary` v `_theme.scss`.
2. Chces tmavsi dark background a jemnejsie card borders.
Uprav `--ui-bg`, `--ui-bg-muted` a `--ui-border` v `_theme.scss`.
3. Chces vacsi radius pre buttony, inputs a cards.
Zmen `--ui-radius` v `_tokens.scss`.
4. Chces sirsi layout alebo iny spacing hero sekcie.
Uprav `_base.scss`.
### Priklady praktickych uprav
Zmena radiusu pre celu app:
```scss
:root {
--ui-radius: 1rem;
}
```
Jemnejsi light mode:
```scss
:root,
.light {
--ui-bg: #f8fafc;
--ui-bg-muted: #f1f5f9;
--ui-border: #dbe4ee;
}
```
Vyraznejsi dark mode:
```scss
.dark {
--ui-bg: #0b1220;
--ui-bg-muted: #111827;
--ui-border: #1f2937;
--ui-text: #e5eef9;
}
```
Silnejsia primarna farba v light mode a jemnejsia v dark mode:
```scss
:root {
--ui-primary: var(--ui-color-primary-700);
}
.dark {
--ui-primary: var(--ui-color-primary-400);
}
```
## Docker Release Image
Co poskytuje:
- [Dockerfile](/c:/Data/Development/MANET/prjtemplates/vue/Dockerfile)
- [.dockerignore](/c:/Data/Development/MANET/prjtemplates/vue/.dockerignore)
- produkcny image pre Nitro server
Musi sa pouzit:
- nie
- ale je to odporucana cesta pre release a deploy
Ako pouzit:
- buildni image cez `docker build`
- spusti kontajner s namapovanym portom `3000`
- runtime premenne dodaj cez `-e`
Priklad:
```bash
docker build -t nuxt-workspace-template:latest .
docker run --rm -p 3000:3000 nuxt-workspace-template:latest
```
Priklad s runtime premennymi:
```powershell
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:
- build stage pouziva `node:24-bookworm-slim`
- runtime stage pouziva hardened `gcr.io/distroless/nodejs24-debian12:nonroot`
- kontajner spusta `.output/server/index.mjs`
- image je urceny pre release alebo deploy, nie pre hot-reload development
## Layout
Co poskytuje:
- spolocny shell aplikacie v `app/layouts/default.vue`
- branding, prepinanie locale a prepinanie temy
Musi sa pouzit:
- nie
- ale je to predvoleny layout
Ako pouzit:
- nechaj sem spolocne prvky aplikacie
- stranky sa do neho renderuju cez ``
Priklad rozsirenia:
- pridat navigation bar
- pridat user menu
- pridat globalne notifikacie alebo loading indikator
## Demo Stranka
Co poskytuje:
- ukazkovu domovsku stranku v `app/pages/index.vue`
- priklad pouzitia i18n, loggera, Nuxt UI a theme switchingu
Musi sa pouzit:
- nie
- je to iba demo start point
Ako pouzit:
- nahrad ju vlastnym dashboardom alebo landing page
Moznosti rozsirenia:
- prerobit na prehlad systemu
- pouzit ju ako interny style guide pre tim
- rozdelit ukazky do samostatnych routes
## VS Code
Co poskytuje:
- `.vscode` konfiguraciu
Musi sa pouzit:
- nie
- ale je to odporucany editorovy setup pre konzistentny workflow
Ako pouzit:
- otvor repo vo VS Code
- spusti `pnpm dev`
Moznosti rozsirenia:
- pridat dalsie VS Code extensions
- upravit Node verziu na hoste
- pridat lokalne helper sluzby podla potrieb projektu
## Kvalita Kodu
Co poskytuje:
- ESLint
- Prettier
- Typecheck
- Vitest
Musi sa pouzit:
- technicky nie
- prakticky ano, ak chces udrzatelny projekt
Ako pouzit:
```bash
pnpm lint
pnpm typecheck
pnpm test:run
pnpm format
```
Moznosti rozsirenia:
- doplnit unit testy
- doplnit component testy
- zapojit CI pipeline
- pridat pre-commit hooks
## Runtime Config
Co poskytuje:
- centralne public config hodnoty v `nuxt.config.ts`
- API a auth env premenne
Musi sa pouzit:
- nie
- ale je to odporucany sposob konfiguracie
Ako pouzit:
Priklad `.env`:
```env
NUXT_PUBLIC_API_BASE_URL=/api
NUXT_PUBLIC_API_TIMEOUT_MS=10000
NUXT_PUBLIC_AUTH_MODE=disabled
NUXT_PUBLIC_AUTH_USERINFO_URL=/api/auth/me
```
Prakticky start:
1. skopiruj `.env.example` do `.env`
2. nastav `NUXT_PUBLIC_API_BASE_URL`
3. rozhodni `NUXT_PUBLIC_AUTH_MODE`
4. ak budes pouzivat `userinfo`, dopln aj login, logout a userinfo URL
Poznamka:
- public runtime config patri do `.env`, nie natvrdo do komponentov
Moznosti rozsirenia:
- pridat dalsie public a private env premenne
- rozdelit config podla modulov
- doplnit feature flags
## Co Je Povinny Zaklad A Co Je Volitelne
Povinny zaklad:
- Nuxt 4
- TypeScript
- zakladna adresarova struktura
- `nuxt.config.ts`
Silno odporucane, ale volitelne:
- Nuxt UI
- i18n
- Pinia
- API vrstva
- logger
- globalne styly
Volitelne casti:
- auth kostra
- OpenAPI generator workflow
- lokalny host workflow nad VS Code
- demo stranka v aktualnej podobe
## Odporucany Sposob Pouzitia Template-u
Ak chces z template-u spravit realny projekt, odporucany postup je:
1. uprav branding, title a preklady
2. rozhodni, ci pouzijes auth a v akom mode
3. nastav API base URL a priprav prve wrappery
4. ak mate OpenAPI kontrakt, nahraj specifikaciu a nastav generator
5. zacni stavat stranky priamo nad Nuxt UI komponentmi
6. zdielany stav presuvaj do Pinia store-ov
7. pred odovzdanim pravidelne pustaj lint, typecheck a testy
Ako spravit prvy krok prakticky:
- v `package.json` zmen `name`
- v `nuxt.config.ts` uprav `app.head.title`, `titleTemplate` a `description`
- v `i18n/locales/sk.json` a `i18n/locales/en.json` prepis demo texty
- v `app/pages/index.vue` nahrad ukazkovu domovsku stranku vlastnym obsahom
- v `nuxt.config.ts`, `app/assets/styles/_tokens.scss`, `_theme.scss` a `_base.scss` dolad semanticke farby, spacing a globalny vizual
## Odporucany Sposob Rozsirovania
Najrozumnejsie miesto pre rozsirovanie podla typu zmeny:
- nova route alebo obrazovka:
`app/pages`
- nova zdielana UI cast alebo zlozitejsi widget:
`app/components`
- nova zdielana logika:
`app/composables`
- novy globalny stav:
`app/stores`
- nove backend volania:
`api/wrappers`
- nova OpenAPI specifikacia:
`openapi-spec`
- nova plugin integracia:
`app/plugins`
- nove typy:
`app/types`
Priklad rozsirania o novu feature:
1. vytvor `app/pages/users/list.vue`
2. pridaj `api/wrappers/users.ts`
3. dopln typy do `app/types/api.ts` alebo pouzi generovany klient
4. ak treba, pridaj `app/stores/users.ts`
5. texty dopln do `i18n/locales/*.json`
## Zaverecne Odporucanie
Tento template nie je monolit, ktory musis pouzit cely. Je to pripraveny zaklad, z ktoreho si mozes zobrat:
- len Nuxt UI a i18n
- len API a OpenAPI workflow
- len auth skeleton
- alebo kompletne vsetky vrstvy spolu
Najlepsie funguje vtedy, ked:
- bezne UI stavas priamo s Nuxt UI
- backend komunikaciu drzis v wrapperoch
- zdielany stav davas do Pinie
- auth zapinas len tam, kde ho naozaj potrebujes