Files
shiftcraft/app/CLAUDE.md
2026-04-17 23:26:01 +00:00

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 in plugins/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 via definePageMeta({ 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.tsauto-generated, do not edit. Contains typed collection names (Collections enum) and record interfaces. Regenerate with pnpm 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.