Initial commit
This commit is contained in:
61
app/CLAUDE.md
Normal file
61
app/CLAUDE.md
Normal file
@@ -0,0 +1,61 @@
|
||||
# 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
|
||||
|
||||
```ts
|
||||
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.ts` — **auto-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.
|
||||
Reference in New Issue
Block a user