{"id":"d6d6f7cb-b25f-4412-8ea1-7313b8db1429","entityType":"agent","slug":"clawhub-bovinphang-fec-vue3-project-standard","name":"Vue3 Project Standard","canonicalUrl":"https://www.xpersona.co/agent/clawhub-bovinphang-fec-vue3-project-standard","canonicalPath":"/agent/clawhub-bovinphang-fec-vue3-project-standard","generatedAt":"2026-10-13T17:23:19.381Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":null},"description":"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil Skill: Vue3 Project Standard Owner: bovinphang Summary: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil Tags: latest:2.9.0 Version history: v2.9.0 | 2026-09-26T14:41:4","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 959 downloads reported by the source. Last updated 10/12/2026.","installCommand":"clawhub skill install s175m64gr8tsfc06cj22czzfys83mp52:fec-vue3-project-standard","sourceUrl":"https://clawhub.ai/bovinphang/fec-vue3-project-standard","homepage":"https://clawhub.ai/bovinphang/skills/fec-vue3-project-standard","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/bovinphang/fec-vue3-project-standard","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/bovinphang/skills/fec-vue3-project-standard","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":60,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, AP"},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":null},"stars":null,"forks":null,"downloads":959,"likes":null,"task":null,"library":null,"packageName":null,"latestVersion":"2.9.0","tractionLabel":"959 downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-12T01:48:35.766Z","emptyReason":null},"lastUpdatedAt":"2026-10-12T01:48:35.856Z","lastCrawledAt":"2026-10-12T01:48:35.766Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-13T01:48:35.766Z","lastVerifiedAt":null,"highlights":[{"version":"2.9.0","createdAt":"2026-09-26T14:41:46.275Z","changelog":"## fec-vue3-project-standard v2.9.0 - Translated SKILL.md content from Chinese to English, standardizing terminology for an international audience. - Added a LICENSE file for clearer project licensing. - Removed the skill-card.md file.","fileCount":11,"zipByteSize":16425},{"version":"2.7.0","createdAt":"2026-06-11T02:15:23.503Z","changelog":"- Reference content split into four focused documentation files for project structure, composables/routing, state/API/quality, and performance patterns. - Legacy reference and skill card files removed. - Updated core procedure to clarify composable input conventions, cross-framework typing, and component test scope. - Constraints expanded to cover getter/callback handling and improved component test assertions. - Output expectations refined to include composable reactivity, Pinia/Router edge cases, and async component testing guidelines.","fileCount":10,"zipByteSize":16522},{"version":"2.4.0","createdAt":"2026-06-01T09:27:08.848Z","changelog":"Version 2.4.0 - Added LICENSE, README.md, metadata.json, package.json, and detailed structural reference (references/vue3-project-details.md) - Removed skill-card.md - Updated skill trigger and description for improved specificity and English usage - Refined structure: split out detailed architecture, conventions, and procedures into dedicated references file - Clarified boundaries and constraints for components, composables, Pinia, and error handling - Output expectations and guidance are now more concise and strictly scoped to architecture, not style/test specifics","fileCount":7,"zipByteSize":13210}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s175m64gr8tsfc06cj22czzfys83mp52:fec-vue3-project-standard","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-13T17:23:19.381Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-bovinphang-fec-vue3-project-standard/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":null},"readme":"Skill: Vue3 Project Standard\n\nOwner: bovinphang\n\nSummary: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil\n\nTags: latest:2.9.0\n\nVersion history:\n\nv2.9.0 | 2026-09-26T14:41:46.275Z | user\n\n## fec-vue3-project-standard v2.9.0\n\n- Translated SKILL.md content from Chinese to English, standardizing terminology for an international audience.\n- Added a LICENSE file for clearer project licensing.\n- Removed the skill-card.md file.\n\nv2.7.0 | 2026-06-11T02:15:23.503Z | user\n\n- Reference content split into four focused documentation files for project structure, composables/routing, state/API/quality, and performance patterns.\n- Legacy reference and skill card files removed.\n- Updated core procedure to clarify composable input conventions, cross-framework typing, and component test scope.\n- Constraints expanded to cover getter/callback handling and improved component test assertions.\n- Output expectations refined to include composable reactivity, Pinia/Router edge cases, and async component testing guidelines.\n\nv2.4.0 | 2026-06-01T09:27:08.848Z | user\n\nVersion 2.4.0\n\n- Added LICENSE, README.md, metadata.json, package.json, and detailed structural reference (references/vue3-project-details.md)\n- Removed skill-card.md\n- Updated skill trigger and description for improved specificity and English usage\n- Refined structure: split out detailed architecture, conventions, and procedures into dedicated references file\n- Clarified boundaries and constraints for components, composables, Pinia, and error handling\n- Output expectations and guidance are now more concise and strictly scoped to architecture, not style/test specifics\n\nArchive index:\n\nArchive v2.9.0: 11 files, 16425 bytes\n\nFiles: LICENSE (1089b), metadata.json (2350b), package.json (1232b), README.md (1781b), references/vue3-composables-routing.md (5391b), references/vue3-performance-patterns.md (604b), references/vue3-project-structure.md (8234b), references/vue3-state-api-quality.md (6444b), skill-card.md (1958b), SKILL.md (4912b), _meta.json (144b)\n\nFile v2.9.0:SKILL.md\n\n---\nname: fec-vue3-project-standard\ndescription: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\n---\n\n# Vue 3 project specifications\n\nFor repositories using Vue 3 + TypeScript.\n\n## Purpose\n\nProvides project structure, component boundaries, Composables, and default implementation conventions for Vue 3 + TypeScript projects to ensure conventional development and type safety.\n\n## Procedure\n\n1. Identify the existing Vue conventions in the warehouse: directory, routing, Pinia, request layer, style system, component library and test framework.\n2. Demarcate the boundaries between pages, business components, common components, composables, stores, services and utils.\n3. Prioritize the existing automatic import/module export conventions of `<script setup lang=\"ts\">`, composite API and warehouse.\n4. Complete state ownership, API layer, error handling, style isolation and special skill offloading when outputting.\n5. Pages and modules must have recoverable error UI; global `errorHandler`, `onErrorCaptured`, request error mapping and routing error page have clear division of labor.\n6. Tailwind token/variant or responsive layout requirements should be diverted to corresponding special skills to avoid stuffing style system rules into Vue component specifications.\n7. When the state ownership is complex, first make a state list; when the boundaries of DTO, public props, generic composable or `tsconfig` are complex, first use the TypeScript project specification process to converge cross-framework type contracts.\n8. When designing reusable composables, clarify whether the input supports plain value, ref, computed or getter; when testing Vue components, cover the common boundaries of Pinia, Router, Teleport, Suspense and async setup.\n\n## Detailed reference\n\nLoad more detailed reference files as needed:\n\n- Project directory, component layering, component specifications, annotations, and TypeScript: Load [references/vue3-project-structure.md](references/vue3-project-structure.md).\n- Composables, slots, Provide/Inject and routing organizations: Load [references/vue3-composables-routing.md](references/vue3-composables-routing.md).\n- Pinia, API layer, error handling, directives, styles, tests, anti-patterns and output checklist: Loading [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md).\n- Lightweight performance conventions at the Vue project specification level: Load [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md).\n\n## Constraints\n\n- Use `<script setup lang=\"ts\">` to disable using Options API to add new components\n- The size of the component file should be approximately **300 lines**; if it exceeds **500 lines** or is too complex, sub-components and Composables must be separated\n- Props / Emits must be defined using the TypeScript interface, and `any` is prohibited\n- Composable returns a `readonly` reference to prevent accidental external modifications\n- Do not store UI temporary states (modal switches, form inputs, etc.) in the store\n- Server-side data is first managed by the request library rather than manually stored in Pinia\n- Avoid using `v-if` in `v-for` (extract to computed filtering)\n- It is forbidden to import directly from the deep path inside the feature, bypassing `index.ts`\n- No need for global error handling to swallow recoverable API, form or permission errors within components.\n- Do not mistake function parameters for getter automatic calls; if composable parameters may be callbacks, avoid using getter input conventions.\n- Do not rely on snapshots as the only assertions for Vue components; asynchronous components, Teleport and Pinia scenes must have user-visible behavior assertions.\n\n## Expected Output\n\n- The component uses `<script setup lang=\"ts\">`, and the Props/Emits type is complete\n- Reusable logic has been extracted to composable, returning `readonly` reference\n- Loading / Error / Empty / Data status have been processed\n- Routing components are loaded using dynamic import, and state management conforms to the proximity principle\n- URL status, server status, form status and Pinia global status have clear boundaries\n- API calls have type constraints and unified error handling\n- Styles are isolated using scoped, and key behaviors are covered by tests\n- The file structure is consistent with the project convention (pages/features/components are separated)\n- Input responsiveness, Pinia/Router boundaries and asynchronous component testing strategies for reusable composables explained\n\nFile v2.9.0:README.md\n\n# Vue 3 project specifications\n\nOrganize Vue 3 and TypeScript SFCs, composables, routes, Pinia, and project boundaries.\n\n## Skill\n\n- ID: `fec-vue3-project-standard`\n- Category: `project-standard`\n- Version: `2.9.0`\n- Source: `skills/fec-vue3-project-standard/SKILL.md`\n\n## Description\n\nUse when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\n\n## Usage\n\nInstall or import this package with any skill runtime that understands the standard `SKILL.md` layout. The canonical source remains the Frontend Craft repository.\n\n## Packaged Files\n\n- [references/vue3-composables-routing.md](references/vue3-composables-routing.md)\n- [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md)\n- [references/vue3-project-structure.md](references/vue3-project-structure.md)\n- [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md)\n\n## Optional Related Packages\n\n- `@bovinphang/fec-typescript-project-standard`\n- `@bovinphang/fec-state-management`\n- `@bovinphang/fec-tailwind-design-system`\n- `@bovinphang/fec-responsive-layout`\n- `@bovinphang/fec-form-handling`\n- `@bovinphang/fec-data-fetching`\n- `@bovinphang/fec-component-testing`\n- `@bovinphang/fec-e2e-testing`\n- `@bovinphang/fec-accessibility-check`\n- `@bovinphang/fec-security-review`\n- `@bovinphang/fec-list-virtualization`\n- `@bovinphang/fec-svg-animation`\n- `@bovinphang/fec-canvas-threejs`\n\n## License\n\nMIT\n\nFile v2.9.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b0nh7hvj1pffeqc8y0dqwwh83m726\",\n  \"slug\": \"fec-vue3-project-standard\",\n  \"version\": \"2.9.0\",\n  \"publishedAt\": 1790433706275\n}\n\nFile v2.9.0:references/vue3-composables-routing.md\n\n# Vue 3 composables and routing patterns\n\n## Composables specification\n\n### Design principles\n\n- Named with `use` prefix\n- Use objects as return values and clearly mark the type\n- Internal processing loading / error / data tri-state\n-Support parameter responsiveness (accepts `Ref` or getter)\n- Library level composable to clarify whether the parameter supports normal values, `Ref`, `computed` or getter, and parse the latest value inside the side effect\n\n```typescript\nexport function useUserList(params: MaybeRef<QueryParams>) {\n  const data = ref<User[]>([]);\n  const loading = ref(false);\n  const error = ref<Error | null>(null);\n\n  async function fetch() {\n    loading.value = true;\n    error.value = null;\n    try {\n      const res = await getUserList(toValue(params));\n      data.value = res.list;\n    } catch (e) {\n      error.value = e as Error;\n    } finally {\n      loading.value = false;\n    }\n  }\n\n  watchEffect(() => {\n    fetch();\n  });\n\n  return {\n    data: readonly(data),\n    loading: readonly(loading),\n    error: readonly(error),\n    refetch: fetch,\n  };\n}\n```\n\n### Composable usage principles\n\n- Return a `readonly` reference to prevent accidental modification by outsiders\n- In data request scenarios, libraries such as VueQuery / VueUse are preferred (if the project has been introduced)\n- Clean up timers, event listeners and other side effects in `onUnmounted`\n- Avoid directly manipulating DOM in composable\n- Read-only inputs accept normal values, refs, computed or getters; inputs that require bidirectional writing only accept writable refs or explicit setters.\n- If the parameter itself is a callback, comparator or predicate, do not design it as a getter type input, otherwise the business function may be mistakenly called during parsing.\n\n### Vue Router / Pinia / Test common boundaries\n\n- Changes in routing parameters will not recreate the same routing component; data that relies on `route.params` must watch clear fields and handle cancellation and race conditions.\n- Avoid old-style `next()` multi-branch repeated calls in navigation guards; give priority to returning `false`, redirecting objects or throwing handleable errors.\n- Use `storeToRefs` when destructuring the Pinia store will lose responsiveness; the setup store must return state, getters and actions that need to be tracked externally.\n- UI temporary status, form input, and pop-up window switches do not enter the global store; URL query, server-side cache, and local component status are returned to their respective places first.\n- Vue Test Utils tests prioritize user-visible behavior and do not use snapshots as the only proof; asynchronous updates use `await`, `flushPromises` or the waiting method recommended by the framework.\n- When testing using Pinia, Router, Teleport, Suspense, async setup or `defineAsyncComponent`, explicitly install the plugin in the test fixture, mount the target container and wait for async to stabilize.\n\n## Slots and Provide/Inject\n\n### Slots\n\n- Use `<slot>` to achieve component composition instead of too many props\n- Named slots are used for explicit layout areas\n- Scope slot passes data to parent component for custom rendering\n\n```vue\n<template>\n  <div class=\"card\">\n    <div class=\"card-header\">\n      <slot name=\"header\">{{ title }}</slot>\n    </div>\n    <div class=\"card-body\">\n      <slot :data=\"processedData\" :loading=\"loading\" />\n    </div>\n  </div>\n</template>\n```\n\n### Provide/Inject\n\n- For context sharing across multiple levels (topics, configurations, permissions)\n- Provide InjectionKey to ensure type safety\n- Do not use provide/inject instead of props to pass direct parent-child data\n\n```typescript\n// keys.ts\nexport const ThemeKey: InjectionKey<Ref<Theme>> = Symbol(\"theme\");\n\n// Provider.vue\nprovide(ThemeKey, theme);\n\n// Consumer.vue\nconst theme = inject(ThemeKey);\n```\n\n## Routing specifications\n\n### Routing organization\n\n```typescript\n// app/router.ts\nconst routes: RouteRecordRaw[] = [\n  {\n    path: \"/\",\n    component: MainLayout,\n    children: [\n      {\n        path: \"\",\n        name: \"Dashboard\",\n        component: () => import(\"@/pages/Dashboard/DashboardPage.vue\"),\n      },\n      {\n        path: \"users\",\n        name: \"UserList\",\n        component: () => import(\"@/pages/UserList/UserListPage.vue\"),\n      },\n      {\n        path: \"users/:id\",\n        name: \"UserDetail\",\n        component: () => import(\"@/pages/UserDetail/UserDetailPage.vue\"),\n      },\n      {\n        path: \"settings\",\n        name: \"Settings\",\n        component: () => import(\"@/pages/Settings/SettingsPage.vue\"),\n      },\n    ],\n  },\n  {\n    path: \"/login\",\n    name: \"Login\",\n    component: () => import(\"@/pages/Login/LoginPage.vue\"),\n  },\n  {\n    path: \"/:pathMatch(.*)*\",\n    name: \"NotFound\",\n    component: () => import(\"@/pages/NotFound.vue\"),\n  },\n];\n```\n\n### Routing principles\n\n- Centralized management of routing configuration, each route must have a `name`\n- Page components are loaded on demand using dynamic `import()`\n- Permission control uses route guard (`beforeEach`) instead of judging within each page\n- URL parameters (pagination, filtering, sorting) and routing status are synchronized\n\n```typescript\n// Navigation guard\nrouter.beforeEach((to) => {\n  const authStore = useAuthStore();\n  if (to.meta.requiresAuth && !authStore.isLoggedIn) {\n    return { name: \"Login\", query: { redirect: to.fullPath } };\n  }\n});\n```\n\nFile v2.9.0:references/vue3-performance-patterns.md\n\n# Vue 3 performance patterns\n\nThis file keeps lightweight Vue project-standard performance guidance. Use the frontend performance workflow when the task needs metrics, traces, profiles, bundle analysis, network evidence, or a formal performance report.\n\n## Performance\n\n- Use `shallowRef` / `shallowReactive` to optimize large objects\n- Use virtual scrolling for large lists\n- Avoid using `v-if` in `v-for` (extract to computed filtering)\n- Use `defineAsyncComponent` to lazily load heavy components\n- `v-for` must have a stable `:key`\n- Routing components are loaded on demand using dynamic `import()`\n\nFile v2.9.0:references/vue3-project-structure.md\n\n# Vue 3 project structure and component standards\n\n## Project structure\n\nThe following is the industry's best practice structure for medium and large Vue 3 projects, tailored according to the actual situation of the project:\n\n```\nsrc/\n├── app/ # Application entry and global configuration\n│ ├── App.vue # Root component\n│ ├── main.ts # Application startup entrance\n│ └── router.ts # Routing instance and configuration\n│\n├── pages/ # Page components (one-to-one correspondence with routing)\n│   ├── Dashboard/\n│   │   ├── DashboardPage.vue\n│ │ ├── components/ # Page private components\n│ │ └── composables/ # Page private composables\n│   ├── UserList/\n│   └── Settings/\n│\n├── layouts/ # Layout component\n│ ├── MainLayout.vue # Main layout (sidebar + top bar + content area)\n│ ├── AuthLayout.vue # Login/registration page layout\n│ └── BlankLayout.vue # Blank layout (error page, etc.)\n│\n├── features/ # Function modules (divided by business areas)\n│   ├── auth/\n│ │ ├── components/ # Module components\n│ │ ├── composables/ # module composables\n│ │ ├── api.ts # Module API call\n│ │ ├── types.ts # Module type definition\n│ │ ├── constants.ts # Module constants\n│ │ └── index.ts # Module publicly exported\n│   └── order/\n│\n├── components/ # Globally shared UI components\n│   ├── AppButton/\n│   │   ├── AppButton.vue\n│   │   └── __tests__/\n│   ├── AppModal/\n│   ├── AppForm/\n│   └── AppErrorBoundary/\n│\n├── composables/ # Global shared composables\n│   ├── useAuth.ts\n│   ├── useDebounce.ts\n│   └── useMediaQuery.ts\n│\n├── services/ # API base layer\n│ ├── request.ts # Axios/fetch instance and interceptor\n│ └── endpoints/ # API endpoint definition (such as split by field)\n│\n├── stores/ # Pinia status management\n│   ├── authStore.ts\n│   └── uiStore.ts\n│\n├── locales/ # International language pack\n│ ├── zh-CN.json # Simplified Chinese\n│ ├── en-US.json # English\n│ └── index.ts # i18n instance initialization (vue-i18n)\n│\n├── assets/ # Static resources\n│ ├── images/ # Pictures (PNG, JPG, WebP)\n│ ├── icons/ # SVG icon\n│ └── fonts/ # Custom fonts\n│\n├── config/ # Application configuration\n│ ├── env.ts # Typed encapsulation of environment variables\n│ └── features.ts # Feature Flags Management\n│\n├── types/ # Global shared types\n│ ├── api.ts # API response/request common type\n│ ├── models.ts #Business entity type\n│ └── global.d.ts # Global type extension (component type, module declaration, etc.)\n│\n├── utils/ # Pure utility function\n│ ├── format.ts # Date, number, currency formatting\n│ ├── validators.ts # Form validation rules\n│ └── storage.ts # LocalStorage / SessionStorage package\n│\n├── directives/ # Custom directives\n│ ├── vPermission.ts # Permission command\n│ └── vClickOutside.ts # Click outside to close\n│\n├── plugins/ # Vue plug-in registration\n│ ├── i18n.ts # vue-i18n plug-in configuration\n│ └── index.ts # Plug-in unified registration entrance\n│\n├── styles/ # Global styles and themes\n│ ├── global.css # Global basic style (reset/normalize)\n│ ├── variables.css # CSS variables (color, spacing, font size)\n│ ├── breakpoints.ts # Responsive breakpoint constants\n│ └── themes/ # theme definition\n│ ├── light.css # Light theme variable\n│ ├── dark.css # Dark theme variable\n│ └── index.ts # theme switching logic\n│\n└── constants/ # Global constants\n    ├── routes.ts #Routing path constants\n    └── config.ts #Business constants (paging size, timeout, etc.)\n```\n\n### Key Principles\n\n- `pages/` does route mapping and layout combination without putting business logic\n- `layouts/` defines the page skeleton (sidebar, top bar, breadcrumbs), referenced by the `component` of the routing configuration\n- `features/` is divided by business areas, self-contained within the module (components + composables + api + types)\n- `components/` only contains common components without business coupling and can be reused across projects\n- `composables/` only places common logic (anti-shake, media query, etc.), and business composables are placed in the corresponding feature\n- `locales/` stores language pack JSON files, use `$t('key')` in the template instead of hard-coded copy\n- `assets/` stores static resources, SVG is preferred for icons, and WebP/AVIF is preferred for images.\n- `config/` encapsulates environment variables and Feature Flags, prohibiting direct reading of `import.meta.env` in components\n- `styles/themes/` implements theme switching through CSS variables. Variables are referenced in components instead of hard-coded colors.\n- Each module controls the public API through `index.ts` to avoid deep path imports\n\n## Component design specifications\n\n- Use `<script setup lang=\"ts\">`\n- Explicitly use `defineProps` / `defineEmits` with accompanying types\n- Reusable logic is first extracted to composables\n- Keep the template readable and avoid too deep nesting of conditions\n- Prefer using computed properties instead of repeatedly maintaining state\n- Avoid building large single components; **single file size** see `templates/shared/rules/fec-vue.md` \"**component file size**\" (approximately 300 lines or less, more than 500 lines or too complex to separate sub-components and Composables)\n- Prioritize the use of strongly typed props, emits and exposed methods\n- Follow the file and directory naming conventions of the warehouse\n- Prioritize reuse of existing UI components and tokens\n\n### Component layering\n\n```\nPages → Route mapping, layout combination\n  └── Container components (Containers) → Data acquisition, status orchestration\n       └── Business components (Features) → Domain logic display\n            └── Universal Component (UI) → Pure display, no business coupling\n```\n\n## Comment specifications\n\n- **Prefer using Chinese**: When explaining \"why this is done\", business constraints, boundary conditions, and non-obvious trade-offs, give priority to writing comments in Chinese to make it easier for the team and business parties to read.\n- **Exception when consistent with the code language**: When connecting third-party protocol field names, HTTP headers, and English terms in specifications, English proper nouns can be retained in the comments, and Chinese and English descriptions can be given when necessary.\n- **Less but more precise**: Can express clear logic through clear naming and types without writing nonsense comments; complex branches, temporary compatibility, and performance trade-offs must be clearly stated.\n- **Public API**: Composable or module external contracts can use JSDoc (`@param` / `@returns` / `@example`). The instructions can be in Chinese, unless the warehouse requires English.\n\n## TypeScript Specification\n\nCommon TypeScript project rules are taken care of by `fec-typescript-project-standard`, including `tsconfig`, strictness, DTO / view model boundaries, `unknown` narrowing, public API types, declared artifacts, and type tests.\n\nThe Vue specification only supplements SFC, Props / Emits, exposed methods, Provide / Inject and composable reactive types; complex type modeling or cross-framework type contracts are first offloaded to `fec-typescript-project-standard`.\n\n### Vue 3 project supplementary conventions\n\n```vue\n<script setup lang=\"ts\">\ninterface Props {\n  title: string;\n  items: Item[];\n  loading?: boolean;\n}\n\ninterface Emits {\n  (e: \"select\", item: Item): void;\n  (e: \"delete\", id: string): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  loading: false,\n});\n\nconst emit = defineEmits<Emits>();\n</script>\n```\n\n- Props and Emits are defined using the TypeScript interface\n- Use `withDefaults` to set default values\n- `defineExpose` exposed methods must have type constraints\n\nFile v2.9.0:references/vue3-state-api-quality.md\n\n# Vue 3 state, API, and quality patterns\n\n## Status Management (Pinia)\n\n| Status type | Recommended solution |\n| ------------------ | ----------------------------- |\n| Temporary UI state within the component | `ref` / `reactive` |\n| Sharing business status across components | Pinia store |\n| Server-side data cache | VueQuery / Custom composable |\n| URL driver status | Route parameters / `useRoute().query` |\n| Form Status | VeeValidate / FormKit |\n\n### Pinia Store Specifications\n\nUsing Composition API style (`setup store`):\n\n```typescript\n// stores/authStore.ts\nexport const useAuthStore = defineStore(\"auth\", () => {\n  const user = ref<User | null>(null);\n  const token = ref<string | null>(localStorage.getItem(\"token\"));\n\n  const isLoggedIn = computed(() => !!token.value);\n\n  async function login(credentials: LoginParams) {\n    const res = await authApi.login(credentials);\n    user.value = res.user;\n    token.value = res.token;\n    localStorage.setItem(\"token\", res.token);\n  }\n\n  function logout() {\n    user.value = null;\n    token.value = null;\n    localStorage.removeItem(\"token\");\n  }\n\n  return { user: readonly(user), isLoggedIn, login, logout };\n});\n```\n\n### Store Principles\n\n- Each store has a single responsibility and is split by area.\n- Expose the status of `readonly` to the outside world and modify it through action\n- Do not store UI temporary states (modal switches, form inputs, etc.) in the store\n- Server-side data is first managed by the request library rather than manually stored in the store\n\n## API layer specification\n\n### Request instance\n\n```typescript\n// services/request.ts\nconst request = axios.create({\n  baseURL: import.meta.env.VITE_API_BASE_URL,\n  timeout: 10000,\n});\n\nrequest.interceptors.request.use((config) => {\n  const authStore = useAuthStore();\n  if (authStore.token) {\n    config.headers.Authorization = `Bearer ${authStore.token}`;\n  }\n  return config;\n});\n\nrequest.interceptors.response.use(\n  (res) => res.data,\n  (error) => {\n    if (error.response?.status === 401) {\n      const authStore = useAuthStore();\n      authStore.logout();\n      router.push({ name: \"Login\" });\n    }\n    return Promise.reject(normalizeError(error));\n  },\n);\n```\n\n### API functions\n\n```typescript\n// features/user/api.ts\nexport function getUserList(\n  params: UserQueryParams,\n): Promise<PageResult<User>> {\n  return request.get(\"/users\", { params });\n}\n\nexport function updateUser(id: string, data: UpdateUserDTO): Promise<User> {\n  return request.put(`/users/${id}`, data);\n}\n```\n\n- API functions are organized by feature instead of all being piled in one file\n- Request parameters and responses have type constraints\n- The interceptor handles authentication and error formatting uniformly\n\n## Error handling\n\n### Global error capture\n\n```typescript\n// main.ts\napp.config.errorHandler = (err, instance, info) => {\n  reportError(err, { component: instance?.$options.name, info });\n};\n```\n\n### Component level errors\n\n- Use `onErrorCaptured` to capture child component errors in the parent component\n- Failed data requests must have user-visible prompts and retry mechanisms\n- Don't swallow errors (empty catch block)\n\n## Custom directive\n\n```typescript\n// directives/vPermission.ts\nexport const vPermission: Directive<HTMLElement, string> = {\n  mounted(el, binding) {\n    const authStore = useAuthStore();\n    if (!authStore.hasPermission(binding.value)) {\n      el.parentNode?.removeChild(el);\n    }\n  },\n};\n```\n\n- The directive only handles operations at the DOM level\n- Do not put business logic in instructions\n- Implement the `updated` hook when responsive updates are required\n\n## Style specification\n\n- Use `<style scoped>` to isolate styles\n- Depth selector uses `:deep()` instead of the deprecated `::v-deep`\n- Be consistent with the existing style system of the project\n- Dynamic styles preferentially use `:class` / `:style` binding\n- Complex theme switching using CSS variables\n- Theme/global variables are managed through CSS variables or Token\n\n## Test specifications\n\n### Must be tested\n\n- Core interaction behaviors (click, input, submit)\n- Conditional rendering (loading/error/empty/data)\n- Emits trigger and payload\n- Return value of key composables\n- Pinia store actions and getters\n\n### Test style\n\n```typescript\ndescribe(\"UserForm\", () => {\n  it(\"should emit submit with valid data\", async () => {\n    const wrapper = mount(UserForm);\n\n    await wrapper.find('[data-testid=\"username\"]').setValue(\"test\");\n    await wrapper.find(\"form\").trigger(\"submit\");\n\n    expect(wrapper.emitted(\"submit\")?.[0]).toEqual([{ username: \"test\" }]);\n  });\n\n  it(\"should show validation error on empty submit\", async () => {\n    const wrapper = mount(UserForm);\n    await wrapper.find(\"form\").trigger(\"submit\");\n    expect(wrapper.text()).toContain(\"Username cannot be empty\");\n  });\n});\n```\n\n### Store Test\n\n```typescript\ndescribe(\"authStore\", () => {\n  beforeEach(() => setActivePinia(createPinia()));\n\n  it(\"should login and set user\", async () => {\n    const store = useAuthStore();\n    await store.login({ username: \"admin\", password: \"pass\" });\n    expect(store.isLoggedIn).toBe(true);\n  });\n});\n```\n\n\n## Anti-pattern\n\n- Inline large sections of business logic in template-driven components\n- Used wide range watcher instead of computed\n- The event payload is unclear\n- Mix raw API calls directly into pure presentation components\n- ref and props have no type constraints\n- Use `watch` + manual assignment to simulate computed\n- Mixing unrelated responsibilities into a component\n- Use large-scale global style coverage to solve local UI problems\n- Push all status to Pinia store instead of managing it nearby\n- Put business coupling components in `components/`\n- Import directly from the deep path inside the feature, bypassing `index.ts`\n\n## Output checklist\n\n- [ ] The file structure is consistent with the project convention (pages/features/components are separated)\n- [ ] Use `<script setup lang=\"ts\">`\n- [ ] Props / Emits type complete\n- [ ] Whether explanatory comments should be given priority in Chinese and to the point\n- [ ] Reusable logic has been extracted to composable\n- [ ] Loading / Error / Empty status have been processed\n- [ ] Routing components are loaded using dynamic import\n- [ ] Reasonable status management plan (proximity principle)\n- [ ] API calls have type constraints and unified error handling\n- [ ] styles use scoped isolation\n- [ ] Key behaviors are covered by tests\n\nFile v2.9.0:skill-card.md\n\n## Description:\n\nGuides the design and review of Vue 3 and TypeScript project structure, components, composables, routing, state ownership, and implementation conventions.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[bovinphang](https://clawhub.ai/user/bovinphang)\n\n### License/Terms of Use:\n\nMIT\n\n## Use Case:\n\nDevelopers and engineers use this skill to design or review Vue 3 and TypeScript projects, including component boundaries, composables, routing, Pinia state, API errors, and testing conventions.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Project conventions or Chinese-language comment preferences may not match the adopting team's standards.\n\nMitigation: Compare guidance with existing repository conventions and confirm the team's comment-language preference before adopting changes.\n\n## Reference(s):\n\n- [ClawHub skill release](https://clawhub.ai/bovinphang/skills/fec-vue3-project-standard)\n- [Vue 3 project structure and component standards](references/vue3-project-structure.md)\n- [Vue 3 composables and routing patterns](references/vue3-composables-routing.md)\n- [Vue 3 state, API, and quality patterns](references/vue3-state-api-quality.md)\n- [Vue 3 performance patterns](references/vue3-performance-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [Guidance, Code, Configuration instructions]\n\n**Output Format:** [Markdown with Vue and TypeScript code examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Documentation-only guidance; does not independently run code or access private data.]\n\n## Skill Version(s):\n\n2.9.0 (source: ClawHub release, package.json, README.md)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v2.9.0:metadata.json\n\n{\n  \"id\": \"fec-vue3-project-standard\",\n  \"name\": \"Vue 3 project specifications\",\n  \"category\": \"project-standard\",\n  \"tags\": [\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"summary\": \"Organize Vue 3 and TypeScript SFCs, composables, routes, Pinia, and project boundaries.\",\n  \"version\": \"2.9.0\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"repository\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"platforms\": [\n    \"skills-cli\",\n    \"skillreg\",\n    \"claude-code\",\n    \"codex\",\n    \"cursor\",\n    \"opencode\",\n    \"openclaw\",\n    \"generic-skill-runtime\"\n  ],\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\",\n  \"source\": \"skills/fec-vue3-project-standard\",\n  \"references\": [\n    \"references/vue3-composables-routing.md\",\n    \"references/vue3-performance-patterns.md\",\n    \"references/vue3-project-structure.md\",\n    \"references/vue3-state-api-quality.md\"\n  ],\n  \"relations\": {\n    \"relatedSkills\": [\n      \"fec-typescript-project-standard\",\n      \"fec-state-management\",\n      \"fec-tailwind-design-system\",\n      \"fec-responsive-layout\",\n      \"fec-form-handling\",\n      \"fec-data-fetching\",\n      \"fec-component-testing\",\n      \"fec-e2e-testing\",\n      \"fec-accessibility-check\",\n      \"fec-security-review\",\n      \"fec-list-virtualization\",\n      \"fec-svg-animation\",\n      \"fec-canvas-threejs\"\n    ],\n    \"boundaryWorkflows\": [\n      \"Use specialty workflows for complex forms, state ownership, TypeScript contracts, server state, tests, accessibility, security, large lists, animation, or graphics.\",\n      \"Keep generic Vue component architecture, composables, and Pinia boundaries in the Vue project workflow.\"\n    ],\n    \"capabilityTags\": [\n      \"vue\",\n      \"project-standard\",\n      \"fec-architecture\"\n    ]\n  }\n}\n\nFile v2.9.0:package.json\n\n{\n  \"name\": \"@bovinphang/fec-vue3-project-standard\",\n  \"version\": \"2.9.0\",\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Bovin Phang\",\n    \"email\": \"pengbaowen@msn.com\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/bovinphang/frontend-craft\",\n    \"directory\": \"skills/fec-vue3-project-standard\"\n  },\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"agent-skill\",\n    \"frontend-craft\",\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"files\": [\n    \"SKILL.md\",\n    \"references\",\n    \"scripts\",\n    \"data\",\n    \"assets\",\n    \"metadata.json\",\n    \"README.md\",\n    \"LICENSE\"\n  ],\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n\nFile v2.9.0:LICENSE\n\nMIT License\r\n\r\nCopyright (c) 2025 Bovin Phang\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\n\nArchive v2.7.0: 10 files, 16522 bytes\n\nFiles: metadata.json (2278b), package.json (1213b), README.md (1709b), references/vue3-composables-routing.md (4790b), references/vue3-performance-patterns.md (566b), references/vue3-project-structure.md (8107b), references/vue3-state-api-quality.md (5965b), skill-card.md (2329b), SKILL.md (4111b), _meta.json (144b)\n\nFile v2.7.0:SKILL.md\n\n---\nname: fec-vue3-project-standard\ndescription: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\n---\n\n# Vue 3 项目规范\n\n适用于使用 Vue 3 + TypeScript 的仓库。\n\n## Purpose\n\n为 Vue 3 + TypeScript 项目提供工程结构、组件边界、Composables 和默认实现约定，确保约定式开发和类型安全。\n\n## Procedure\n\n1. 识别仓库已有 Vue 约定：目录、路由、Pinia、请求层、样式体系、组件库和测试框架。\n2. 划分页面、业务组件、通用组件、composables、stores、services 和 utils 的边界。\n3. 优先沿用 `<script setup lang=\"ts\">`、组合式 API 和仓库现有自动导入/模块出口约定。\n4. 输出时补齐状态归属、API 层、错误处理、样式隔离和专项 skill 分流。\n5. 页面和模块要有可恢复错误 UI；全局 `errorHandler`、`onErrorCaptured`、请求错误映射和路由错误页分工明确。\n6. Tailwind token/variant 或响应式布局需求应分流到对应专项 skill，避免把样式系统规则塞进 Vue 组件规范。\n7. 状态归属复杂时先做状态清单；DTO、公共 props、泛型 composable 或 `tsconfig` 边界复杂时，先使用 TypeScript 项目规范流程收敛跨框架类型契约。\n8. 设计可复用 composable 时明确输入是否支持 plain value、ref、computed 或 getter；测试 Vue 组件时覆盖 Pinia、Router、Teleport、Suspense 和 async setup 的常见边界。\n\n## 详细参考\n\n按需要加载更细的参考文件：\n\n- 项目目录、组件分层、组件规范、注释和 TypeScript：加载 [references/vue3-project-structure.md](references/vue3-project-structure.md)。\n- Composables、slots、Provide/Inject 和路由组织：加载 [references/vue3-composables-routing.md](references/vue3-composables-routing.md)。\n- Pinia、API 层、错误处理、指令、样式、测试、反模式和输出检查清单：加载 [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md)。\n- Vue 项目规范层面的轻量性能约定：加载 [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md)。\n\n## Constraints\n\n- 使用 `<script setup lang=\"ts\">`，禁止使用 Options API 新增组件\n- 组件文件规模宜约 **300 行**内；逾 **500 行**或复杂度过高须拆子组件与 Composables\n- Props / Emits 必须使用 TypeScript interface 定义，禁止使用 `any`\n- Composable 返回 `readonly` 引用，防止外部意外修改\n- 不要在 store 中存放 UI 临时状态（modal 开关、表单输入等）\n- 服务端数据优先用请求库管理，而非手动存入 Pinia\n- 避免在 `v-for` 中使用 `v-if`（提取为 computed 过滤）\n- 禁止直接从 feature 内部深层路径导入，绕过 `index.ts`\n- 不用全局错误处理吞掉组件内可恢复的 API、表单或权限错误。\n- 不把函数型参数误当 getter 自动调用；composable 参数若可能是回调，应避免使用 getter 型输入约定。\n- 不依赖快照作为 Vue 组件唯一断言；异步组件、Teleport 和 Pinia 场景要有用户可见行为断言。\n\n## Expected Output\n\n- 组件使用 `<script setup lang=\"ts\">`，Props / Emits 类型完整\n- 可复用逻辑已提取到 composable，返回 `readonly` 引用\n- Loading / Error / Empty / Data 状态均已处理\n- 路由组件使用动态 import 加载，状态管理符合就近原则\n- URL 状态、服务端状态、表单状态和 Pinia 全局状态边界明确\n- API 调用有类型约束和统一错误处理\n- 样式使用 scoped 隔离，关键行为有测试覆盖\n- 文件结构与项目约定一致（pages / features / components 分离）\n- 可复用 composable 的输入响应性、Pinia/Router 边界和异步组件测试策略已说明\n\nFile v2.7.0:README.md\n\n# Vue 3 项目规范\n\nFrontend Craft skill for Vue 3 项目规范.\n\n## Skill\n\n- ID: `fec-vue3-project-standard`\n- Category: `project-standard`\n- Version: `2.7.0`\n- Source: `skills/fec-vue3-project-standard/SKILL.md`\n\n## Description\n\nUse when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\n\n## Usage\n\nInstall or import this package with any skill runtime that understands the standard `SKILL.md` layout. The canonical source remains the Frontend Craft repository.\n\n## Packaged Files\n\n- [references/vue3-composables-routing.md](references/vue3-composables-routing.md)\n- [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md)\n- [references/vue3-project-structure.md](references/vue3-project-structure.md)\n- [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md)\n\n## Optional Related Packages\n\n- `@bovinphang/fec-typescript-project-standard`\n- `@bovinphang/fec-state-management`\n- `@bovinphang/fec-tailwind-design-system`\n- `@bovinphang/fec-responsive-layout`\n- `@bovinphang/fec-form-handling`\n- `@bovinphang/fec-data-fetching`\n- `@bovinphang/fec-component-testing`\n- `@bovinphang/fec-e2e-testing`\n- `@bovinphang/fec-accessibility-check`\n- `@bovinphang/fec-security-review`\n- `@bovinphang/fec-list-virtualization`\n- `@bovinphang/fec-svg-animation`\n- `@bovinphang/fec-canvas-threejs`\n\n## License\n\nMIT\n\nFile v2.7.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b0nh7hvj1pffeqc8y0dqwwh83m726\",\n  \"slug\": \"fec-vue3-project-standard\",\n  \"version\": \"2.7.0\",\n  \"publishedAt\": 1781144123503\n}\n\nFile v2.7.0:references/vue3-composables-routing.md\n\n# Vue 3 composables and routing patterns\n\n## Composables 规范\n\n### 设计原则\n\n- 以 `use` 前缀命名\n- 返回值使用对象，明确标注类型\n- 内部处理 loading / error / data 三态\n- 支持参数响应式（接受 `Ref` 或 getter）\n- 库级 composable 要明确参数是否支持普通值、`Ref`、`computed` 或 getter，并在副作用内部解析最新值\n\n```typescript\nexport function useUserList(params: MaybeRef<QueryParams>) {\n  const data = ref<User[]>([]);\n  const loading = ref(false);\n  const error = ref<Error | null>(null);\n\n  async function fetch() {\n    loading.value = true;\n    error.value = null;\n    try {\n      const res = await getUserList(toValue(params));\n      data.value = res.list;\n    } catch (e) {\n      error.value = e as Error;\n    } finally {\n      loading.value = false;\n    }\n  }\n\n  watchEffect(() => {\n    fetch();\n  });\n\n  return {\n    data: readonly(data),\n    loading: readonly(loading),\n    error: readonly(error),\n    refetch: fetch,\n  };\n}\n```\n\n### Composable 使用原则\n\n- 返回 `readonly` 引用防止外部意外修改\n- 数据请求场景优先使用 VueQuery / VueUse 等库（如项目已引入）\n- `onUnmounted` 中清理定时器、事件监听等副作用\n- 避免在 composable 中直接操作 DOM\n- 只读输入可接受普通值、ref、computed 或 getter；需要双向写入的输入只接受可写 ref 或明确的 setter。\n- 如果参数本身是回调、比较器或 predicate，不要把它设计成 getter 型输入，否则解析时可能误调用业务函数。\n\n### Vue Router / Pinia / 测试常见边界\n\n- 路由参数变化不会重新创建同一个路由组件；依赖 `route.params` 的数据要 watch 明确字段，并处理取消和竞态。\n- 导航守卫中避免旧式 `next()` 多分支重复调用；优先返回 `false`、重定向对象或抛出可处理错误。\n- Pinia store 解构会丢失响应性时使用 `storeToRefs`；setup store 必须返回需要被外部追踪的 state、getter 和 action。\n- UI 临时状态、表单输入、弹窗开关不进入全局 store；URL 查询、服务端缓存和本地组件状态先各归其位。\n- Vue Test Utils 测试优先断言用户可见行为，不把快照作为唯一证明；异步更新使用 `await`、`flushPromises` 或框架推荐的等待方式。\n- 测试使用 Pinia、Router、Teleport、Suspense、async setup 或 `defineAsyncComponent` 时，在测试夹具中显式安装插件、挂载目标容器并等待异步稳定。\n\n## Slots 与 Provide/Inject\n\n### Slots\n\n- 用 `<slot>` 实现组件组合，而非过多 props\n- 具名 slot 用于明确的布局区域\n- 作用域 slot 传递数据给父组件自定义渲染\n\n```vue\n<template>\n  <div class=\"card\">\n    <div class=\"card-header\">\n      <slot name=\"header\">{{ title }}</slot>\n    </div>\n    <div class=\"card-body\">\n      <slot :data=\"processedData\" :loading=\"loading\" />\n    </div>\n  </div>\n</template>\n```\n\n### Provide/Inject\n\n- 用于跨多层级的上下文共享（主题、配置、权限）\n- 提供 InjectionKey 保证类型安全\n- 不要用 provide/inject 替代 props 传递直接父子数据\n\n```typescript\n// keys.ts\nexport const ThemeKey: InjectionKey<Ref<Theme>> = Symbol(\"theme\");\n\n// Provider.vue\nprovide(ThemeKey, theme);\n\n// Consumer.vue\nconst theme = inject(ThemeKey);\n```\n\n## 路由规范\n\n### 路由组织\n\n```typescript\n// app/router.ts\nconst routes: RouteRecordRaw[] = [\n  {\n    path: \"/\",\n    component: MainLayout,\n    children: [\n      {\n        path: \"\",\n        name: \"Dashboard\",\n        component: () => import(\"@/pages/Dashboard/DashboardPage.vue\"),\n      },\n      {\n        path: \"users\",\n        name: \"UserList\",\n        component: () => import(\"@/pages/UserList/UserListPage.vue\"),\n      },\n      {\n        path: \"users/:id\",\n        name: \"UserDetail\",\n        component: () => import(\"@/pages/UserDetail/UserDetailPage.vue\"),\n      },\n      {\n        path: \"settings\",\n        name: \"Settings\",\n        component: () => import(\"@/pages/Settings/SettingsPage.vue\"),\n      },\n    ],\n  },\n  {\n    path: \"/login\",\n    name: \"Login\",\n    component: () => import(\"@/pages/Login/LoginPage.vue\"),\n  },\n  {\n    path: \"/:pathMatch(.*)*\",\n    name: \"NotFound\",\n    component: () => import(\"@/pages/NotFound.vue\"),\n  },\n];\n```\n\n### 路由原则\n\n- 路由配置集中管理，每个路由必须有 `name`\n- 页面组件使用动态 `import()` 按需加载\n- 权限控制使用路由守卫（`beforeEach`），而非在每个页面内判断\n- URL 参数（分页、筛选、排序）与路由状态同步\n\n```typescript\n// 导航守卫\nrouter.beforeEach((to) => {\n  const authStore = useAuthStore();\n  if (to.meta.requiresAuth && !authStore.isLoggedIn) {\n    return { name: \"Login\", query: { redirect: to.fullPath } };\n  }\n});\n```\n\nFile v2.7.0:references/vue3-performance-patterns.md\n\n# Vue 3 performance patterns\n\nThis file keeps lightweight Vue project-standard performance guidance. Use the frontend performance workflow when the task needs metrics, traces, profiles, bundle analysis, network evidence, or a formal performance report.\n\n## 性能\n\n- 使用 `shallowRef` / `shallowReactive` 优化大型对象\n- 大列表使用虚拟滚动\n- 避免在 `v-for` 中使用 `v-if`（提取为 computed 过滤）\n- 使用 `defineAsyncComponent` 懒加载重型组件\n- `v-for` 必须有稳定的 `:key`\n- 路由组件使用动态 `import()` 按需加载\n\nFile v2.7.0:references/vue3-project-structure.md\n\n# Vue 3 project structure and component standards\n\n## 项目结构\n\n以下为中大型 Vue 3 项目的业界最佳实践结构，按项目实际情况裁剪：\n\n```\nsrc/\n├── app/                        # 应用入口与全局配置\n│   ├── App.vue                 # 根组件\n│   ├── main.ts                 # 应用启动入口\n│   └── router.ts               # 路由实例与配置\n│\n├── pages/                      # 页面组件（与路由一一对应）\n│   ├── Dashboard/\n│   │   ├── DashboardPage.vue\n│   │   ├── components/         # 页面私有组件\n│   │   └── composables/        # 页面私有 composables\n│   ├── UserList/\n│   └── Settings/\n│\n├── layouts/                    # 布局组件\n│   ├── MainLayout.vue          # 主布局（侧边栏 + 顶栏 + 内容区）\n│   ├── AuthLayout.vue          # 登录/注册页布局\n│   └── BlankLayout.vue         # 空白布局（错误页等）\n│\n├── features/                   # 功能模块（按业务领域划分）\n│   ├── auth/\n│   │   ├── components/         # 模块组件\n│   │   ├── composables/        # 模块 composables\n│   │   ├── api.ts              # 模块 API 调用\n│   │   ├── types.ts            # 模块类型定义\n│   │   ├── constants.ts        # 模块常量\n│   │   └── index.ts            # 模块公开导出\n│   └── order/\n│\n├── components/                 # 全局共享 UI 组件\n│   ├── AppButton/\n│   │   ├── AppButton.vue\n│   │   └── __tests__/\n│   ├── AppModal/\n│   ├── AppForm/\n│   └── AppErrorBoundary/\n│\n├── composables/                # 全局共享 composables\n│   ├── useAuth.ts\n│   ├── useDebounce.ts\n│   └── useMediaQuery.ts\n│\n├── services/                   # API 基础层\n│   ├── request.ts              # Axios/fetch 实例与拦截器\n│   └── endpoints/              # API 端点定义（如按领域拆分）\n│\n├── stores/                     # Pinia 状态管理\n│   ├── authStore.ts\n│   └── uiStore.ts\n│\n├── locales/                    # 国际化语言包\n│   ├── zh-CN.json              # 中文\n│   ├── en-US.json              # 英文\n│   └── index.ts                # i18n 实例初始化（vue-i18n）\n│\n├── assets/                     # 静态资源\n│   ├── images/                 # 图片（PNG、JPG、WebP）\n│   ├── icons/                  # SVG 图标\n│   └── fonts/                  # 自定义字体\n│\n├── config/                     # 应用配置\n│   ├── env.ts                  # 环境变量类型化封装\n│   └── features.ts             # Feature Flags 管理\n│\n├── types/                      # 全局共享类型\n│   ├── api.ts                  # API 响应/请求通用类型\n│   ├── models.ts               # 业务实体类型\n│   └── global.d.ts             # 全局类型扩展（组件类型、模块声明等）\n│\n├── utils/                      # 纯工具函数\n│   ├── format.ts               # 日期、数字、货币格式化\n│   ├── validators.ts           # 表单校验规则\n│   └── storage.ts              # LocalStorage / SessionStorage 封装\n│\n├── directives/                 # 自定义指令\n│   ├── vPermission.ts          # 权限指令\n│   └── vClickOutside.ts        # 点击外部关闭\n│\n├── plugins/                    # Vue 插件注册\n│   ├── i18n.ts                 # vue-i18n 插件配置\n│   └── index.ts                # 插件统一注册入口\n│\n├── styles/                     # 全局样式与主题\n│   ├── global.css              # 全局基础样式（reset / normalize）\n│   ├── variables.css           # CSS 变量（颜色、间距、字号）\n│   ├── breakpoints.ts          # 响应式断点常量\n│   └── themes/                 # 主题定义\n│       ├── light.css           # 亮色主题变量\n│       ├── dark.css            # 暗色主题变量\n│       └── index.ts            # 主题切换逻辑\n│\n└── constants/                  # 全局常量\n    ├── routes.ts               # 路由路径常量\n    └── config.ts               # 业务常量（分页大小、超时时间等）\n```\n\n### 关键原则\n\n- `pages/` 做路由映射和布局组合，不放业务逻辑\n- `layouts/` 定义页面骨架（侧边栏、顶栏、面包屑），由路由配置的 `component` 引用\n- `features/` 按业务领域划分，模块内自包含（components + composables + api + types）\n- `components/` 仅放无业务耦合的通用组件，可跨项目复用\n- `composables/` 仅放通用逻辑（防抖、媒体查询等），业务 composables 放到对应 feature 中\n- `locales/` 存放语言包 JSON 文件，模板中使用 `$t('key')` 而非硬编码文案\n- `assets/` 存放静态资源，图标优先使用 SVG，图片优先使用 WebP/AVIF\n- `config/` 封装环境变量和 Feature Flags，禁止组件中直接读取 `import.meta.env`\n- `styles/themes/` 通过 CSS 变量实现主题切换，组件中引用变量而非硬编码颜色\n- 每个模块通过 `index.ts` 管控公开 API，避免深层路径导入\n\n## 组件设计规范\n\n- 使用 `<script setup lang=\"ts\">`\n- 明确使用 `defineProps` / `defineEmits` 并附带类型\n- 可复用逻辑优先提取到 composables\n- 保持 template 可读，避免过深条件嵌套\n- 优先使用计算属性，而不是重复维护状态\n- 避免构建大型单体组件；**单文件规模**见 `templates/shared/rules/fec-vue.md`「**组件文件规模**」（约 300 行内为佳，逾 500 行或复杂度过高拆子组件与 Composables）\n- 优先使用强类型的 props、emits 和暴露方法\n- 遵循仓库的文件与目录命名规范\n- 优先复用现有 UI 组件和 Token\n\n### 组件分层\n\n```\n页面组件 (Pages)          → 路由映射、布局组合\n  └── 容器组件 (Containers)  → 数据获取、状态编排\n       └── 业务组件 (Features) → 领域逻辑展示\n            └── 通用组件 (UI)   → 纯展示，无业务耦合\n```\n\n## 注释规范\n\n- **优先使用中文**：解释「为什么这样做」、业务约束、边界情况、非显而易见的权衡时，优先用中文撰写注释，便于团队与业务方阅读。\n- **与代码语言一致时的例外**：对接第三方协议字段名、HTTP 头、规范中的英文术语时，注释里可保留英文专有名词，必要时中英文并列说明。\n- **少而精**：能通过清晰命名与类型表达清楚的逻辑不写废话注释；复杂分支、临时兼容、性能取舍必须写清意图。\n- **公开 API**：composable 或模块的对外契约可用 JSDoc（`@param` / `@returns` / `@example`），说明用中文即可，除非仓库统一要求英文。\n\n## TypeScript 规范\n\n通用 TypeScript 工程规则由 `fec-typescript-project-standard` 负责，包括 `tsconfig`、strictness、DTO / view model 边界、`unknown` 收窄、public API 类型、声明产物和类型测试。\n\nVue 规范只补充 SFC、Props / Emits、暴露方法、Provide / Inject 和 composable 响应性类型；复杂类型建模或跨框架类型契约先分流到 `fec-typescript-project-standard`。\n\n### Vue 3 项目补充约定\n\n```vue\n<script setup lang=\"ts\">\ninterface Props {\n  title: string;\n  items: Item[];\n  loading?: boolean;\n}\n\ninterface Emits {\n  (e: \"select\", item: Item): void;\n  (e: \"delete\", id: string): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  loading: false,\n});\n\nconst emit = defineEmits<Emits>();\n</script>\n```\n\n- Props 和 Emits 使用 TypeScript interface 定义\n- 使用 `withDefaults` 设置默认值\n- `defineExpose` 暴露的方法需有类型约束\n\nFile v2.7.0:references/vue3-state-api-quality.md\n\n# Vue 3 state, API, and quality patterns\n\n## 状态管理（Pinia）\n\n| 状态类型           | 推荐方案                      |\n| ------------------ | ----------------------------- |\n| 组件内临时 UI 状态 | `ref` / `reactive`            |\n| 跨组件共享业务状态 | Pinia store                   |\n| 服务端数据缓存     | VueQuery / 自定义 composable  |\n| URL 驱动状态       | 路由参数 / `useRoute().query` |\n| 表单状态           | VeeValidate / FormKit         |\n\n### Pinia Store 规范\n\n使用 Composition API 风格（`setup store`）：\n\n```typescript\n// stores/authStore.ts\nexport const useAuthStore = defineStore(\"auth\", () => {\n  const user = ref<User | null>(null);\n  const token = ref<string | null>(localStorage.getItem(\"token\"));\n\n  const isLoggedIn = computed(() => !!token.value);\n\n  async function login(credentials: LoginParams) {\n    const res = await authApi.login(credentials);\n    user.value = res.user;\n    token.value = res.token;\n    localStorage.setItem(\"token\", res.token);\n  }\n\n  function logout() {\n    user.value = null;\n    token.value = null;\n    localStorage.removeItem(\"token\");\n  }\n\n  return { user: readonly(user), isLoggedIn, login, logout };\n});\n```\n\n### Store 原则\n\n- 每个 store 职责单一，按领域拆分\n- 对外暴露 `readonly` 的状态，通过 action 修改\n- 不要在 store 中存放 UI 临时状态（modal 开关、表单输入等）\n- 服务端数据优先用请求库管理，而非手动存入 store\n\n## API 层规范\n\n### 请求实例\n\n```typescript\n// services/request.ts\nconst request = axios.create({\n  baseURL: import.meta.env.VITE_API_BASE_URL,\n  timeout: 10000,\n});\n\nrequest.interceptors.request.use((config) => {\n  const authStore = useAuthStore();\n  if (authStore.token) {\n    config.headers.Authorization = `Bearer ${authStore.token}`;\n  }\n  return config;\n});\n\nrequest.interceptors.response.use(\n  (res) => res.data,\n  (error) => {\n    if (error.response?.status === 401) {\n      const authStore = useAuthStore();\n      authStore.logout();\n      router.push({ name: \"Login\" });\n    }\n    return Promise.reject(normalizeError(error));\n  },\n);\n```\n\n### API 函数\n\n```typescript\n// features/user/api.ts\nexport function getUserList(\n  params: UserQueryParams,\n): Promise<PageResult<User>> {\n  return request.get(\"/users\", { params });\n}\n\nexport function updateUser(id: string, data: UpdateUserDTO): Promise<User> {\n  return request.put(`/users/${id}`, data);\n}\n```\n\n- API 函数按 feature 组织，而非全部堆在一个文件\n- 请求参数和响应都有类型约束\n- 拦截器统一处理认证、错误格式化\n\n## 错误处理\n\n### 全局错误捕获\n\n```typescript\n// main.ts\napp.config.errorHandler = (err, instance, info) => {\n  reportError(err, { component: instance?.$options.name, info });\n};\n```\n\n### 组件级错误\n\n- 使用 `onErrorCaptured` 在父组件中捕获子组件错误\n- 数据请求失败需有用户可见的提示和重试机制\n- 不要吞掉错误（空 catch 块）\n\n## 自定义指令\n\n```typescript\n// directives/vPermission.ts\nexport const vPermission: Directive<HTMLElement, string> = {\n  mounted(el, binding) {\n    const authStore = useAuthStore();\n    if (!authStore.hasPermission(binding.value)) {\n      el.parentNode?.removeChild(el);\n    }\n  },\n};\n```\n\n- 指令只处理 DOM 层面的操作\n- 业务逻辑不要放在指令中\n- 需要响应式更新时实现 `updated` 钩子\n\n## 样式规范\n\n- 使用 `<style scoped>` 隔离样式\n- 深度选择器使用 `:deep()` 而非已废弃的 `::v-deep`\n- 与项目现有样式体系保持一致\n- 动态样式优先使用 `:class` / `:style` 绑定\n- 复杂主题切换使用 CSS 变量\n- 主题/全局变量通过 CSS 变量或 Token 管理\n\n## 测试规范\n\n### 必须测试\n\n- 核心交互行为（点击、输入、提交）\n- 条件渲染（loading / error / empty / data）\n- Emits 的触发和 payload\n- 关键 composables 的返回值\n- Pinia store 的 action 和 getter\n\n### 测试风格\n\n```typescript\ndescribe(\"UserForm\", () => {\n  it(\"should emit submit with valid data\", async () => {\n    const wrapper = mount(UserForm);\n\n    await wrapper.find('[data-testid=\"username\"]').setValue(\"test\");\n    await wrapper.find(\"form\").trigger(\"submit\");\n\n    expect(wrapper.emitted(\"submit\")?.[0]).toEqual([{ username: \"test\" }]);\n  });\n\n  it(\"should show validation error on empty submit\", async () => {\n    const wrapper = mount(UserForm);\n    await wrapper.find(\"form\").trigger(\"submit\");\n    expect(wrapper.text()).toContain(\"用户名不能为空\");\n  });\n});\n```\n\n### Store 测试\n\n```typescript\ndescribe(\"authStore\", () => {\n  beforeEach(() => setActivePinia(createPinia()));\n\n  it(\"should login and set user\", async () => {\n    const store = useAuthStore();\n    await store.login({ username: \"admin\", password: \"pass\" });\n    expect(store.isLoggedIn).toBe(true);\n  });\n});\n```\n\n\n## 反模式\n\n- 在模板驱动组件中内联大段业务逻辑\n- 本该用 computed 却使用大范围 watcher\n- 事件 payload 不明确\n- 在纯展示组件中直接混入原始 API 调用\n- ref 和 props 没有类型约束\n- 用 `watch` + 手动赋值模拟 computed\n- 在一个组件中混入无关职责\n- 用大范围全局样式覆盖去解决局部 UI 问题\n- 将所有状态推入 Pinia store，而非就近管理\n- 在 `components/` 中放业务耦合组件\n- 直接从 feature 内部深层路径导入，绕过 `index.ts`\n\n## 输出检查清单\n\n- [ ] 文件结构与项目约定一致（pages / features / components 分离）\n- [ ] 使用 `<script setup lang=\"ts\">`\n- [ ] Props / Emits 类型完整\n- [ ] 解释性注释是否优先使用中文且点到要害\n- [ ] 可复用逻辑已提取到 composable\n- [ ] Loading / Error / Empty 状态均已处理\n- [ ] 路由组件使用动态 import 加载\n- [ ] 状态管理方案合理（就近原则）\n- [ ] API 调用有类型约束和统一错误处理\n- [ ] 样式使用 scoped 隔离\n- [ ] 关键行为有测试覆盖\n\nFile v2.7.0:skill-card.md\n\n## Description:\n\nThis skill guides Vue 3 + TypeScript project design and review across project structure, component boundaries, composables, routing, Pinia ownership, API and error handling, styling defaults, directives, and repository-wide conventions.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[bovinphang](https://clawhub.ai/user/bovinphang)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineering teams use this skill to design or review Vue 3 + TypeScript applications for consistent folder structure, component layering, composable boundaries, route organization, Pinia state ownership, API/error handling, styling isolation, and test expectations.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: The guidance includes a bearer-token localStorage example that readers could copy as a default authentication pattern.\n\nMitigation: Review authentication guidance before use and prefer an explicit session-security design, such as HttpOnly Secure cookies or short-lived in-memory access tokens, for applications that handle sensitive sessions.\n\n## Reference(s):\n\n- [Vue3 Project Standard release page](https://clawhub.ai/bovinphang/skills/fec-vue3-project-standard)\n- [Vue 3 project structure and component standards](references/vue3-project-structure.md)\n- [Vue 3 composables and routing patterns](references/vue3-composables-routing.md)\n- [Vue 3 state, API, and quality patterns](references/vue3-state-api-quality.md)\n- [Vue 3 performance patterns](references/vue3-performance-patterns.md)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, markdown, code, configuration]\n\n**Output Format:** [Markdown guidance with Vue 3 and TypeScript code examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Outputs may include review checklists, project-structure recommendations, and implementation guidance tailored to the target repository.]\n\n## Skill Version(s):\n\n2.7.0 (source: server release metadata, artifact metadata.json, package.json, and README)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nFile v2.7.0:metadata.json\n\n{\n  \"id\": \"fec-vue3-project-standard\",\n  \"name\": \"Vue 3 项目规范\",\n  \"category\": \"project-standard\",\n  \"tags\": [\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"summary\": \"Frontend Craft skill for Vue 3 项目规范.\",\n  \"version\": \"2.7.0\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"repository\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"platforms\": [\n    \"skills-cli\",\n    \"skillreg\",\n    \"claude-code\",\n    \"codex\",\n    \"cursor\",\n    \"opencode\",\n    \"openclaw\",\n    \"generic-skill-runtime\"\n  ],\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\",\n  \"source\": \"skills/fec-vue3-project-standard\",\n  \"references\": [\n    \"references/vue3-composables-routing.md\",\n    \"references/vue3-performance-patterns.md\",\n    \"references/vue3-project-structure.md\",\n    \"references/vue3-state-api-quality.md\"\n  ],\n  \"relations\": {\n    \"relatedSkills\": [\n      \"fec-typescript-project-standard\",\n      \"fec-state-management\",\n      \"fec-tailwind-design-system\",\n      \"fec-responsive-layout\",\n      \"fec-form-handling\",\n      \"fec-data-fetching\",\n      \"fec-component-testing\",\n      \"fec-e2e-testing\",\n      \"fec-accessibility-check\",\n      \"fec-security-review\",\n      \"fec-list-virtualization\",\n      \"fec-svg-animation\",\n      \"fec-canvas-threejs\"\n    ],\n    \"boundaryWorkflows\": [\n      \"Use specialty workflows for complex forms, state ownership, TypeScript contracts, server state, tests, accessibility, security, large lists, animation, or graphics.\",\n      \"Keep generic Vue component architecture, composables, and Pinia boundaries in the Vue project workflow.\"\n    ],\n    \"capabilityTags\": [\n      \"vue\",\n      \"project-standard\",\n      \"fec-architecture\"\n    ]\n  }\n}\n\nFile v2.7.0:package.json\n\n{\n  \"name\": \"@bovinphang/fec-vue3-project-standard\",\n  \"version\": \"2.7.0\",\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Bovin Phang\",\n    \"email\": \"pengbaowen@msn.com\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/bovinphang/frontend-craft\",\n    \"directory\": \"skills/fec-vue3-project-standard\"\n  },\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"agent-skill\",\n    \"frontend-craft\",\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"files\": [\n    \"SKILL.md\",\n    \"references\",\n    \"scripts\",\n    \"data\",\n    \"assets\",\n    \"metadata.json\",\n    \"README.md\",\n    \"LICENSE\"\n  ],\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}\n\nArchive v2.4.0: 7 files, 13210 bytes\n\nFiles: metadata.json (2134b), package.json (1203b), README.md (1505b), references/vue3-project-details.md (17519b), skill-card.md (2058b), SKILL.md (3119b), _meta.json (144b)\n\nFile v2.4.0:SKILL.md\n\n---\nname: fec-vue3-project-standard\ndescription: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\n---\n\n# Vue 3 项目规范\n\n适用于使用 Vue 3 + TypeScript 的仓库。\n\n## Purpose\n\n为 Vue 3 + TypeScript 项目提供工程结构、组件边界、Composables 和默认实现约定，确保约定式开发和类型安全。\n\n## Procedure\n\n1. 识别仓库已有 Vue 约定：目录、路由、Pinia、请求层、样式体系、组件库和测试框架。\n2. 划分页面、业务组件、通用组件、composables、stores、services 和 utils 的边界。\n3. 优先沿用 `<script setup lang=\"ts\">`、组合式 API 和仓库现有自动导入/模块出口约定。\n4. 输出时补齐状态归属、API 层、错误处理、样式隔离和专项 skill 分流。\n5. 页面和模块要有可恢复错误 UI；全局 `errorHandler`、`onErrorCaptured`、请求错误映射和路由错误页分工明确。\n6. Tailwind token/variant 或响应式布局需求应分流到对应专项 skill，避免把样式系统规则塞进 Vue 组件规范。\n5. 状态归属复杂时先做状态清单；DTO、公共 props 或泛型 composable 复杂时先收敛 TypeScript 类型契约。\n\n## Detailed References\n\n需要具体 Vue 3 项目结构、组件模式、Composables、slots、Provide/Inject、路由、Pinia、API 层、错误处理、指令、样式、TypeScript、测试、性能或审查清单时，加载 [references/vue3-project-details.md](references/vue3-project-details.md)。\n\n## Constraints\n\n- 使用 `<script setup lang=\"ts\">`，禁止使用 Options API 新增组件\n- 组件文件规模宜约 **300 行**内；逾 **500 行**或复杂度过高须拆子组件与 Composables\n- Props / Emits 必须使用 TypeScript interface 定义，禁止使用 `any`\n- Composable 返回 `readonly` 引用，防止外部意外修改\n- 不要在 store 中存放 UI 临时状态（modal 开关、表单输入等）\n- 服务端数据优先用请求库管理，而非手动存入 Pinia\n- 避免在 `v-for` 中使用 `v-if`（提取为 computed 过滤）\n- 禁止直接从 feature 内部深层路径导入，绕过 `index.ts`\n- 不用全局错误处理吞掉组件内可恢复的 API、表单或权限错误。\n\n## Expected Output\n\n- 组件使用 `<script setup lang=\"ts\">`，Props / Emits 类型完整\n- 可复用逻辑已提取到 composable，返回 `readonly` 引用\n- Loading / Error / Empty / Data 状态均已处理\n- 路由组件使用动态 import 加载，状态管理符合就近原则\n- URL 状态、服务端状态、表单状态和 Pinia 全局状态边界明确\n- API 调用有类型约束和统一错误处理\n- 样式使用 scoped 隔离，关键行为有测试覆盖\n- 文件结构与项目约定一致（pages / features / components 分离）\n\nFile v2.4.0:README.md\n\n# Vue 3 项目规范\n\nFrontend Craft skill for Vue 3 项目规范.\n\n## Skill\n\n- ID: `fec-vue3-project-standard`\n- Category: `project-standard`\n- Version: `2.4.0`\n- Source: `skills/fec-vue3-project-standard/SKILL.md`\n\n## Description\n\nUse when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\n\n## Usage\n\nInstall or import this package with any skill runtime that understands the standard `SKILL.md` layout. The canonical source remains the Frontend Craft repository.\n\n## Packaged Files\n\n- [references/vue3-project-details.md](references/vue3-project-details.md)\n\n## Optional Related Packages\n\n- `@frontend-craft/fec-typescript-type-safety`\n- `@frontend-craft/fec-state-management`\n- `@frontend-craft/fec-tailwind-design-system`\n- `@frontend-craft/fec-responsive-layout`\n- `@frontend-craft/fec-form-handling`\n- `@frontend-craft/fec-data-fetching`\n- `@frontend-craft/fec-component-testing`\n- `@frontend-craft/fec-e2e-testing`\n- `@frontend-craft/fec-accessibility-check`\n- `@frontend-craft/fec-security-review`\n- `@frontend-craft/fec-list-virtualization`\n- `@frontend-craft/fec-svg-animation`\n- `@frontend-craft/fec-canvas-threejs`\n\n## License\n\nMIT\n\nFile v2.4.0:_meta.json\n\n{\n  \"ownerId\": \"kn7b0nh7hvj1pffeqc8y0dqwwh83m726\",\n  \"slug\": \"fec-vue3-project-standard\",\n  \"version\": \"2.4.0\",\n  \"publishedAt\": 1780306028848\n}\n\nFile v2.4.0:references/vue3-project-details.md\n\n# Vue 3 项目规范详解\n\n## 项目结构\n\n以下为中大型 Vue 3 项目的业界最佳实践结构，按项目实际情况裁剪：\n\n```\nsrc/\n├── app/                        # 应用入口与全局配置\n│   ├── App.vue                 # 根组件\n│   ├── main.ts                 # 应用启动入口\n│   └── router.ts               # 路由实例与配置\n│\n├── pages/                      # 页面组件（与路由一一对应）\n│   ├── Dashboard/\n│   │   ├── DashboardPage.vue\n│   │   ├── components/         # 页面私有组件\n│   │   └── composables/        # 页面私有 composables\n│   ├── UserList/\n│   └── Settings/\n│\n├── layouts/                    # 布局组件\n│   ├── MainLayout.vue          # 主布局（侧边栏 + 顶栏 + 内容区）\n│   ├── AuthLayout.vue          # 登录/注册页布局\n│   └── BlankLayout.vue         # 空白布局（错误页等）\n│\n├── features/                   # 功能模块（按业务领域划分）\n│   ├── auth/\n│   │   ├── components/         # 模块组件\n│   │   ├── composables/        # 模块 composables\n│   │   ├── api.ts              # 模块 API 调用\n│   │   ├── types.ts            # 模块类型定义\n│   │   ├── constants.ts        # 模块常量\n│   │   └── index.ts            # 模块公开导出\n│   └── order/\n│\n├── components/                 # 全局共享 UI 组件\n│   ├── AppButton/\n│   │   ├── AppButton.vue\n│   │   └── __tests__/\n│   ├── AppModal/\n│   ├── AppForm/\n│   └── AppErrorBoundary/\n│\n├── composables/                # 全局共享 composables\n│   ├── useAuth.ts\n│   ├── useDebounce.ts\n│   └── useMediaQuery.ts\n│\n├── services/                   # API 基础层\n│   ├── request.ts              # Axios/fetch 实例与拦截器\n│   └── endpoints/              # API 端点定义（如按领域拆分）\n│\n├── stores/                     # Pinia 状态管理\n│   ├── authStore.ts\n│   └── uiStore.ts\n│\n├── locales/                    # 国际化语言包\n│   ├── zh-CN.json              # 中文\n│   ├── en-US.json              # 英文\n│   └── index.ts                # i18n 实例初始化（vue-i18n）\n│\n├── assets/                     # 静态资源\n│   ├── images/                 # 图片（PNG、JPG、WebP）\n│   ├── icons/                  # SVG 图标\n│   └── fonts/                  # 自定义字体\n│\n├── config/                     # 应用配置\n│   ├── env.ts                  # 环境变量类型化封装\n│   └── features.ts             # Feature Flags 管理\n│\n├── types/                      # 全局共享类型\n│   ├── api.ts                  # API 响应/请求通用类型\n│   ├── models.ts               # 业务实体类型\n│   └── global.d.ts             # 全局类型扩展（组件类型、模块声明等）\n│\n├── utils/                      # 纯工具函数\n│   ├── format.ts               # 日期、数字、货币格式化\n│   ├── validators.ts           # 表单校验规则\n│   └── storage.ts              # LocalStorage / SessionStorage 封装\n│\n├── directives/                 # 自定义指令\n│   ├── vPermission.ts          # 权限指令\n│   └── vClickOutside.ts        # 点击外部关闭\n│\n├── plugins/                    # Vue 插件注册\n│   ├── i18n.ts                 # vue-i18n 插件配置\n│   └── index.ts                # 插件统一注册入口\n│\n├── styles/                     # 全局样式与主题\n│   ├── global.css              # 全局基础样式（reset / normalize）\n│   ├── variables.css           # CSS 变量（颜色、间距、字号）\n│   ├── breakpoints.ts          # 响应式断点常量\n│   └── themes/                 # 主题定义\n│       ├── light.css           # 亮色主题变量\n│       ├── dark.css            # 暗色主题变量\n│       └── index.ts            # 主题切换逻辑\n│\n└── constants/                  # 全局常量\n    ├── routes.ts               # 路由路径常量\n    └── config.ts               # 业务常量（分页大小、超时时间等）\n```\n\n### 关键原则\n\n- `pages/` 做路由映射和布局组合，不放业务逻辑\n- `layouts/` 定义页面骨架（侧边栏、顶栏、面包屑），由路由配置的 `component` 引用\n- `features/` 按业务领域划分，模块内自包含（components + composables + api + types）\n- `components/` 仅放无业务耦合的通用组件，可跨项目复用\n- `composables/` 仅放通用逻辑（防抖、媒体查询等），业务 composables 放到对应 feature 中\n- `locales/` 存放语言包 JSON 文件，模板中使用 `$t('key')` 而非硬编码文案\n- `assets/` 存放静态资源，图标优先使用 SVG，图片优先使用 WebP/AVIF\n- `config/` 封装环境变量和 Feature Flags，禁止组件中直接读取 `import.meta.env`\n- `styles/themes/` 通过 CSS 变量实现主题切换，组件中引用变量而非硬编码颜色\n- 每个模块通过 `index.ts` 管控公开 API，避免深层路径导入\n\n## 组件设计规范\n\n- 使用 `<script setup lang=\"ts\">`\n- 明确使用 `defineProps` / `defineEmits` 并附带类型\n- 可复用逻辑优先提取到 composables\n- 保持 template 可读，避免过深条件嵌套\n- 优先使用计算属性，而不是重复维护状态\n- 避免构建大型单体组件；**单文件规模**见 `templates/shared/rules/fec-vue.md`「**组件文件规模**」（约 300 行内为佳，逾 500 行或复杂度过高拆子组件与 Composables）\n- 优先使用强类型的 props、emits 和暴露方法\n- 遵循仓库的文件与目录命名规范\n- 优先复用现有 UI 组件和 Token\n\n### 组件分层\n\n```\n页面组件 (Pages)          → 路由映射、布局组合\n  └── 容器组件 (Containers)  → 数据获取、状态编排\n       └── 业务组件 (Features) → 领域逻辑展示\n            └── 通用组件 (UI)   → 纯展示，无业务耦合\n```\n\n## 注释规范\n\n- **优先使用中文**：解释「为什么这样做」、业务约束、边界情况、非显而易见的权衡时，优先用中文撰写注释，便于团队与业务方阅读。\n- **与代码语言一致时的例外**：对接第三方协议字段名、HTTP 头、规范中的英文术语时，注释里可保留英文专有名词，必要时中英文并列说明。\n- **少而精**：能通过清晰命名与类型表达清楚的逻辑不写废话注释；复杂分支、临时兼容、性能取舍必须写清意图。\n- **公开 API**：composable 或模块的对外契约可用 JSDoc（`@param` / `@returns` / `@example`），说明用中文即可，除非仓库统一要求英文。\n\n## TypeScript 规范\n\n通用 TypeScript / JavaScript 约定见插件模板 **`templates/shared/rules/fec-typescript.md`**（初始化到项目后为 `.claude/rules/fec-typescript.md`）。\n\n### Vue 3 项目补充约定\n\n```vue\n<script setup lang=\"ts\">\ninterface Props {\n  title: string;\n  items: Item[];\n  loading?: boolean;\n}\n\ninterface Emits {\n  (e: \"select\", item: Item): void;\n  (e: \"delete\", id: string): void;\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n  loading: false,\n});\n\nconst emit = defineEmits<Emits>();\n</script>\n```\n\n- Props 和 Emits 使用 TypeScript interface 定义\n- 使用 `withDefaults` 设置默认值\n- 禁止使用 `any`，优先使用精确类型\n- `defineExpose` 暴露的方法需有类型约束\n\n## Composables 规范\n\n### 设计原则\n\n- 以 `use` 前缀命名\n- 返回值使用对象，明确标注类型\n- 内部处理 loading / error / data 三态\n- 支持参数响应式（接受 `Ref` 或 getter）\n\n```typescript\nexport function useUserList(params: MaybeRef<QueryParams>) {\n  const data = ref<User[]>([]);\n  const loading = ref(false);\n  const error = ref<Error | null>(null);\n\n  async function fetch() {\n    loading.value = true;\n    error.value = null;\n    try {\n      const res = await getUserList(toValue(params));\n      data.value = res.list;\n    } catch (e) {\n      error.value = e as Error;\n    } finally {\n      loading.value = false;\n    }\n  }\n\n  watchEffect(() => {\n    fetch();\n  });\n\n  return {\n    data: readonly(data),\n    loading: readonly(loading),\n    error: readonly(error),\n    refetch: fetch,\n  };\n}\n```\n\n### Composable 使用原则\n\n- 返回 `readonly` 引用防止外部意外修改\n- 数据请求场景优先使用 VueQuery / VueUse 等库（如项目已引入）\n- `onUnmounted` 中清理定时器、事件监听等副作用\n- 避免在 composable 中直接操作 DOM\n\n## Slots 与 Provide/Inject\n\n### Slots\n\n- 用 `<slot>` 实现组件组合，而非过多 props\n- 具名 slot 用于明确的布局区域\n- 作用域 slot 传递数据给父组件自定义渲染\n\n```vue\n<template>\n  <div class=\"card\">\n    <div class=\"card-header\">\n      <slot name=\"header\">{{ title }}</slot>\n    </div>\n    <div class=\"card-body\">\n      <slot :data=\"processedData\" :loading=\"loading\" />\n    </div>\n  </div>\n</template>\n```\n\n### Provide/Inject\n\n- 用于跨多层级的上下文共享（主题、配置、权限）\n- 提供 InjectionKey 保证类型安全\n- 不要用 provide/inject 替代 props 传递直接父子数据\n\n```typescript\n// keys.ts\nexport const ThemeKey: InjectionKey<Ref<Theme>> = Symbol(\"theme\");\n\n// Provider.vue\nprovide(ThemeKey, theme);\n\n// Consumer.vue\nconst theme = inject(ThemeKey);\n```\n\n## 路由规范\n\n### 路由组织\n\n```typescript\n// app/router.ts\nconst routes: RouteRecordRaw[] = [\n  {\n    path: \"/\",\n    component: MainLayout,\n    children: [\n      {\n        path: \"\",\n        name: \"Dashboard\",\n        component: () => import(\"@/pages/Dashboard/DashboardPage.vue\"),\n      },\n      {\n        path: \"users\",\n        name: \"UserList\",\n        component: () => import(\"@/pages/UserList/UserListPage.vue\"),\n      },\n      {\n        path: \"users/:id\",\n        name: \"UserDetail\",\n        component: () => import(\"@/pages/UserDetail/UserDetailPage.vue\"),\n      },\n      {\n        path: \"settings\",\n        name: \"Settings\",\n        component: () => import(\"@/pages/Settings/SettingsPage.vue\"),\n      },\n    ],\n  },\n  {\n    path: \"/login\",\n    name: \"Login\",\n    component: () => import(\"@/pages/Login/LoginPage.vue\"),\n  },\n  {\n    path: \"/:pathMatch(.*)*\",\n    name: \"NotFound\",\n    component: () => import(\"@/pages/NotFound.vue\"),\n  },\n];\n```\n\n### 路由原则\n\n- 路由配置集中管理，每个路由必须有 `name`\n- 页面组件使用动态 `import()` 按需加载\n- 权限控制使用路由守卫（`beforeEach`），而非在每个页面内判断\n- URL 参数（分页、筛选、排序）与路由状态同步\n\n```typescript\n// 导航守卫\nrouter.beforeEach((to) => {\n  const authStore = useAuthStore();\n  if (to.meta.requiresAuth && !authStore.isLoggedIn) {\n    return { name: \"Login\", query: { redirect: to.fullPath } };\n  }\n});\n```\n\n## 状态管理（Pinia）\n\n| 状态类型           | 推荐方案                      |\n| ------------------ | ----------------------------- |\n| 组件内临时 UI 状态 | `ref` / `reactive`            |\n| 跨组件共享业务状态 | Pinia store                   |\n| 服务端数据缓存     | VueQuery / 自定义 composable  |\n| URL 驱动状态       | 路由参数 / `useRoute().query` |\n| 表单状态           | VeeValidate / FormKit         |\n\n### Pinia Store 规范\n\n使用 Composition API 风格（`setup store`）：\n\n```typescript\n// stores/authStore.ts\nexport const useAuthStore = defineStore(\"auth\", () => {\n  const user = ref<User | null>(null);\n  const token = ref<string | null>(localStorage.getItem(\"token\"));\n\n  const isLoggedIn = computed(() => !!token.value);\n\n  async function login(credentials: LoginParams) {\n    const res = await authApi.login(credentials);\n    user.value = res.user;\n    token.value = res.token;\n    localStorage.setItem(\"token\", res.token);\n  }\n\n  function logout() {\n    user.value = null;\n    token.value = null;\n    localStorage.removeItem(\"token\");\n  }\n\n  return { user: readonly(user), isLoggedIn, login, logout };\n});\n```\n\n### Store 原则\n\n- 每个 store 职责单一，按领域拆分\n- 对外暴露 `readonly` 的状态，通过 action 修改\n- 不要在 store 中存放 UI 临时状态（modal 开关、表单输入等）\n- 服务端数据优先用请求库管理，而非手动存入 store\n\n## API 层规范\n\n### 请求实例\n\n```typescript\n// services/request.ts\nconst request = axios.create({\n  baseURL: import.meta.env.VITE_API_BASE_URL,\n  timeout: 10000,\n});\n\nrequest.interceptors.request.use((config) => {\n  const authStore = useAuthStore();\n  if (authStore.token) {\n    config.headers.Authorization = `Bearer ${authStore.token}`;\n  }\n  return config;\n});\n\nrequest.interceptors.response.use(\n  (res) => res.data,\n  (error) => {\n    if (error.response?.status === 401) {\n      const authStore = useAuthStore();\n      authStore.logout();\n      router.push({ name: \"Login\" });\n    }\n    return Promise.reject(normalizeError(error));\n  },\n);\n```\n\n### API 函数\n\n```typescript\n// features/user/api.ts\nexport function getUserList(\n  params: UserQueryParams,\n): Promise<PageResult<User>> {\n  return request.get(\"/users\", { params });\n}\n\nexport function updateUser(id: string, data: UpdateUserDTO): Promise<User> {\n  return request.put(`/users/${id}`, data);\n}\n```\n\n- API 函数按 feature 组织，而非全部堆在一个文件\n- 请求参数和响应都有类型约束\n- 拦截器统一处理认证、错误格式化\n\n## 错误处理\n\n### 全局错误捕获\n\n```typescript\n// main.ts\napp.config.errorHandler = (err, instance, info) => {\n  reportError(err, { component: instance?.$options.name, info });\n};\n```\n\n### 组件级错误\n\n- 使用 `onErrorCaptured` 在父组件中捕获子组件错误\n- 数据请求失败需有用户可见的提示和重试机制\n- 不要吞掉错误（空 catch 块）\n\n## 自定义指令\n\n```typescript\n// directives/vPermission.ts\nexport const vPermission: Directive<HTMLElement, string> = {\n  mounted(el, binding) {\n    const authStore = useAuthStore();\n    if (!authStore.hasPermission(binding.value)) {\n      el.parentNode?.removeChild(el);\n    }\n  },\n};\n```\n\n- 指令只处理 DOM 层面的操作\n- 业务逻辑不要放在指令中\n- 需要响应式更新时实现 `updated` 钩子\n\n## 样式规范\n\n- 使用 `<style scoped>` 隔离样式\n- 深度选择器使用 `:deep()` 而非已废弃的 `::v-deep`\n- 与项目现有样式体系保持一致\n- 动态样式优先使用 `:class` / `:style` 绑定\n- 复杂主题切换使用 CSS 变量\n- 主题/全局变量通过 CSS 变量或 Token 管理\n\n## 测试规范\n\n### 必须测试\n\n- 核心交互行为（点击、输入、提交）\n- 条件渲染（loading / error / empty / data）\n- Emits 的触发和 payload\n- 关键 composables 的返回值\n- Pinia store 的 action 和 getter\n\n### 测试风格\n\n```typescript\ndescribe(\"UserForm\", () => {\n  it(\"should emit submit with valid data\", async () => {\n    const wrapper = mount(UserForm);\n\n    await wrapper.find('[data-testid=\"username\"]').setValue(\"test\");\n    await wrapper.find(\"form\").trigger(\"submit\");\n\n    expect(wrapper.emitted(\"submit\")?.[0]).toEqual([{ username: \"test\" }]);\n  });\n\n  it(\"should show validation error on empty submit\", async () => {\n    const wrapper = mount(UserForm);\n    await wrapper.find(\"form\").trigger(\"submit\");\n    expect(wrapper.text()).toContain(\"用户名不能为空\");\n  });\n});\n```\n\n### Store 测试\n\n```typescript\ndescribe(\"authStore\", () => {\n  beforeEach(() => setActivePinia(createPinia()));\n\n  it(\"should login and set user\", async () => {\n    const store = useAuthStore();\n    await store.login({ username: \"admin\", password: \"pass\" });\n    expect(store.isLoggedIn).toBe(true);\n  });\n});\n```\n\n## 性能\n\n- 使用 `shallowRef` / `shallowReactive` 优化大型对象\n- 大列表使用虚拟滚动\n- 避免在 `v-for` 中使用 `v-if`（提取为 computed 过滤）\n- 使用 `defineAsyncComponent` 懒加载重型组件\n- `v-for` 必须有稳定的 `:key`\n- 路由组件使用动态 `import()` 按需加载\n\n## 反模式\n\n- 在模板驱动组件中内联大段业务逻辑\n- 本该用 computed 却使用大范围 watcher\n- 事件 payload 不明确\n- 在纯展示组件中直接混入原始 API 调用\n- ref 和 props 没有类型约束\n- 用 `watch` + 手动赋值模拟 computed\n- 在一个组件中混入无关职责\n- 用大范围全局样式覆盖去解决局部 UI 问题\n- 将所有状态推入 Pinia store，而非就近管理\n- 在 `components/` 中放业务耦合组件\n- 直接从 feature 内部深层路径导入，绕过 `index.ts`\n\n## 输出检查清单\n\n- [ ] 文件结构与项目约定一致（pages / features / components 分离）\n- [ ] 使用 `<script setup lang=\"ts\">`\n- [ ] Props / Emits 类型完整\n- [ ] 解释性注释是否优先使用中文且点到要害\n- [ ] 可复用逻辑已提取到 composable\n- [ ] Loading / Error / Empty 状态均已处理\n- [ ] 路由组件使用动态 import 加载\n- [ ] 状态管理方案合理（就近原则）\n- [ ] API 调用有类型约束和统一错误处理\n- [ ] 样式使用 scoped 隔离\n- [ ] 关键行为有测试覆盖\n\nFile v2.4.0:skill-card.md\n\n## Description: <br>\nGuides agents in designing or reviewing Vue 3 + TypeScript project structure, component boundaries, composables, route composition, Pinia ownership, API and error handling defaults, styling boundaries, directives, and repository-wide Vue conventions. <br>\n\nThis skill is ready for commercial/non-commercial use. <br>\n\n## Publisher: <br>\n[bovinphang](https://clawhub.ai/user/bovinphang) <br>\n\n### License/Terms of Use: <br>\nMIT <br>\n\n\n## Use Case: <br>\nDevelopers and coding agents use this skill to structure and review Vue 3 + TypeScript applications, especially component boundaries, composables, Pinia state ownership, routing, API and error handling, and project conventions. <br>\n\n### Deployment Geography for Use: <br>\nGlobal <br>\n\n## Known Risks and Mitigations: <br>\nRisk: The skill can guide agents to propose broad Vue architecture or code changes that may not fit a specific repository. <br>\nMitigation: Review generated changes against the repository's existing conventions and tests before applying or deploying them. <br>\n\n\n## Reference(s): <br>\n- [Vue 3 Project Details](references/vue3-project-details.md) <br>\n- [ClawHub Skill Page](https://clawhub.ai/bovinphang/fec-vue3-project-standard) <br>\n- [Frontend Craft Repository](https://github.com/bovinphang/frontend-craft) <br>\n\n\n## Skill Output: <br>\n**Output Type(s):** [Guidance, Markdown, Code, Configuration] <br>\n**Output Format:** [Markdown guidance with code and configuration examples when needed] <br>\n**Output Parameters:** [1D] <br>\n**Other Properties Related to Output:** [Documentation-only skill; review generated recommendations before applying project changes.] <br>\n\n## Skill Version(s): <br>\n2.4.0 (source: server release metadata, package.json, metadata.json, README.md) <br>\n\n## Ethical Considerations: <br>\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment. <br>\n\nFile v2.4.0:metadata.json\n\n{\n  \"id\": \"fec-vue3-project-standard\",\n  \"name\": \"Vue 3 项目规范\",\n  \"category\": \"project-standard\",\n  \"tags\": [\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"summary\": \"Frontend Craft skill for Vue 3 项目规范.\",\n  \"version\": \"2.4.0\",\n  \"license\": \"MIT\",\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"repository\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"platforms\": [\n    \"skills-cli\",\n    \"skillreg\",\n    \"claude-code\",\n    \"codex\",\n    \"cursor\",\n    \"opencode\",\n    \"openclaw\",\n    \"generic-skill-runtime\"\n  ],\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\",\n  \"source\": \"skills/fec-vue3-project-standard\",\n  \"references\": [\n    \"references/vue3-project-details.md\"\n  ],\n  \"relations\": {\n    \"relatedSkills\": [\n      \"fec-typescript-type-safety\",\n      \"fec-state-management\",\n      \"fec-tailwind-design-system\",\n      \"fec-responsive-layout\",\n      \"fec-form-handling\",\n      \"fec-data-fetching\",\n      \"fec-component-testing\",\n      \"fec-e2e-testing\",\n      \"fec-accessibility-check\",\n      \"fec-security-review\",\n      \"fec-list-virtualization\",\n      \"fec-svg-animation\",\n      \"fec-canvas-threejs\"\n    ],\n    \"boundaryWorkflows\": [\n      \"Use specialty workflows for complex forms, state ownership, TypeScript contracts, server state, tests, accessibility, security, large lists, animation, or graphics.\",\n      \"Keep generic Vue component architecture, composables, and Pinia boundaries in the Vue project workflow.\"\n    ],\n    \"capabilityTags\": [\n      \"vue\",\n      \"project-standard\",\n      \"fec-architecture\"\n    ]\n  }\n}\n\nFile v2.4.0:package.json\n\n{\n  \"name\": \"@frontend-craft/fec-vue3-project-standard\",\n  \"version\": \"2.4.0\",\n  \"description\": \"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 项目规范, Vue 组件架构.\",\n  \"type\": \"module\",\n  \"license\": \"MIT\",\n  \"author\": {\n    \"name\": \"Bovin Phang\",\n    \"email\": \"pengbaowen@msn.com\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"https://github.com/bovinphang/frontend-craft\",\n    \"directory\": \"skills/fec-vue3-project-standard\"\n  },\n  \"homepage\": \"https://github.com/bovinphang/frontend-craft\",\n  \"keywords\": [\n    \"agent-skill\",\n    \"frontend-craft\",\n    \"project-standard\",\n    \"vue3\",\n    \"typescript\",\n    \"composition-api\",\n    \"pinia\",\n    \"components\"\n  ],\n  \"files\": [\n    \"SKILL.md\",\n    \"references\",\n    \"scripts\",\n    \"data\",\n    \"metadata.json\",\n    \"README.md\",\n    \"LICENSE\"\n  ],\n  \"publishConfig\": {\n    \"access\": \"public\"\n  }\n}","readmeExcerpt":"Skill: Vue3 Project Standard Owner: bovinphang Summary: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil Tags: latest:2.9.0 Version history: v2.9.0 | 2026-09-26T14:41:4","codeSnippets":[],"executableExamples":[{"language":"typescript","snippet":"export function useUserList(params: MaybeRef<QueryParams>) {\n  const data = ref<User[]>([]);\n  const loading = ref(false);\n  const error = ref<Error | null>(null);\n\n  async function fetch() {\n    loading.value = true;\n    error.value = null;\n    try {\n      const res = await getUserList(toValue(params));\n      data.value = res.list;\n    } catch (e) {\n      error.value = e as Error;\n    } finally {\n      loading.value = false;\n    }\n  }\n\n  watchEffect(() => {\n    fetch();\n  });\n\n  return {\n    data: readonly(data),\n    loading: readonly(loading),\n    error: readonly(error),\n    refetch: fetch,\n  };\n}"},{"language":"vue","snippet":"<template>\n  <div class=\"card\">\n    <div class=\"card-header\">\n      <slot name=\"header\">{{ title }}</slot>\n    </div>\n    <div class=\"card-body\">\n      <slot :data=\"processedData\" :loading=\"loading\" />\n    </div>\n  </div>\n</template>"},{"language":"typescript","snippet":"// keys.ts\nexport const ThemeKey: InjectionKey<Ref<Theme>> = Symbol(\"theme\");\n\n// Provider.vue\nprovide(ThemeKey, theme);\n\n// Consumer.vue\nconst theme = inject(ThemeKey);"},{"language":"typescript","snippet":"// app/router.ts\nconst routes: RouteRecordRaw[] = [\n  {\n    path: \"/\",\n    component: MainLayout,\n    children: [\n      {\n        path: \"\",\n        name: \"Dashboard\",\n        component: () => import(\"@/pages/Dashboard/DashboardPage.vue\"),\n      },\n      {\n        path: \"users\",\n        name: \"UserList\",\n        component: () => import(\"@/pages/UserList/UserListPage.vue\"),\n      },\n      {\n        path: \"users/:id\",\n        name: \"UserDetail\",\n        component: () => import(\"@/pages/UserDetail/UserDetailPage.vue\"),\n      },\n      {\n        path: \"settings\",\n        name: \"Settings\",\n        component: () => import(\"@/pages/Settings/SettingsPage.vue\"),\n      },\n    ],\n  },\n  {\n    path: \"/login\",\n    name: \"Login\",\n    component: () => import(\"@/pages/Login/LoginPage.vue\"),\n  },\n  {\n    path: \"/:pathMatch(.*)*\",\n    name: \"NotFound\",\n    component: () => import(\"@/pages/NotFound.vue\"),\n  },\n];"},{"language":"typescript","snippet":"// Navigation guard\nrouter.beforeEach((to) => {\n  const authStore = useAuthStore();\n  if (to.meta.requiresAuth && !authStore.isLoggedIn) {\n    return { name: \"Login\", query: { redirect: to.fullPath } };\n  }\n});"},{"language":"text","snippet":"src/\n├── app/ # Application entry and global configuration\n│ ├── App.vue # Root component\n│ ├── main.ts # Application startup entrance\n│ └── router.ts # Routing instance and configuration\n│\n├── pages/ # Page components (one-to-one correspondence with routing)\n│   ├── Dashboard/\n│   │   ├── DashboardPage.vue\n│ │ ├── components/ # Page private components\n│ │ └── composables/ # Page private composables\n│   ├── UserList/\n│   └── Settings/\n│\n├── layouts/ # Layout component\n│ ├── MainLayout.vue # Main layout (sidebar + top bar + content area)\n│ ├── AuthLayout.vue # Login/registration page layout\n│ └── BlankLayout.vue # Blank layout (error page, etc.)\n│\n├── features/ # Function modules (divided by business areas)\n│   ├── auth/\n│ │ ├── components/ # Module components\n│ │ ├── composables/ # module composables\n│ │ ├── api.ts # Module API call\n│ │ ├── types.ts # Module type definition\n│ │ ├── constants.ts # Module constants\n│ │ └── index.ts # Module publicly exported\n│   └── order/\n│\n├── components/ # Globally shared UI components\n│   ├── AppButton/\n│   │   ├── AppButton.vue\n│   │   └── __tests__/\n│   ├── AppModal/\n│   ├── AppForm/\n│   └── AppErrorBoundary/\n│\n├── composables/ # Global shared composables\n│   ├── useAuth.ts\n│   ├── useDebounce.ts\n│   └── useMediaQuery.ts\n│\n├── services/ # API base layer\n│ ├── request.ts # Axios/fetch instance and interceptor\n│ └── endpoints/ # API endpoint definition (such as split by field)\n│\n├── stores/ # Pinia status management\n│   ├── authStore.ts\n│   └── uiStore.ts\n│\n├── locales/ # International language pack\n│ ├── zh-CN.json # Simplified Chinese\n│ ├── en-US.json # English\n│ └── index.ts # i18n instance initialization (vue-i18n)\n│\n├── assets/ # Static resources\n│ ├── images/ # Pictures (PNG, JPG, WebP)\n│ ├── icons/ # SVG icon\n│ └── fonts/ # Custom fonts\n│\n├── config/ # Application configuration\n│ ├── env.ts # Typed encapsulation of environment variables\n│ └── features.ts # Feature Flags Management\n│\n├── types/ # Global shared types\n│ ├── ap"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: fec-vue3-project-standard\ndescription: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\n---\n\n# Vue 3 project specifications\n\nFor repositories using Vue 3 + TypeScript.\n\n## Purpose\n\nProvides project structure, component boundaries, Composables, and default implementation conventions for Vue 3 + TypeScript projects to ensure conventional development and type safety.\n\n## Procedure\n\n1. Identify the existing Vue conventions in the warehouse: directory, routing, Pinia, request layer, style system, component library and test framework.\n2. Demarcate the boundaries between pages, business components, common components, composables, stores, services and utils.\n3. Prioritize the existing automatic import/module export conventions of `<script setup lang=\"ts\">`, composite API and warehouse.\n4. Complete state ownership, API layer, error handling, style isolation and special skill offloading when outputting.\n5. Pages and modules must have recoverable error UI; global `errorHandler`, `onErrorCaptured`, request error mapping and routing error page have clear division of labor.\n6. Tailwind token/variant or responsive layout requirements should be diverted to corresponding special skills to avoid stuffing style system rules into Vue component specifications.\n7. When the state ownership is complex, first make a state list; when the boundaries of DTO, public props, generic composable or `tsconfig` are complex, first use the TypeScript project specification process to converge cross-framework type contracts.\n8. When designing reusable composables, clarify whether the input supports plain value, ref, computed or getter; when testing Vue components, cover the common boundaries of Pinia, Router, Teleport, Suspense and async setup.\n\n## Detailed reference\n\nLoad more detailed reference files as needed:\n\n- Project directory, component layering, component specifications, annotations, and TypeScript: Load [references/vue3-project-structure.md](references/vue3-project-structure.md).\n- Composables, slots, Provide/Inject and routing organizations: Load [references/vue3-composables-routing.md](references/vue3-composables-routing.md).\n- Pinia, API layer, error handling, directives, styles, tests, anti-patterns and output checklist: Loading [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md).\n- Lightweight performance conventions at the Vue project specification level: Load [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md).\n\n## Constraints\n\n- Use `<script setup lang=\"ts\">` to disable using Options API to add new components\n- The size "},{"path":"README.md","content":"# Vue 3 project specifications\n\nOrganize Vue 3 and TypeScript SFCs, composables, routes, Pinia, and project boundaries.\n\n## Skill\n\n- ID: `fec-vue3-project-standard`\n- Category: `project-standard`\n- Version: `2.9.0`\n- Source: `skills/fec-vue3-project-standard/SKILL.md`\n\n## Description\n\nUse when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibility, virtualization, animation, or security deep dives; Chinese triggers include Vue 3 project specification, Vue component architecture.\n\n## Usage\n\nInstall or import this package with any skill runtime that understands the standard `SKILL.md` layout. The canonical source remains the Frontend Craft repository.\n\n## Packaged Files\n\n- [references/vue3-composables-routing.md](references/vue3-composables-routing.md)\n- [references/vue3-performance-patterns.md](references/vue3-performance-patterns.md)\n- [references/vue3-project-structure.md](references/vue3-project-structure.md)\n- [references/vue3-state-api-quality.md](references/vue3-state-api-quality.md)\n\n## Optional Related Packages\n\n- `@bovinphang/fec-typescript-project-standard`\n- `@bovinphang/fec-state-management`\n- `@bovinphang/fec-tailwind-design-system`\n- `@bovinphang/fec-responsive-layout`\n- `@bovinphang/fec-form-handling`\n- `@bovinphang/fec-data-fetching`\n- `@bovinphang/fec-component-testing`\n- `@bovinphang/fec-e2e-testing`\n- `@bovinphang/fec-accessibility-check`\n- `@bovinphang/fec-security-review`\n- `@bovinphang/fec-list-virtualization`\n- `@bovinphang/fec-svg-animation`\n- `@bovinphang/fec-canvas-threejs`\n\n## License\n\nMIT"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn7b0nh7hvj1pffeqc8y0dqwwh83m726\",\n  \"slug\": \"fec-vue3-project-standard\",\n  \"version\": \"2.9.0\",\n  \"publishedAt\": 1790433706275\n}"},{"path":"references/vue3-composables-routing.md","content":"# Vue 3 composables and routing patterns\n\n## Composables specification\n\n### Design principles\n\n- Named with `use` prefix\n- Use objects as return values and clearly mark the type\n- Internal processing loading / error / data tri-state\n-Support parameter responsiveness (accepts `Ref` or getter)\n- Library level composable to clarify whether the parameter supports normal values, `Ref`, `computed` or getter, and parse the latest value inside the side effect\n\n```typescript\nexport function useUserList(params: MaybeRef<QueryParams>) {\n  const data = ref<User[]>([]);\n  const loading = ref(false);\n  const error = ref<Error | null>(null);\n\n  async function fetch() {\n    loading.value = true;\n    error.value = null;\n    try {\n      const res = await getUserList(toValue(params));\n      data.value = res.list;\n    } catch (e) {\n      error.value = e as Error;\n    } finally {\n      loading.value = false;\n    }\n  }\n\n  watchEffect(() => {\n    fetch();\n  });\n\n  return {\n    data: readonly(data),\n    loading: readonly(loading),\n    error: readonly(error),\n    refetch: fetch,\n  };\n}\n```\n\n### Composable usage principles\n\n- Return a `readonly` reference to prevent accidental modification by outsiders\n- In data request scenarios, libraries such as VueQuery / VueUse are preferred (if the project has been introduced)\n- Clean up timers, event listeners and other side effects in `onUnmounted`\n- Avoid directly manipulating DOM in composable\n- Read-only inputs accept normal values, refs, computed or getters; inputs that require bidirectional writing only accept writable refs or explicit setters.\n- If the parameter itself is a callback, comparator or predicate, do not design it as a getter type input, otherwise the business function may be mistakenly called during parsing.\n\n### Vue Router / Pinia / Test common boundaries\n\n- Changes in routing parameters will not recreate the same routing component; data that relies on `route.params` must watch clear fields and handle cancellation and race conditions.\n- Avoid old-style `next()` multi-branch repeated calls in navigation guards; give priority to returning `false`, redirecting objects or throwing handleable errors.\n- Use `storeToRefs` when destructuring the Pinia store will lose responsiveness; the setup store must return state, getters and actions that need to be tracked externally.\n- UI temporary status, form input, and pop-up window switches do not enter the global store; URL query, server-side cache, and local component status are returned to their respective places first.\n- Vue Test Utils tests prioritize user-visible behavior and do not use snapshots as the only proof; asynchronous updates use `await`, `flushPromises` or the waiting method recommended by the framework.\n- When testing using Pinia, Router, Teleport, Suspense, async setup or `defineAsyncComponent`, explicitly install the plugin in the test fixture, mount the target container and wait for async to stabilize.\n\n## Slots and Provide/Inject\n\n### Slots\n\n- Use `<slot>`"},{"path":"references/vue3-performance-patterns.md","content":"# Vue 3 performance patterns\n\nThis file keeps lightweight Vue project-standard performance guidance. Use the frontend performance workflow when the task needs metrics, traces, profiles, bundle analysis, network evidence, or a formal performance report.\n\n## Performance\n\n- Use `shallowRef` / `shallowReactive` to optimize large objects\n- Use virtual scrolling for large lists\n- Avoid using `v-if` in `v-for` (extract to computed filtering)\n- Use `defineAsyncComponent` to lazily load heavy components\n- `v-for` must have a stable `:key`\n- Routing components are loaded on demand using dynamic `import()`"}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil Skill: Vue3 Project Standard Owner: bovinphang Summary: Use when designing or reviewing Vue 3 + TypeScript project structure, SFC/component boundaries, composables organization, route composition, Pinia ownership, API/error/styling defaults, directives, or repository-wide Vue conventions. Prefer narrower skills for forms, data fetching, tests, accessibil Tags: latest:2.9.0 Version history: v2.9.0 | 2026-09-26T14:41:4","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1550,"uniquenessScore":47,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-12T01:48:35.856Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-13T17:23:19.381Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}