.cursor/skills/fantasia-quasar-vue/SKILL.md
Builds Vue 3 + Quasar UI for Fantasia Archive: layouts, pages, router, Pinia, and boot files. Use when editing .vue files, Quasar components, routes, or stores under src/.
npx skillsauth add vishiri/fantasia-archive fantasia-quasar-vueInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
package.json engines.node).quasar v2, @quasar/app-vite).src/stores/); router in src/router/.app/ maps to project root (see imports like app/types/...).src/components/)dialogs/ — Dialog* modal SFCs. Root q-dialog v-model refs that participate in global open coordination should call registerComponentDialogStackGuard or registerMarkdownDialogStackGuard from src/scripts/appGlobalManagementUI/dialogManagement.ts (same module as openDialogMarkdownDocument) so names state the stacking rule, not metaphor-only labels.globals/ — app chrome (GlobalWindowButtons, AppControlMenus, AppControlSingleMenu).elements/ — small reusable widgets (FantasiaMascotImage, SocialContactSingleButton).other/ — other composites (SocialContactButtons).foundation/ — Storybook-only design catalogues (FoundationColorPalette, FoundationTextList, …): not shipped in product routes, no i18n/ mirror, no Playwright component tests, stories tagged skip-visual. See AGENTS.md Foundation components.Locale L_* paths under i18n/<locale>/components/ use the same bucket names as src/components/ (foundation/ excluded). See README and AGENTS.md.
src/layouts/MainLayout.vue and routes in src/router/routes.ts.MainLayout.vue registers the app-wide keydown listener after S_FaKeybinds loads from preload; matching and actions live under src/scripts/keybinds/. Tools → Keybind settings edits chords (src/components/dialogs/DialogKeybindSettings/). Extension checklist: fantasia-keybinds and AGENTS.md Global keyboard shortcuts (faKeybinds).src/pages/ComponentTesting.vue with src/layouts/ComponentTestingLayout.vue — use for isolated UI experiments before wiring into main flows.src/components/**/_tests/<Component>.stories.ts with meta.title Components/<bucket>/<ComponentName> (dialogs, elements, foundation, globals, other — same as src/components/ folders). foundation/ stories are reference pages only (skip-visual, docs disabled). Optional canvas-only stories may exist for src/layouts/**/_tests/*.stories.ts and src/pages/**/_tests/*.stories.ts (router previews); for those, do not add autodocs, Docs tab content, or parameters.docs.description — keep parameters.docs.disable: true (see storybook-stories.mdc). Storybook runs from .storybook-workspace/ (config under .storybook-workspace/.storybook/, static build storybook-static/, VRT under visual-tests/ + playwright.storybook-visual.config.ts) so staticDirs and Vite can mirror the Quasar app’s public/ layout. Root scripts: yarn storybook:run, yarn storybook:build, yarn test:storybook:visual*..vue SFC must list top-level blocks in this order only: <template>, then <script> (or <script setup>), then <style> (all style blocks last). Do not open <script> or <style> before <template>.q-*) and existing spacing/typography patterns in sibling components.src/css/quasar.variables.scss for colors and sized units in Vue <style lang="scss"> (not template props). Use hyphens between segments in every $ name (e.g. $globalWindowButtons-zIndex), never underscores. Group order, section banners, and naming are specified in project-scss.mdc.hasScrollbar on the scroll container when content may sometimes overflow and show a vertical scrollbar (and sometimes not), so scrollbar-gutter: stable prevents horizontal layout jitter. Defined in src/css/globals/scrollbar.scss; see project-scss.mdc and AGENTS.md.src/boot/ run at app init (e.g. axios, external links).I_ / T_ prefixes and use descriptive singular/collection naming (e.g. T_documentName, I_appMenuList).import type for type-only imports..vue SFCs, prefer template $t('...') translation calls; avoid importing useI18n only for t(...) when a template binding can express the same text.public/ assets and Electron (file://)import.meta.env.BASE_URL as '/' or '' for the Electron renderer. URLs such as /images/foo.png then resolve to the filesystem root under file://, not next to index.html, and images or other public/ files may fail to load in packaged builds (and break Playwright assertions that expect a loaded <img>).public/, build href/src with a relative base when BASE_URL is '/' or empty (e.g. ./images/...). Example: SocialContactSingleButton.vue._data/ (production structured payloads).vue file would hold a large production data object (menus, multi-part configs, long lists), move pieces under src/components/<Feature>/_data/..ts files inside _data/ instead of one giant file when it aids navigation (mirror AppControlMenus/_data).i18n), imported copy helpers, and functions on items (e.g. trigger handlers); they are not limited to string literals._data/ or in _tests/<fixture>.ts modules: Vitest keeps it inside *.vitest.test.ts; Playwright keeps mount payloads inline in *.playwright.test.ts and passes them via COMPONENT_PROPS. If a parent SFC must embed a component-mode-only blob, keep it as a const inside that .vue. See vue-quasar.mdc for split vs src/scripts/ boundaries.scripts/ and SFC size.vue ≤250 lines, functions ≤50 lines, non-exempt .ts ≤200 lines — see code-size-decomposition.mdc. When a feature would exceed them, extract into src/components/<bucket>/<Feature>/scripts/*.ts, add subcomponents, and/or move shared pure logic to src/scripts/. Do not park feature-owned extractions next to the .vue at the feature root.scripts/: limits are maximums. Prefer fewer TypeScript modules that each hold a whole concern (for example one file for table rows + columns + filtered state, one for dialog open + routing + global suspend) until a file approaches 200 lines or a single function approaches 50 lines. Avoid a long list of 10–20 line files with one export each when grouping would stay within ESLint caps — see code-size-decomposition.mdc Module count: prefer logical grouping. After merging production modules, merge or rename colocated scripts/_tests/*.vitest.test.ts so tests stay easy to find.src/scripts/<feature>/: same anti-fragmentation rule as component scripts/ — batch by subsystem (see typescript-scripts.mdc); add a thin extra file only for a documented boundary (mock target, circular import, public shim).<style> files are a last resort anti-pattern; use only with explicit user approval in that session._data/ (production structured payloads) and from src/scripts/ (shared app-wide helpers). See vue-quasar.mdc..vue files (split by topic)| Topic | Rule |
|-------|------|
| Quasar, Composition API, i18n, script size / extraction | vue-quasar.mdc |
| BEM classes and scoped SCSS only | vue-bem-scss.mdc |
| data-test-locator and other Playwright data-test-* template hooks | vue-template-test-hooks.mdc |
| Global SCSS / src/css | project-scss.mdc |
yarn testbatch:verify (testing-terminal-isolation.mdc) — see eslint-typescript.mdc. TSLint is not used.yarn lint:stylelint extra attention when changing Vue <style> blocks or src/**/*.scss.quasar.config.ts: match Quasar typings (e.g. PWA workboxMode: 'GenerateSW' | 'InjectManifest'; bex uses QuasarBexConfiguration, not legacy contentScripts). Duplicate Vite Plugin types vs @quasar/app-vite may require a documented @ts-expect-error on defineConfig.src/boot/i18n.ts: vue-i18n module augmentation may use @ts-expect-error (TS2665) because the package module entry targets the ESM bundle under tsc.any; prefer explicit prop/emits/interfaces, unknown, and narrowing.src/components/**, src/layouts/**, and src/pages/**: each feature .vue should have a colocated _tests/<Name>.vitest.test.ts (presence baseline; not a claim of exhaustive line/branch coverage).i18n/index.ts or i18n/en-US/index.ts) because they import markdown documents/*.md.L_* locale modules (for example menu/button translation modules) and provide explicit placeholder copy for markdown-backed documents.* keys used by dialogs.A11y/* category for this project.TEST_ENV === 'components' branches; validate those paths in Playwright/component-test harnesses instead.types/)interface / type declarations in repository-root types/ (import with app/types/...). Prefer one domain-oriented module per feature area with brief JSDoc on exports (see types/I_appMenusDataList.ts). Do not add colocated <filename>.types.ts under src/, src-electron/, or .storybook-workspace/. Ambient augmentations for third-party modules also live under types/ and are loaded with a side-effect import from the owning boot file or src/stores/index.ts (see types/piniaModuleAugmentation.ts)..js), TypeScript (.ts), Vue (.vue), and JSON (.json, .jsonc, .json5) files, enforce expanded multi-line object literals via ESLint (object-curly-newline + object-property-newline) and keep files auto-fixable with eslint --fix.development
Splits working tree changes into logical Git commits with conventional messages (feat, fix, test, chore, refactor, style, docs). Proposes commits one at a time and waits for explicit user approval before each git commit. Use when the user asks to commit, split commits, stage by topic, or use conventional / semantic commit messages.
development
Aligns AI suggestions with Fantasia Archive as a worldbuilding database manager: projects, documents, and in-app concepts. Use when designing UX, data models, menus, or copy that should match the product purpose.
development
Runs and extends Fantasia Archive tests: Vitest unit tests vs Playwright component and E2E tests, including rebuild-before-Playwright rules and file naming. Use when writing tests, debugging CI, or when the user mentions Vitest, Playwright, component tests, or e2e.
development
Designs SQLite usage in Fantasia Archive’s Electron main process: file locations under userData, native better-sqlite3 module constraints, and migrations. Use when editing electron-main database code, schema, or persistence paths.