2.6 KiB
CLAUDE.md — app/
Nuxt Frontend (SPA Mode)
This is a client-side only Nuxt 4 app (ssr: false). No server routes, no server/ directory. All data comes from PocketBase via its SDK.
PocketBase Client Access
const { pb, authStore } = usePocketBase()
pb— PocketBase SDK instance (configured inplugins/pocketbase.ts)authStore— reactive Vue ref wrapping PocketBase's auth state (.isValid,.record,.token)
Never instantiate PocketBase directly. Always use the usePocketBase() composable.
Stores (Pinia)
All backend interaction goes through Pinia stores in stores/:
| Store | Collection | Key patterns |
|---|---|---|
user.ts |
users |
Auth flows (OTP, OAuth), profile CRUD, isAuthenticated getter |
counter.ts |
counters |
Realtime subscription, increment/reset |
notifications.ts |
notifications + fcm_tokens |
Realtime subscription, FCM token registration |
avatar.ts |
users (file field) |
Avatar URL getter, file upload |
Realtime pattern: Stores call pb.collection('x').subscribe('*', callback) in a subscribeToChanges() action. Components call this on mount and unsubscribe() on unmount.
Routing & Middleware
Pages use Nuxt file-based routing. Two middleware:
middleware/auth.ts— route-level guard, add viadefinePageMeta({ middleware: 'auth' })middleware/00.fetchUser.global.ts— runs on every navigation, refreshes auth token
Two layouts: default (with AppHeader) and empty (login/confirm pages).
Components
Organized by feature domain: App/ (header, notifications), Counter/ (widget), Profile/ (avatar, upload, lang select). Components use Nuxt UI v3 primitives (UButton, UCard, UForm, UModal, etc.).
Styling
Tailwind CSS v4 + Nuxt UI. Theme colors set in app.config.ts (primary: teal, neutral: slate). Custom font: Public Sans (defined in assets/css/main.css).
i18n
Strategy: no_prefix — URLs are not prefixed with locale. Two locales: en, de. Translation files in i18n/locales/. Use $t('key') in templates or const { t } = useI18n() in setup.
LanguageCode type defined in types/i18n.types.ts.
Types
types/pocketbase.types.ts— auto-generated, do not edit. Contains typed collection names (Collectionsenum) and record interfaces. Regenerate withpnpm pocketbase:types.types/i18n.types.ts— manual type for supported language codes.
Mobile (Capacitor)
app.vue handles Capacitor-specific setup: deep link listener (App.addListener('appUrlOpen')), push notification registration, and safe-area CSS. Check Capacitor.isNativePlatform() before using native APIs.