# Development Guide English | [įŽ€äŊ“中文](./Development.zh-CN.md) > Back to [README](../README.md) ## đŸ“Ļ Requirements - **Node.js >= 18** (`engines` in `package.json`) - **pnpm >= 9** — enforced via `preinstall` (`only-allow pnpm`); the repo pins `pnpm@9.15.9` via `packageManager` - Rust toolchain (only for Tauri desktop builds / `dev:tauri`) - Android SDK (only for building the APK locally) ## 🚀 Quick Start ```bash # Install dependencies (pnpm workspace: root + packages/*) pnpm install # Web development (http://localhost:8080, hot reload) npm run dev:web ``` > Note: `dev:web` sets `VUE_APP_PLATFORM=android`, so the browser build runs with the same platform flags as the Android client. ## đŸ› ī¸ NPM Scripts | Script | Description | | --- | --- | | `dev:web` | Web dev server (port 8080, `VUE_APP_PLATFORM=android`) | | `dev:tauri` | Tauri desktop dev (requires Rust) | | `dev:web:tauri` | Web dev server with `VUE_APP_PLATFORM=tauri` | | `build:web` | Production web build → `dist/` | | `build:web:tauri` | Web build with Tauri browserslist/platform env | | `build:and` | Android: web build (`BROWSERSLIST_ENV=capacitor`) + `npx cap sync android` | | `build:and:dev` | Same as above with `BROWSERSLIST_ENV=development` (faster, less optimized) | | `build:ios` | iOS: web build + `npx cap sync ios` (unsigned) | | `build:ios:dev` | Same as above with `BROWSERSLIST_ENV=development` | | `build:win` | Windows desktop build (Tauri, x86_64-pc-windows-msvc) | | `build:mac` | macOS desktop build (Tauri, universal-apple-darwin) | | `lint` | ESLint check + auto-fix for `src/**/*.{js,vue}` | | `bump` | Bump version across all platform configs (see below) | | `check-version` | Verify version consistency across all configs (used by CI) | ## đŸ—ī¸ Platform Abstraction The whole app is built around the `VUE_APP_PLATFORM` env var: | Value | Runtime | Init file | | --- | --- | --- | | `android` | Capacitor | `src/platform/capacitor/init.js` | | `ios` | Capacitor | `src/platform/capacitor/init.js` | | `tauri` | Tauri | `src/platform/tauri/init.js` | - `src/main.js` dynamically imports the platform init based on `VUE_APP_PLATFORM`. - **The platform init is where Vue is mounted** (`new Vue({...}).$mount('#app')`). If no platform matches, the app never mounts. - `src/platform/index.js` exposes flags: `isCapacitor`, `isTauri`, `isAndroid`, `isIOS`, `current`. - Platform init does all of: import global styles, register Vant/Vue plugins/directives, register global components (`WfCont`, `TopBar`, `Pximg`), set up SafeArea / StatusBar / deep links / error tracking, then mount Vue. When adding platform-specific code, create a module under `src/platform/capacitor/` or `src/platform/tauri/`, keep the exported function signatures identical, import it dynamically, and guard call sites with `platform.isCapacitor` / `platform.isTauri`. ## 📁 Project Structure ``` src/ ├── api/ # API calls + HTTP client (axios) │ ├── index.js # Main API module — all endpoint functions │ ├── http.js # Axios instance + interceptors │ ├── client/ # Direct-connect local API (OAuth + Pixiv App API) │ └── user.js ├── assets/ # Global styles (Stylus) ├── components/ # Shared components (image layouts, cards, etc.) ├── consts/ # Env vars, API URLs, constants ├── icons/ # SVG icon loader + components ├── i18n.js # vue-i18n setup ├── layouts/ # BaseLayout.vue, MainLayout.vue ├── lib/ # Third-party wrappers: lodash, vant, vant-apis, polyfill ├── locales/ # 14 locale JSON files (zh-CN is default) ├── platform/ # Capacitor + Tauri platform modules ├── router/ # Vue Router config (history mode) ├── store/ # Vuex store (single store) ├── utils/ # storage, filter, font, novel, translate, ugoira, sync... └── views/ # Page components (Home, Search, Rank, Artwork, Users...) ``` The repo is a **pnpm workspace**; `packages/` contains 8 custom Capacitor plugins maintained in-tree: `capacitor-filesystem`, `capacitor-mediastore`, `capacitor-navigation-bar`, `capacitor-plugin-file-opener`, `capacitor-plugin-filedownload`, `capacitor-plugin-pixiv-cronet`, `capacitor-plugin-pixiv-login`, `capacitor-plugin-saf` ## đŸ”ĸ Version Management Versions must stay in sync across `package.json`, `capacitor.config.json` (User-Agent strings), `src-tauri/tauri.conf.json`, `src-tauri/Cargo.toml` + `Cargo.lock`, `android/app/build.gradle` (`versionName`/`versionCode`) and the iOS `project.pbxproj` (`MARKETING_VERSION`). ```bash # Bump: node scripts/bump.mjs pnpm bump patch # Verify consistency (CI runs this before building) pnpm check-version ``` ## 🎨 Code Style - **ESLint is the only formatter** — there is no Prettier; `lintOnSave: false` in `vue.config.js`. Prefer linting only the files you changed: `npx eslint src/path/to/file.vue --fix` - Single quotes, **no semicolons**, 2-space indentation - Trailing commas in multiline arrays/objects/imports/exports, **never** in function parameters - Named exports only from `@/utils`; no default exports from utility modules - Vue SFC tag order (ESLint-enforced): `