mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
199ba687c3
Achievement names, descriptions and category labels, the secret placeholder and the monthly challenge are text the server writes and every client shows as is, so they stayed English in a translated web page and will in the localized iOS app. The routes that return them now read Accept-Language and answer in that language, with Vary: Accept-Language. The translations live in the web's catalogs under serverText, so Crowdin, its checks and its translators handle them through the existing pipeline; the server reads that subtree, and the image copies the catalogs beside dist. English is never looked up: a request without the header, and every client that predates it, gets the bytes it got before. A test keeps serverText in en.json equal to the seed and the constants it mirrors. The web now sends its chosen language on every API request, and the Accept-Language matcher moved into @bookorbit/types so the client and the server negotiate the same way. The iOS app is a consumer the web client does not show: it will send its own interface language. App Store builds that predate that still send the device language, so on a non-English device they will start getting translated achievement names inside English screens. That was accepted; the response shape does not change. Ref bookorbit/bookorbit-ios-support#79
BookOrbit - Client
Vue 3 SPA built with Vite and Tailwind CSS v4.
Running
From the repo root: pnpm dev (starts both server and client).
Client only: pnpm dev (from this directory). Runs at http://localhost:6263.
The Vite dev server proxies /api and /socket.io requests to the backend at localhost:6262.
IDE setup
- VS Code: Install the Vue (Official) extension. Disable Vetur if installed.
- WebStorm / IntelliJ: Vue support is built in. Enable TypeScript service for
.vuefiles. - Browser: Install Vue.js devtools and enable Custom Object Formatters in DevTools settings.
Project layout
src/
├── features/ Feature modules (one folder per domain)
│ ├── auth/ Login, registration, password reset
│ ├── book/ Book detail, covers, metadata
│ ├── library/ Library management
│ ├── collection/ Book collections
│ ├── smart-scope/ Saved search views
│ ├── scanner/ Scan progress UI
│ ├── reader/ Book reader (epub, pdf, cbz)
│ ├── settings/ User settings
│ └── admin/ Admin panel (users, roles, settings)
├── components/ Shared components (header, sidebar, icons)
│ └── ui/ Reusable UI primitives (button, dialog, etc.)
├── composables/ Global composables
├── views/ Route-level page components
├── router/ Vue Router config and guards
├── lib/ Utilities (api client, helpers)
├── stores/ Pinia stores (theme only - prefer composables)
└── assets/ CSS, fonts, static assets
Testing
pnpm test:unit # run unit tests
pnpm test:cov # run unit tests with coverage
Key conventions
- All components use
<script setup lang="ts">(Composition API only). - Feature state lives in composables (
features/<name>/composables/use*.ts), not global stores. - HTTP calls use the native
fetchAPI viasrc/lib/api.ts. - Styling with Tailwind CSS v4 utility classes. Theme tokens are CSS variables in
src/assets/main.css. - Icons from
@lucide/vueonly. - Shared types imported from
@bookorbit/types.