@wazir-dev/cli 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +111 -0
- package/CHANGELOG.md +14 -0
- package/CONTRIBUTING.md +101 -0
- package/LICENSE +21 -0
- package/README.md +314 -0
- package/assets/composition-engine.mmd +34 -0
- package/assets/demo-script.sh +17 -0
- package/assets/logo-dark.svg +14 -0
- package/assets/logo.svg +14 -0
- package/assets/pipeline.mmd +39 -0
- package/assets/record-demo.sh +51 -0
- package/docs/README.md +51 -0
- package/docs/adapters/context-mode.md +60 -0
- package/docs/concepts/architecture.md +87 -0
- package/docs/concepts/artifact-model.md +60 -0
- package/docs/concepts/composition-engine.md +36 -0
- package/docs/concepts/indexing-and-recall.md +160 -0
- package/docs/concepts/observability.md +41 -0
- package/docs/concepts/roles-and-workflows.md +59 -0
- package/docs/concepts/terminology-policy.md +27 -0
- package/docs/getting-started/01-installation.md +78 -0
- package/docs/getting-started/02-first-run.md +102 -0
- package/docs/getting-started/03-adding-to-project.md +15 -0
- package/docs/getting-started/04-host-setup.md +15 -0
- package/docs/guides/ci-integration.md +15 -0
- package/docs/guides/creating-skills.md +15 -0
- package/docs/guides/expertise-module-authoring.md +15 -0
- package/docs/guides/hook-development.md +15 -0
- package/docs/guides/memory-and-learnings.md +34 -0
- package/docs/guides/multi-host-export.md +15 -0
- package/docs/guides/troubleshooting.md +101 -0
- package/docs/guides/writing-custom-roles.md +15 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-design.md +592 -0
- package/docs/plans/2026-03-15-cli-pipeline-integration-plan.md +598 -0
- package/docs/plans/2026-03-15-docs-enforcement-plan.md +238 -0
- package/docs/readmes/INDEX.md +99 -0
- package/docs/readmes/features/expertise/README.md +171 -0
- package/docs/readmes/features/exports/README.md +222 -0
- package/docs/readmes/features/hooks/README.md +103 -0
- package/docs/readmes/features/hooks/loop-cap-guard.md +133 -0
- package/docs/readmes/features/hooks/post-tool-capture.md +121 -0
- package/docs/readmes/features/hooks/post-tool-lint.md +130 -0
- package/docs/readmes/features/hooks/pre-compact-summary.md +122 -0
- package/docs/readmes/features/hooks/pre-tool-capture-route.md +100 -0
- package/docs/readmes/features/hooks/protected-path-write-guard.md +128 -0
- package/docs/readmes/features/hooks/session-start.md +119 -0
- package/docs/readmes/features/hooks/stop-handoff-harvest.md +125 -0
- package/docs/readmes/features/roles/README.md +157 -0
- package/docs/readmes/features/roles/clarifier.md +152 -0
- package/docs/readmes/features/roles/content-author.md +190 -0
- package/docs/readmes/features/roles/designer.md +193 -0
- package/docs/readmes/features/roles/executor.md +184 -0
- package/docs/readmes/features/roles/learner.md +210 -0
- package/docs/readmes/features/roles/planner.md +182 -0
- package/docs/readmes/features/roles/researcher.md +164 -0
- package/docs/readmes/features/roles/reviewer.md +184 -0
- package/docs/readmes/features/roles/specifier.md +162 -0
- package/docs/readmes/features/roles/verifier.md +215 -0
- package/docs/readmes/features/schemas/README.md +178 -0
- package/docs/readmes/features/skills/README.md +63 -0
- package/docs/readmes/features/skills/brainstorming.md +96 -0
- package/docs/readmes/features/skills/debugging.md +148 -0
- package/docs/readmes/features/skills/design.md +120 -0
- package/docs/readmes/features/skills/prepare-next.md +109 -0
- package/docs/readmes/features/skills/run-audit.md +159 -0
- package/docs/readmes/features/skills/scan-project.md +109 -0
- package/docs/readmes/features/skills/self-audit.md +176 -0
- package/docs/readmes/features/skills/tdd.md +137 -0
- package/docs/readmes/features/skills/using-skills.md +92 -0
- package/docs/readmes/features/skills/verification.md +120 -0
- package/docs/readmes/features/skills/writing-plans.md +104 -0
- package/docs/readmes/features/tooling/README.md +320 -0
- package/docs/readmes/features/workflows/README.md +186 -0
- package/docs/readmes/features/workflows/author.md +181 -0
- package/docs/readmes/features/workflows/clarify.md +154 -0
- package/docs/readmes/features/workflows/design-review.md +171 -0
- package/docs/readmes/features/workflows/design.md +169 -0
- package/docs/readmes/features/workflows/discover.md +162 -0
- package/docs/readmes/features/workflows/execute.md +173 -0
- package/docs/readmes/features/workflows/learn.md +167 -0
- package/docs/readmes/features/workflows/plan-review.md +165 -0
- package/docs/readmes/features/workflows/plan.md +170 -0
- package/docs/readmes/features/workflows/prepare-next.md +167 -0
- package/docs/readmes/features/workflows/review.md +169 -0
- package/docs/readmes/features/workflows/run-audit.md +191 -0
- package/docs/readmes/features/workflows/spec-challenge.md +159 -0
- package/docs/readmes/features/workflows/specify.md +160 -0
- package/docs/readmes/features/workflows/verify.md +177 -0
- package/docs/readmes/packages/README.md +50 -0
- package/docs/readmes/packages/ajv.md +117 -0
- package/docs/readmes/packages/context-mode.md +118 -0
- package/docs/readmes/packages/gray-matter.md +116 -0
- package/docs/readmes/packages/node-test.md +137 -0
- package/docs/readmes/packages/yaml.md +112 -0
- package/docs/reference/configuration-reference.md +159 -0
- package/docs/reference/expertise-index.md +52 -0
- package/docs/reference/git-flow.md +43 -0
- package/docs/reference/hooks.md +87 -0
- package/docs/reference/host-exports.md +50 -0
- package/docs/reference/launch-checklist.md +172 -0
- package/docs/reference/marketplace-listings.md +76 -0
- package/docs/reference/release-process.md +34 -0
- package/docs/reference/roles-reference.md +77 -0
- package/docs/reference/skills.md +33 -0
- package/docs/reference/templates.md +29 -0
- package/docs/reference/tooling-cli.md +94 -0
- package/docs/truth-claims.yaml +222 -0
- package/expertise/PROGRESS.md +63 -0
- package/expertise/README.md +18 -0
- package/expertise/antipatterns/PROGRESS.md +56 -0
- package/expertise/antipatterns/backend/api-design-antipatterns.md +1271 -0
- package/expertise/antipatterns/backend/auth-antipatterns.md +1195 -0
- package/expertise/antipatterns/backend/caching-antipatterns.md +622 -0
- package/expertise/antipatterns/backend/database-antipatterns.md +1038 -0
- package/expertise/antipatterns/backend/index.md +24 -0
- package/expertise/antipatterns/backend/microservices-antipatterns.md +850 -0
- package/expertise/antipatterns/code/architecture-antipatterns.md +919 -0
- package/expertise/antipatterns/code/async-antipatterns.md +622 -0
- package/expertise/antipatterns/code/code-smells.md +1186 -0
- package/expertise/antipatterns/code/dependency-antipatterns.md +1209 -0
- package/expertise/antipatterns/code/error-handling-antipatterns.md +1360 -0
- package/expertise/antipatterns/code/index.md +27 -0
- package/expertise/antipatterns/code/naming-and-abstraction.md +1118 -0
- package/expertise/antipatterns/code/state-management-antipatterns.md +1076 -0
- package/expertise/antipatterns/code/testing-antipatterns.md +1053 -0
- package/expertise/antipatterns/design/accessibility-antipatterns.md +1136 -0
- package/expertise/antipatterns/design/dark-patterns.md +1121 -0
- package/expertise/antipatterns/design/index.md +22 -0
- package/expertise/antipatterns/design/ui-antipatterns.md +1202 -0
- package/expertise/antipatterns/design/ux-antipatterns.md +680 -0
- package/expertise/antipatterns/frontend/css-layout-antipatterns.md +691 -0
- package/expertise/antipatterns/frontend/flutter-antipatterns.md +1827 -0
- package/expertise/antipatterns/frontend/index.md +23 -0
- package/expertise/antipatterns/frontend/mobile-antipatterns.md +573 -0
- package/expertise/antipatterns/frontend/react-antipatterns.md +1128 -0
- package/expertise/antipatterns/frontend/spa-antipatterns.md +1235 -0
- package/expertise/antipatterns/index.md +31 -0
- package/expertise/antipatterns/performance/index.md +20 -0
- package/expertise/antipatterns/performance/performance-antipatterns.md +1013 -0
- package/expertise/antipatterns/performance/premature-optimization.md +623 -0
- package/expertise/antipatterns/performance/scaling-antipatterns.md +785 -0
- package/expertise/antipatterns/process/ai-coding-antipatterns.md +853 -0
- package/expertise/antipatterns/process/code-review-antipatterns.md +656 -0
- package/expertise/antipatterns/process/deployment-antipatterns.md +920 -0
- package/expertise/antipatterns/process/index.md +23 -0
- package/expertise/antipatterns/process/technical-debt-antipatterns.md +647 -0
- package/expertise/antipatterns/security/index.md +20 -0
- package/expertise/antipatterns/security/secrets-antipatterns.md +849 -0
- package/expertise/antipatterns/security/security-theater.md +843 -0
- package/expertise/antipatterns/security/vulnerability-patterns.md +801 -0
- package/expertise/architecture/PROGRESS.md +70 -0
- package/expertise/architecture/data/caching-architecture.md +671 -0
- package/expertise/architecture/data/data-consistency.md +574 -0
- package/expertise/architecture/data/data-modeling.md +536 -0
- package/expertise/architecture/data/event-streams-and-queues.md +634 -0
- package/expertise/architecture/data/index.md +25 -0
- package/expertise/architecture/data/search-architecture.md +663 -0
- package/expertise/architecture/data/sql-vs-nosql.md +708 -0
- package/expertise/architecture/decisions/architecture-decision-records.md +640 -0
- package/expertise/architecture/decisions/build-vs-buy.md +616 -0
- package/expertise/architecture/decisions/index.md +23 -0
- package/expertise/architecture/decisions/monolith-to-microservices.md +790 -0
- package/expertise/architecture/decisions/technology-selection.md +616 -0
- package/expertise/architecture/distributed/cap-theorem-and-tradeoffs.md +800 -0
- package/expertise/architecture/distributed/circuit-breaker-bulkhead.md +741 -0
- package/expertise/architecture/distributed/consensus-and-coordination.md +796 -0
- package/expertise/architecture/distributed/distributed-systems-fundamentals.md +564 -0
- package/expertise/architecture/distributed/idempotency-and-retry.md +796 -0
- package/expertise/architecture/distributed/index.md +25 -0
- package/expertise/architecture/distributed/saga-pattern.md +797 -0
- package/expertise/architecture/foundations/architectural-thinking.md +460 -0
- package/expertise/architecture/foundations/coupling-and-cohesion.md +770 -0
- package/expertise/architecture/foundations/design-principles-solid.md +649 -0
- package/expertise/architecture/foundations/domain-driven-design.md +719 -0
- package/expertise/architecture/foundations/index.md +25 -0
- package/expertise/architecture/foundations/separation-of-concerns.md +472 -0
- package/expertise/architecture/foundations/twelve-factor-app.md +797 -0
- package/expertise/architecture/index.md +34 -0
- package/expertise/architecture/integration/api-design-graphql.md +638 -0
- package/expertise/architecture/integration/api-design-grpc.md +804 -0
- package/expertise/architecture/integration/api-design-rest.md +892 -0
- package/expertise/architecture/integration/index.md +25 -0
- package/expertise/architecture/integration/third-party-integration.md +795 -0
- package/expertise/architecture/integration/webhooks-and-callbacks.md +1152 -0
- package/expertise/architecture/integration/websockets-realtime.md +791 -0
- package/expertise/architecture/mobile-architecture/index.md +22 -0
- package/expertise/architecture/mobile-architecture/mobile-app-architecture.md +780 -0
- package/expertise/architecture/mobile-architecture/mobile-backend-for-frontend.md +670 -0
- package/expertise/architecture/mobile-architecture/offline-first.md +719 -0
- package/expertise/architecture/mobile-architecture/push-and-sync.md +782 -0
- package/expertise/architecture/patterns/cqrs-event-sourcing.md +717 -0
- package/expertise/architecture/patterns/event-driven.md +797 -0
- package/expertise/architecture/patterns/hexagonal-clean-architecture.md +870 -0
- package/expertise/architecture/patterns/index.md +27 -0
- package/expertise/architecture/patterns/layered-architecture.md +736 -0
- package/expertise/architecture/patterns/microservices.md +753 -0
- package/expertise/architecture/patterns/modular-monolith.md +692 -0
- package/expertise/architecture/patterns/monolith.md +626 -0
- package/expertise/architecture/patterns/plugin-architecture.md +735 -0
- package/expertise/architecture/patterns/serverless.md +780 -0
- package/expertise/architecture/scaling/database-scaling.md +615 -0
- package/expertise/architecture/scaling/feature-flags-and-rollouts.md +757 -0
- package/expertise/architecture/scaling/horizontal-vs-vertical.md +606 -0
- package/expertise/architecture/scaling/index.md +24 -0
- package/expertise/architecture/scaling/multi-tenancy.md +800 -0
- package/expertise/architecture/scaling/stateless-design.md +787 -0
- package/expertise/backend/embedded-firmware.md +625 -0
- package/expertise/backend/go.md +853 -0
- package/expertise/backend/index.md +24 -0
- package/expertise/backend/java-spring.md +448 -0
- package/expertise/backend/node-typescript.md +625 -0
- package/expertise/backend/python-fastapi.md +724 -0
- package/expertise/backend/rust.md +458 -0
- package/expertise/backend/solidity.md +711 -0
- package/expertise/composition-map.yaml +443 -0
- package/expertise/content/foundations/content-modeling.md +395 -0
- package/expertise/content/foundations/editorial-standards.md +449 -0
- package/expertise/content/foundations/index.md +24 -0
- package/expertise/content/foundations/microcopy.md +455 -0
- package/expertise/content/foundations/terminology-governance.md +509 -0
- package/expertise/content/index.md +34 -0
- package/expertise/content/patterns/accessibility-copy.md +518 -0
- package/expertise/content/patterns/index.md +24 -0
- package/expertise/content/patterns/notification-content.md +433 -0
- package/expertise/content/patterns/sample-content.md +486 -0
- package/expertise/content/patterns/state-copy.md +439 -0
- package/expertise/design/PROGRESS.md +58 -0
- package/expertise/design/disciplines/dark-mode-theming.md +577 -0
- package/expertise/design/disciplines/design-systems.md +595 -0
- package/expertise/design/disciplines/index.md +25 -0
- package/expertise/design/disciplines/information-architecture.md +800 -0
- package/expertise/design/disciplines/interaction-design.md +788 -0
- package/expertise/design/disciplines/responsive-design.md +552 -0
- package/expertise/design/disciplines/usability-testing.md +516 -0
- package/expertise/design/disciplines/user-research.md +792 -0
- package/expertise/design/foundations/accessibility-design.md +796 -0
- package/expertise/design/foundations/color-theory.md +797 -0
- package/expertise/design/foundations/iconography.md +795 -0
- package/expertise/design/foundations/index.md +26 -0
- package/expertise/design/foundations/motion-and-animation.md +653 -0
- package/expertise/design/foundations/rtl-design.md +585 -0
- package/expertise/design/foundations/spacing-and-layout.md +607 -0
- package/expertise/design/foundations/typography.md +800 -0
- package/expertise/design/foundations/visual-hierarchy.md +761 -0
- package/expertise/design/index.md +32 -0
- package/expertise/design/patterns/authentication-flows.md +474 -0
- package/expertise/design/patterns/content-consumption.md +789 -0
- package/expertise/design/patterns/data-display.md +618 -0
- package/expertise/design/patterns/e-commerce.md +1494 -0
- package/expertise/design/patterns/feedback-and-states.md +642 -0
- package/expertise/design/patterns/forms-and-input.md +819 -0
- package/expertise/design/patterns/gamification.md +801 -0
- package/expertise/design/patterns/index.md +31 -0
- package/expertise/design/patterns/microinteractions.md +449 -0
- package/expertise/design/patterns/navigation.md +800 -0
- package/expertise/design/patterns/notifications.md +705 -0
- package/expertise/design/patterns/onboarding.md +700 -0
- package/expertise/design/patterns/search-and-filter.md +601 -0
- package/expertise/design/patterns/settings-and-preferences.md +768 -0
- package/expertise/design/patterns/social-and-community.md +748 -0
- package/expertise/design/platforms/desktop-native.md +612 -0
- package/expertise/design/platforms/index.md +25 -0
- package/expertise/design/platforms/mobile-android.md +825 -0
- package/expertise/design/platforms/mobile-cross-platform.md +983 -0
- package/expertise/design/platforms/mobile-ios.md +699 -0
- package/expertise/design/platforms/tablet.md +794 -0
- package/expertise/design/platforms/web-dashboard.md +790 -0
- package/expertise/design/platforms/web-responsive.md +550 -0
- package/expertise/design/psychology/behavioral-nudges.md +449 -0
- package/expertise/design/psychology/cognitive-load.md +1191 -0
- package/expertise/design/psychology/error-psychology.md +778 -0
- package/expertise/design/psychology/index.md +22 -0
- package/expertise/design/psychology/persuasive-design.md +736 -0
- package/expertise/design/psychology/user-mental-models.md +623 -0
- package/expertise/design/tooling/open-pencil.md +266 -0
- package/expertise/frontend/angular.md +1073 -0
- package/expertise/frontend/desktop-electron.md +546 -0
- package/expertise/frontend/flutter.md +782 -0
- package/expertise/frontend/index.md +27 -0
- package/expertise/frontend/native-android.md +409 -0
- package/expertise/frontend/native-ios.md +490 -0
- package/expertise/frontend/react-native.md +1160 -0
- package/expertise/frontend/react.md +808 -0
- package/expertise/frontend/vue.md +1089 -0
- package/expertise/humanize/domain-rules-code.md +79 -0
- package/expertise/humanize/domain-rules-content.md +67 -0
- package/expertise/humanize/domain-rules-technical-docs.md +56 -0
- package/expertise/humanize/index.md +35 -0
- package/expertise/humanize/self-audit-checklist.md +87 -0
- package/expertise/humanize/sentence-patterns.md +218 -0
- package/expertise/humanize/vocabulary-blacklist.md +105 -0
- package/expertise/i18n/PROGRESS.md +65 -0
- package/expertise/i18n/advanced/accessibility-and-i18n.md +28 -0
- package/expertise/i18n/advanced/bidirectional-text-algorithm.md +38 -0
- package/expertise/i18n/advanced/complex-scripts.md +30 -0
- package/expertise/i18n/advanced/performance-and-i18n.md +27 -0
- package/expertise/i18n/advanced/testing-i18n.md +28 -0
- package/expertise/i18n/content/content-adaptation.md +23 -0
- package/expertise/i18n/content/locale-specific-formatting.md +23 -0
- package/expertise/i18n/content/machine-translation-integration.md +28 -0
- package/expertise/i18n/content/translation-management.md +29 -0
- package/expertise/i18n/foundations/date-time-calendars.md +67 -0
- package/expertise/i18n/foundations/i18n-architecture.md +272 -0
- package/expertise/i18n/foundations/locale-and-language-tags.md +79 -0
- package/expertise/i18n/foundations/numbers-currency-units.md +61 -0
- package/expertise/i18n/foundations/pluralization-and-gender.md +109 -0
- package/expertise/i18n/foundations/string-externalization.md +236 -0
- package/expertise/i18n/foundations/text-direction-bidi.md +241 -0
- package/expertise/i18n/foundations/unicode-and-encoding.md +86 -0
- package/expertise/i18n/index.md +38 -0
- package/expertise/i18n/platform/backend-i18n.md +31 -0
- package/expertise/i18n/platform/flutter-i18n.md +148 -0
- package/expertise/i18n/platform/native-android-i18n.md +36 -0
- package/expertise/i18n/platform/native-ios-i18n.md +36 -0
- package/expertise/i18n/platform/react-i18n.md +103 -0
- package/expertise/i18n/platform/web-css-i18n.md +81 -0
- package/expertise/i18n/rtl/arabic-specific.md +175 -0
- package/expertise/i18n/rtl/hebrew-specific.md +149 -0
- package/expertise/i18n/rtl/rtl-animations-and-transitions.md +111 -0
- package/expertise/i18n/rtl/rtl-forms-and-input.md +161 -0
- package/expertise/i18n/rtl/rtl-fundamentals.md +211 -0
- package/expertise/i18n/rtl/rtl-icons-and-images.md +181 -0
- package/expertise/i18n/rtl/rtl-layout-mirroring.md +252 -0
- package/expertise/i18n/rtl/rtl-navigation-and-gestures.md +107 -0
- package/expertise/i18n/rtl/rtl-testing-and-qa.md +147 -0
- package/expertise/i18n/rtl/rtl-typography.md +160 -0
- package/expertise/index.md +113 -0
- package/expertise/index.yaml +216 -0
- package/expertise/infrastructure/cloud-aws.md +597 -0
- package/expertise/infrastructure/cloud-gcp.md +599 -0
- package/expertise/infrastructure/cybersecurity.md +816 -0
- package/expertise/infrastructure/database-mongodb.md +447 -0
- package/expertise/infrastructure/database-postgres.md +400 -0
- package/expertise/infrastructure/devops-cicd.md +787 -0
- package/expertise/infrastructure/index.md +27 -0
- package/expertise/performance/PROGRESS.md +50 -0
- package/expertise/performance/backend/api-latency.md +1204 -0
- package/expertise/performance/backend/background-jobs.md +506 -0
- package/expertise/performance/backend/connection-pooling.md +1209 -0
- package/expertise/performance/backend/database-query-optimization.md +515 -0
- package/expertise/performance/backend/index.md +23 -0
- package/expertise/performance/backend/rate-limiting-and-throttling.md +971 -0
- package/expertise/performance/foundations/algorithmic-complexity.md +954 -0
- package/expertise/performance/foundations/caching-strategies.md +489 -0
- package/expertise/performance/foundations/concurrency-and-parallelism.md +847 -0
- package/expertise/performance/foundations/index.md +24 -0
- package/expertise/performance/foundations/measuring-and-profiling.md +440 -0
- package/expertise/performance/foundations/memory-management.md +964 -0
- package/expertise/performance/foundations/performance-budgets.md +1314 -0
- package/expertise/performance/index.md +31 -0
- package/expertise/performance/infrastructure/auto-scaling.md +1059 -0
- package/expertise/performance/infrastructure/cdn-and-edge.md +1081 -0
- package/expertise/performance/infrastructure/index.md +22 -0
- package/expertise/performance/infrastructure/load-balancing.md +1081 -0
- package/expertise/performance/infrastructure/observability.md +1079 -0
- package/expertise/performance/mobile/index.md +23 -0
- package/expertise/performance/mobile/mobile-animations.md +544 -0
- package/expertise/performance/mobile/mobile-memory-battery.md +416 -0
- package/expertise/performance/mobile/mobile-network.md +452 -0
- package/expertise/performance/mobile/mobile-rendering.md +599 -0
- package/expertise/performance/mobile/mobile-startup-time.md +505 -0
- package/expertise/performance/platform-specific/flutter-performance.md +647 -0
- package/expertise/performance/platform-specific/index.md +22 -0
- package/expertise/performance/platform-specific/node-performance.md +1307 -0
- package/expertise/performance/platform-specific/postgres-performance.md +1366 -0
- package/expertise/performance/platform-specific/react-performance.md +1403 -0
- package/expertise/performance/web/bundle-optimization.md +1239 -0
- package/expertise/performance/web/image-and-media.md +636 -0
- package/expertise/performance/web/index.md +24 -0
- package/expertise/performance/web/network-optimization.md +1133 -0
- package/expertise/performance/web/rendering-performance.md +1098 -0
- package/expertise/performance/web/ssr-and-hydration.md +918 -0
- package/expertise/performance/web/web-vitals.md +1374 -0
- package/expertise/quality/accessibility.md +985 -0
- package/expertise/quality/evidence-based-verification.md +499 -0
- package/expertise/quality/index.md +24 -0
- package/expertise/quality/ml-model-audit.md +614 -0
- package/expertise/quality/performance.md +600 -0
- package/expertise/quality/testing-api.md +891 -0
- package/expertise/quality/testing-mobile.md +496 -0
- package/expertise/quality/testing-web.md +849 -0
- package/expertise/security/PROGRESS.md +54 -0
- package/expertise/security/agentic-identity.md +540 -0
- package/expertise/security/compliance-frameworks.md +601 -0
- package/expertise/security/data/data-encryption.md +364 -0
- package/expertise/security/data/data-privacy-gdpr.md +692 -0
- package/expertise/security/data/database-security.md +1171 -0
- package/expertise/security/data/index.md +22 -0
- package/expertise/security/data/pii-handling.md +531 -0
- package/expertise/security/foundations/authentication.md +1041 -0
- package/expertise/security/foundations/authorization.md +603 -0
- package/expertise/security/foundations/cryptography.md +1001 -0
- package/expertise/security/foundations/index.md +25 -0
- package/expertise/security/foundations/owasp-top-10.md +1354 -0
- package/expertise/security/foundations/secrets-management.md +1217 -0
- package/expertise/security/foundations/secure-sdlc.md +700 -0
- package/expertise/security/foundations/supply-chain-security.md +698 -0
- package/expertise/security/index.md +31 -0
- package/expertise/security/infrastructure/cloud-security-aws.md +1296 -0
- package/expertise/security/infrastructure/cloud-security-gcp.md +1376 -0
- package/expertise/security/infrastructure/container-security.md +721 -0
- package/expertise/security/infrastructure/incident-response.md +1295 -0
- package/expertise/security/infrastructure/index.md +24 -0
- package/expertise/security/infrastructure/logging-and-monitoring.md +1618 -0
- package/expertise/security/infrastructure/network-security.md +1337 -0
- package/expertise/security/mobile/index.md +23 -0
- package/expertise/security/mobile/mobile-android-security.md +1218 -0
- package/expertise/security/mobile/mobile-binary-protection.md +1229 -0
- package/expertise/security/mobile/mobile-data-storage.md +1265 -0
- package/expertise/security/mobile/mobile-ios-security.md +1401 -0
- package/expertise/security/mobile/mobile-network-security.md +1520 -0
- package/expertise/security/smart-contract-security.md +594 -0
- package/expertise/security/testing/index.md +22 -0
- package/expertise/security/testing/penetration-testing.md +1258 -0
- package/expertise/security/testing/security-code-review.md +1765 -0
- package/expertise/security/testing/threat-modeling.md +1074 -0
- package/expertise/security/testing/vulnerability-scanning.md +1062 -0
- package/expertise/security/web/api-security.md +586 -0
- package/expertise/security/web/cors-and-headers.md +433 -0
- package/expertise/security/web/csrf.md +562 -0
- package/expertise/security/web/file-upload.md +1477 -0
- package/expertise/security/web/index.md +25 -0
- package/expertise/security/web/injection.md +1375 -0
- package/expertise/security/web/session-management.md +1101 -0
- package/expertise/security/web/xss.md +1158 -0
- package/exports/README.md +17 -0
- package/exports/hosts/claude/.claude/agents/clarifier.md +42 -0
- package/exports/hosts/claude/.claude/agents/content-author.md +63 -0
- package/exports/hosts/claude/.claude/agents/designer.md +55 -0
- package/exports/hosts/claude/.claude/agents/executor.md +55 -0
- package/exports/hosts/claude/.claude/agents/learner.md +51 -0
- package/exports/hosts/claude/.claude/agents/planner.md +53 -0
- package/exports/hosts/claude/.claude/agents/researcher.md +43 -0
- package/exports/hosts/claude/.claude/agents/reviewer.md +54 -0
- package/exports/hosts/claude/.claude/agents/specifier.md +47 -0
- package/exports/hosts/claude/.claude/agents/verifier.md +71 -0
- package/exports/hosts/claude/.claude/commands/author.md +42 -0
- package/exports/hosts/claude/.claude/commands/clarify.md +38 -0
- package/exports/hosts/claude/.claude/commands/design-review.md +46 -0
- package/exports/hosts/claude/.claude/commands/design.md +44 -0
- package/exports/hosts/claude/.claude/commands/discover.md +37 -0
- package/exports/hosts/claude/.claude/commands/execute.md +48 -0
- package/exports/hosts/claude/.claude/commands/learn.md +38 -0
- package/exports/hosts/claude/.claude/commands/plan-review.md +42 -0
- package/exports/hosts/claude/.claude/commands/plan.md +39 -0
- package/exports/hosts/claude/.claude/commands/prepare-next.md +37 -0
- package/exports/hosts/claude/.claude/commands/review.md +40 -0
- package/exports/hosts/claude/.claude/commands/run-audit.md +41 -0
- package/exports/hosts/claude/.claude/commands/spec-challenge.md +41 -0
- package/exports/hosts/claude/.claude/commands/specify.md +38 -0
- package/exports/hosts/claude/.claude/commands/verify.md +37 -0
- package/exports/hosts/claude/.claude/settings.json +34 -0
- package/exports/hosts/claude/CLAUDE.md +19 -0
- package/exports/hosts/claude/export.manifest.json +38 -0
- package/exports/hosts/claude/host-package.json +67 -0
- package/exports/hosts/codex/AGENTS.md +19 -0
- package/exports/hosts/codex/export.manifest.json +38 -0
- package/exports/hosts/codex/host-package.json +41 -0
- package/exports/hosts/cursor/.cursor/hooks.json +16 -0
- package/exports/hosts/cursor/.cursor/rules/wazir-core.mdc +19 -0
- package/exports/hosts/cursor/export.manifest.json +38 -0
- package/exports/hosts/cursor/host-package.json +42 -0
- package/exports/hosts/gemini/GEMINI.md +19 -0
- package/exports/hosts/gemini/export.manifest.json +38 -0
- package/exports/hosts/gemini/host-package.json +41 -0
- package/hooks/README.md +18 -0
- package/hooks/definitions/loop_cap_guard.yaml +21 -0
- package/hooks/definitions/post_tool_capture.yaml +24 -0
- package/hooks/definitions/pre_compact_summary.yaml +19 -0
- package/hooks/definitions/pre_tool_capture_route.yaml +19 -0
- package/hooks/definitions/protected_path_write_guard.yaml +19 -0
- package/hooks/definitions/session_start.yaml +19 -0
- package/hooks/definitions/stop_handoff_harvest.yaml +20 -0
- package/hooks/loop-cap-guard +17 -0
- package/hooks/post-tool-lint +36 -0
- package/hooks/protected-path-write-guard +17 -0
- package/hooks/session-start +41 -0
- package/llms-full.txt +2355 -0
- package/llms.txt +43 -0
- package/package.json +79 -0
- package/roles/README.md +20 -0
- package/roles/clarifier.md +42 -0
- package/roles/content-author.md +63 -0
- package/roles/designer.md +55 -0
- package/roles/executor.md +55 -0
- package/roles/learner.md +51 -0
- package/roles/planner.md +53 -0
- package/roles/researcher.md +43 -0
- package/roles/reviewer.md +54 -0
- package/roles/specifier.md +47 -0
- package/roles/verifier.md +71 -0
- package/schemas/README.md +24 -0
- package/schemas/accepted-learning.schema.json +20 -0
- package/schemas/author-artifact.schema.json +156 -0
- package/schemas/clarification.schema.json +19 -0
- package/schemas/design-artifact.schema.json +80 -0
- package/schemas/docs-claim.schema.json +18 -0
- package/schemas/export-manifest.schema.json +20 -0
- package/schemas/hook.schema.json +67 -0
- package/schemas/host-export-package.schema.json +18 -0
- package/schemas/implementation-plan.schema.json +19 -0
- package/schemas/proposed-learning.schema.json +19 -0
- package/schemas/research.schema.json +18 -0
- package/schemas/review.schema.json +29 -0
- package/schemas/run-manifest.schema.json +18 -0
- package/schemas/spec-challenge.schema.json +18 -0
- package/schemas/spec.schema.json +20 -0
- package/schemas/usage.schema.json +102 -0
- package/schemas/verification-proof.schema.json +29 -0
- package/schemas/wazir-manifest.schema.json +173 -0
- package/skills/README.md +40 -0
- package/skills/brainstorming/SKILL.md +77 -0
- package/skills/debugging/SKILL.md +50 -0
- package/skills/design/SKILL.md +61 -0
- package/skills/dispatching-parallel-agents/SKILL.md +128 -0
- package/skills/executing-plans/SKILL.md +70 -0
- package/skills/finishing-a-development-branch/SKILL.md +169 -0
- package/skills/humanize/SKILL.md +123 -0
- package/skills/init-pipeline/SKILL.md +124 -0
- package/skills/prepare-next/SKILL.md +20 -0
- package/skills/receiving-code-review/SKILL.md +123 -0
- package/skills/requesting-code-review/SKILL.md +105 -0
- package/skills/requesting-code-review/code-reviewer.md +108 -0
- package/skills/run-audit/SKILL.md +197 -0
- package/skills/scan-project/SKILL.md +41 -0
- package/skills/self-audit/SKILL.md +153 -0
- package/skills/subagent-driven-development/SKILL.md +154 -0
- package/skills/subagent-driven-development/code-quality-reviewer-prompt.md +26 -0
- package/skills/subagent-driven-development/implementer-prompt.md +102 -0
- package/skills/subagent-driven-development/spec-reviewer-prompt.md +61 -0
- package/skills/tdd/SKILL.md +23 -0
- package/skills/using-git-worktrees/SKILL.md +163 -0
- package/skills/using-skills/SKILL.md +95 -0
- package/skills/verification/SKILL.md +22 -0
- package/skills/wazir/SKILL.md +463 -0
- package/skills/writing-plans/SKILL.md +30 -0
- package/skills/writing-skills/SKILL.md +157 -0
- package/skills/writing-skills/anthropic-best-practices.md +122 -0
- package/skills/writing-skills/persuasion-principles.md +50 -0
- package/templates/README.md +20 -0
- package/templates/artifacts/README.md +10 -0
- package/templates/artifacts/accepted-learning.md +19 -0
- package/templates/artifacts/accepted-learning.template.json +12 -0
- package/templates/artifacts/author.md +74 -0
- package/templates/artifacts/author.template.json +19 -0
- package/templates/artifacts/clarification.md +21 -0
- package/templates/artifacts/clarification.template.json +12 -0
- package/templates/artifacts/execute-notes.md +19 -0
- package/templates/artifacts/implementation-plan.md +21 -0
- package/templates/artifacts/implementation-plan.template.json +11 -0
- package/templates/artifacts/learning-proposal.md +19 -0
- package/templates/artifacts/next-run-handoff.md +21 -0
- package/templates/artifacts/plan-review.md +19 -0
- package/templates/artifacts/proposed-learning.template.json +12 -0
- package/templates/artifacts/research.md +21 -0
- package/templates/artifacts/research.template.json +12 -0
- package/templates/artifacts/review-findings.md +19 -0
- package/templates/artifacts/review.template.json +11 -0
- package/templates/artifacts/run-manifest.template.json +8 -0
- package/templates/artifacts/spec-challenge.md +19 -0
- package/templates/artifacts/spec-challenge.template.json +11 -0
- package/templates/artifacts/spec.md +21 -0
- package/templates/artifacts/spec.template.json +12 -0
- package/templates/artifacts/verification-proof.md +19 -0
- package/templates/artifacts/verification-proof.template.json +11 -0
- package/templates/examples/accepted-learning.example.json +14 -0
- package/templates/examples/author.example.json +152 -0
- package/templates/examples/clarification.example.json +15 -0
- package/templates/examples/docs-claim.example.json +8 -0
- package/templates/examples/export-manifest.example.json +7 -0
- package/templates/examples/host-export-package.example.json +11 -0
- package/templates/examples/implementation-plan.example.json +17 -0
- package/templates/examples/proposed-learning.example.json +13 -0
- package/templates/examples/research.example.json +15 -0
- package/templates/examples/research.example.md +6 -0
- package/templates/examples/review.example.json +17 -0
- package/templates/examples/run-manifest.example.json +9 -0
- package/templates/examples/spec-challenge.example.json +14 -0
- package/templates/examples/spec.example.json +21 -0
- package/templates/examples/verification-proof.example.json +21 -0
- package/templates/examples/wazir-manifest.example.yaml +65 -0
- package/templates/task-definition-schema.md +99 -0
- package/tooling/README.md +20 -0
- package/tooling/src/adapters/context-mode.js +50 -0
- package/tooling/src/capture/command.js +376 -0
- package/tooling/src/capture/store.js +99 -0
- package/tooling/src/capture/usage.js +270 -0
- package/tooling/src/checks/branches.js +50 -0
- package/tooling/src/checks/brand-truth.js +110 -0
- package/tooling/src/checks/changelog.js +231 -0
- package/tooling/src/checks/command-registry.js +36 -0
- package/tooling/src/checks/commits.js +102 -0
- package/tooling/src/checks/docs-drift.js +103 -0
- package/tooling/src/checks/docs-truth.js +201 -0
- package/tooling/src/checks/runtime-surface.js +156 -0
- package/tooling/src/cli.js +116 -0
- package/tooling/src/command-options.js +56 -0
- package/tooling/src/commands/validate.js +320 -0
- package/tooling/src/doctor/command.js +91 -0
- package/tooling/src/export/command.js +77 -0
- package/tooling/src/export/compiler.js +498 -0
- package/tooling/src/guards/loop-cap-guard.js +52 -0
- package/tooling/src/guards/protected-path-write-guard.js +67 -0
- package/tooling/src/index/command.js +152 -0
- package/tooling/src/index/storage.js +1061 -0
- package/tooling/src/index/summarizers.js +261 -0
- package/tooling/src/loaders.js +18 -0
- package/tooling/src/project-root.js +22 -0
- package/tooling/src/recall/command.js +225 -0
- package/tooling/src/schema-validator.js +30 -0
- package/tooling/src/state-root.js +40 -0
- package/tooling/src/status/command.js +71 -0
- package/wazir.manifest.yaml +135 -0
- package/workflows/README.md +19 -0
- package/workflows/author.md +42 -0
- package/workflows/clarify.md +38 -0
- package/workflows/design-review.md +46 -0
- package/workflows/design.md +44 -0
- package/workflows/discover.md +37 -0
- package/workflows/execute.md +48 -0
- package/workflows/learn.md +38 -0
- package/workflows/plan-review.md +42 -0
- package/workflows/plan.md +39 -0
- package/workflows/prepare-next.md +37 -0
- package/workflows/review.md +40 -0
- package/workflows/run-audit.md +41 -0
- package/workflows/spec-challenge.md +41 -0
- package/workflows/specify.md +38 -0
- package/workflows/verify.md +37 -0
|
@@ -0,0 +1,1089 @@
|
|
|
1
|
+
# Vue.js — Expertise Module
|
|
2
|
+
|
|
3
|
+
> A Vue.js specialist designs, builds, and maintains reactive web applications using Vue 3's
|
|
4
|
+
> Composition API, Nuxt 3 for SSR/SSG, and the modern Vue ecosystem (Pinia, Vite, Vitest).
|
|
5
|
+
> Scope spans component architecture, state management, performance optimization, testing, and deployment.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 1. Core Patterns & Conventions
|
|
10
|
+
|
|
11
|
+
### 1.1 Project Structure
|
|
12
|
+
|
|
13
|
+
**Standalone Vue 3 + Vite (feature-based):**
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/
|
|
17
|
+
features/
|
|
18
|
+
auth/
|
|
19
|
+
components/ # Feature-scoped components
|
|
20
|
+
composables/ # Feature-scoped composables
|
|
21
|
+
stores/ # Feature-scoped Pinia stores
|
|
22
|
+
types/ # Feature-scoped TypeScript types
|
|
23
|
+
views/ # Route-level pages
|
|
24
|
+
index.ts # Public API barrel
|
|
25
|
+
dashboard/
|
|
26
|
+
...
|
|
27
|
+
shared/
|
|
28
|
+
components/ # Cross-feature reusable components
|
|
29
|
+
composables/ # Cross-feature composables (useDebounce, useFetch)
|
|
30
|
+
utils/ # Pure utility functions
|
|
31
|
+
types/ # Shared TypeScript types
|
|
32
|
+
layouts/
|
|
33
|
+
router/
|
|
34
|
+
index.ts
|
|
35
|
+
stores/ # Global stores (user session, app config)
|
|
36
|
+
App.vue
|
|
37
|
+
main.ts
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
**Nuxt 3 (convention-based):**
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
app/
|
|
44
|
+
components/ # Auto-imported components
|
|
45
|
+
composables/ # Auto-imported composables
|
|
46
|
+
layouts/ # Application layouts (default.vue, admin.vue)
|
|
47
|
+
middleware/ # Route middleware (auth, guest)
|
|
48
|
+
pages/ # File-based routing
|
|
49
|
+
plugins/ # Nuxt plugins (runs on app init)
|
|
50
|
+
utils/ # Auto-imported utility functions
|
|
51
|
+
server/
|
|
52
|
+
api/ # Server API routes (Nitro)
|
|
53
|
+
middleware/ # Server middleware
|
|
54
|
+
utils/ # Server-side utilities
|
|
55
|
+
stores/ # Pinia stores
|
|
56
|
+
layers/ # Nuxt layers for code sharing
|
|
57
|
+
public/ # Static assets (served at /)
|
|
58
|
+
nuxt.config.ts
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Key Nuxt 3 conventions: directories like `components/`, `composables/`, and `utils/` are
|
|
62
|
+
auto-imported. The `layers/` directory enables sharing code, components, and config across
|
|
63
|
+
projects. The `server/` directory uses Nitro for API routes and server middleware.
|
|
64
|
+
|
|
65
|
+
### 1.2 Naming Conventions & Code Style
|
|
66
|
+
|
|
67
|
+
| Element | Convention | Example |
|
|
68
|
+
|-------------------------|-------------------------------------|--------------------------------|
|
|
69
|
+
| Components | PascalCase, multi-word | `UserProfileCard.vue` |
|
|
70
|
+
| Composables | camelCase, `use` prefix | `useAuthSession.ts` |
|
|
71
|
+
| Pinia stores | camelCase, `use...Store` suffix | `useCartStore.ts` |
|
|
72
|
+
| Props | camelCase in script, kebab in template | `userName` / `user-name` |
|
|
73
|
+
| Events | camelCase with verb | `@update:modelValue` |
|
|
74
|
+
| Route files (Nuxt) | kebab-case | `user-profile.vue` |
|
|
75
|
+
| CSS classes | BEM or utility-first (Tailwind) | `.user-card__avatar` |
|
|
76
|
+
| Constants | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT` |
|
|
77
|
+
| TypeScript interfaces | PascalCase, no `I` prefix | `UserProfile`, not `IUserProfile` |
|
|
78
|
+
|
|
79
|
+
**eslint-plugin-vue (v9.x+):** Use the `flat/recommended` preset as baseline. Key rules:
|
|
80
|
+
|
|
81
|
+
- `vue/multi-word-component-names` — enforces multi-word names to avoid HTML element collisions
|
|
82
|
+
- `vue/component-api-style` — enforce `<script setup>` usage
|
|
83
|
+
- `vue/define-macros-order` — consistent ordering of defineProps, defineEmits, defineModel
|
|
84
|
+
- `vue/block-order` — enforce `<script>`, `<template>`, `<style>` ordering
|
|
85
|
+
- `vue/no-v-html` — warn on v-html usage (security)
|
|
86
|
+
- `vue/require-typed-ref` — require typed ref declarations with TypeScript
|
|
87
|
+
|
|
88
|
+
### 1.3 Composition API Patterns
|
|
89
|
+
|
|
90
|
+
**`<script setup>` is the standard for Vue 3.4+.** It reduces boilerplate and provides
|
|
91
|
+
better TypeScript inference. All new components should use this syntax.
|
|
92
|
+
|
|
93
|
+
**Composables** encapsulate reusable stateful logic:
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
// composables/useCounter.ts
|
|
97
|
+
import { ref, computed } from 'vue'
|
|
98
|
+
|
|
99
|
+
export function useCounter(initial = 0) {
|
|
100
|
+
const count = ref(initial)
|
|
101
|
+
const doubled = computed(() => count.value * 2)
|
|
102
|
+
|
|
103
|
+
function increment() { count.value++ }
|
|
104
|
+
function reset() { count.value = initial }
|
|
105
|
+
|
|
106
|
+
return { count, doubled, increment, reset }
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Rules for composables:
|
|
111
|
+
- Always return refs (not raw values) so destructuring preserves reactivity
|
|
112
|
+
- Prefix with `use` — this is enforced by eslint-plugin-vue
|
|
113
|
+
- Accept refs or plain values as arguments; use `toValue()` (Vue 3.3+) to normalize
|
|
114
|
+
- Clean up side effects (watchers, event listeners) — Vue auto-disposes when the
|
|
115
|
+
component hosting the composable unmounts, but manual cleanup is needed for
|
|
116
|
+
non-Vue event listeners
|
|
117
|
+
|
|
118
|
+
**Provide/Inject** for subtree-scoped state (avoids prop drilling):
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// Parent
|
|
122
|
+
import { provide, ref } from 'vue'
|
|
123
|
+
const theme = ref<'light' | 'dark'>('light')
|
|
124
|
+
provide('theme', theme) // Use InjectionKey<T> for type safety
|
|
125
|
+
|
|
126
|
+
// Child (any depth)
|
|
127
|
+
import { inject } from 'vue'
|
|
128
|
+
const theme = inject('theme', ref('light')) // default fallback
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Use `InjectionKey<T>` from Vue for type-safe provide/inject in TypeScript projects.
|
|
132
|
+
|
|
133
|
+
### 1.4 State Management (Pinia 2.x)
|
|
134
|
+
|
|
135
|
+
Pinia is the official Vue state management library, replacing Vuex.
|
|
136
|
+
|
|
137
|
+
**Setup Store syntax (recommended for complex stores):**
|
|
138
|
+
|
|
139
|
+
```typescript
|
|
140
|
+
// stores/useCartStore.ts
|
|
141
|
+
import { defineStore } from 'pinia'
|
|
142
|
+
import { ref, computed } from 'vue'
|
|
143
|
+
|
|
144
|
+
export const useCartStore = defineStore('cart', () => {
|
|
145
|
+
// State
|
|
146
|
+
const items = ref<CartItem[]>([])
|
|
147
|
+
|
|
148
|
+
// Getters
|
|
149
|
+
const totalPrice = computed(() =>
|
|
150
|
+
items.value.reduce((sum, item) => sum + item.price * item.qty, 0)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
// Actions
|
|
154
|
+
async function addItem(product: Product) {
|
|
155
|
+
const existing = items.value.find(i => i.id === product.id)
|
|
156
|
+
if (existing) existing.qty++
|
|
157
|
+
else items.value.push({ ...product, qty: 1 })
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function clear() { items.value = [] }
|
|
161
|
+
|
|
162
|
+
return { items, totalPrice, addItem, clear }
|
|
163
|
+
})
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**When to use Pinia vs composables vs provide/inject:**
|
|
167
|
+
|
|
168
|
+
| Criterion | Composable | Provide/Inject | Pinia |
|
|
169
|
+
|----------------------------------|-----------------------|----------------------|---------------------|
|
|
170
|
+
| State scope | Per-consumer instance | Component subtree | Global singleton |
|
|
171
|
+
| DevTools support | No | No | Yes (time-travel) |
|
|
172
|
+
| SSR hydration safety | Manual | Manual | Built-in |
|
|
173
|
+
| Best for | Reusable logic | Subtree coordination | Global app state |
|
|
174
|
+
| Performance (ref changes) | Fastest (~20x Pinia) | Fast | Baseline |
|
|
175
|
+
|
|
176
|
+
### 1.5 Routing
|
|
177
|
+
|
|
178
|
+
**Vue Router 4 (standalone Vue):** Declare routes in `router/index.ts`. Use lazy loading
|
|
179
|
+
via `() => import('./views/Dashboard.vue')` for code splitting.
|
|
180
|
+
|
|
181
|
+
**Nuxt 3 auto-routing:** File-based routing from `pages/` directory:
|
|
182
|
+
|
|
183
|
+
- `pages/index.vue` -> `/`
|
|
184
|
+
- `pages/users/[id].vue` -> `/users/:id`
|
|
185
|
+
- `pages/posts/[...slug].vue` -> `/posts/*` (catch-all)
|
|
186
|
+
- `pages/admin.vue` + `pages/admin/settings.vue` -> nested routes
|
|
187
|
+
|
|
188
|
+
Route middleware in Nuxt:
|
|
189
|
+
```typescript
|
|
190
|
+
// middleware/auth.ts
|
|
191
|
+
export default defineNuxtRouteMiddleware((to, from) => {
|
|
192
|
+
const { loggedIn } = useUserSession()
|
|
193
|
+
if (!loggedIn.value) return navigateTo('/login')
|
|
194
|
+
})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 1.6 Data Flow Patterns
|
|
198
|
+
|
|
199
|
+
- **Props down, events up** — the fundamental Vue data flow pattern
|
|
200
|
+
- **v-model / defineModel** (Vue 3.4+) — two-way binding macro for parent-child sync
|
|
201
|
+
- **Provide/Inject** — skip intermediate components in deep trees
|
|
202
|
+
- **Pinia** — cross-tree or cross-route state sharing
|
|
203
|
+
- **Event bus** — AVOID in Vue 3; use Pinia or provide/inject instead
|
|
204
|
+
|
|
205
|
+
`defineModel` (stable in Vue 3.4+) simplifies v-model support:
|
|
206
|
+
|
|
207
|
+
```vue
|
|
208
|
+
<script setup lang="ts">
|
|
209
|
+
const modelValue = defineModel<string>({ required: true })
|
|
210
|
+
</script>
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### 1.7 Error Handling
|
|
214
|
+
|
|
215
|
+
**onErrorCaptured** — lifecycle hook that catches errors from descendant components:
|
|
216
|
+
|
|
217
|
+
```typescript
|
|
218
|
+
import { onErrorCaptured, ref } from 'vue'
|
|
219
|
+
|
|
220
|
+
const error = ref<Error | null>(null)
|
|
221
|
+
|
|
222
|
+
onErrorCaptured((err: Error) => {
|
|
223
|
+
error.value = err
|
|
224
|
+
return false // Prevents error from propagating further
|
|
225
|
+
})
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Error boundary component pattern:**
|
|
229
|
+
|
|
230
|
+
```vue
|
|
231
|
+
<!-- ErrorBoundary.vue -->
|
|
232
|
+
<script setup lang="ts">
|
|
233
|
+
import { onErrorCaptured, ref } from 'vue'
|
|
234
|
+
const error = ref<Error | null>(null)
|
|
235
|
+
const reset = () => { error.value = null }
|
|
236
|
+
onErrorCaptured((err: Error) => {
|
|
237
|
+
error.value = err
|
|
238
|
+
return false
|
|
239
|
+
})
|
|
240
|
+
</script>
|
|
241
|
+
<template>
|
|
242
|
+
<slot v-if="!error" />
|
|
243
|
+
<slot v-else name="fallback" :error="error" :reset="reset" />
|
|
244
|
+
</template>
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
Limitations: `onErrorCaptured` only catches errors during Vue lifecycle (render, setup,
|
|
248
|
+
watchers). Errors in `@click` handlers or setTimeout callbacks require explicit try/catch.
|
|
249
|
+
|
|
250
|
+
**Global error handler:**
|
|
251
|
+
```typescript
|
|
252
|
+
app.config.errorHandler = (err, instance, info) => {
|
|
253
|
+
reportToSentry(err, { component: instance?.$options.name, info })
|
|
254
|
+
}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### 1.8 Logging & Observability
|
|
258
|
+
|
|
259
|
+
- Use `app.config.errorHandler` to funnel all uncaught Vue errors to an observability
|
|
260
|
+
service (Sentry, DataDog, LogRocket)
|
|
261
|
+
- `app.config.warnHandler` captures Vue warnings in development
|
|
262
|
+
- For Nuxt 3, use the `useError()` composable and `error.vue` page for application-level
|
|
263
|
+
error display
|
|
264
|
+
- Instrument API calls in composables (log request/response/timing)
|
|
265
|
+
- Use `performance.mark()` and `performance.measure()` for custom timing in critical paths
|
|
266
|
+
|
|
267
|
+
---
|
|
268
|
+
|
|
269
|
+
## 2. Anti-Patterns & Pitfalls
|
|
270
|
+
|
|
271
|
+
### 2.1 Mutating Props Directly
|
|
272
|
+
|
|
273
|
+
**Problem:** Props are one-way data flow. Mutating them causes silent overwrites on parent
|
|
274
|
+
re-render and makes data flow unpredictable. Vue emits a runtime warning.
|
|
275
|
+
**Fix:** Emit an event to the parent or use `defineModel` for two-way binding.
|
|
276
|
+
|
|
277
|
+
### 2.2 Using `reactive()` for Primitives
|
|
278
|
+
|
|
279
|
+
**Problem:** `reactive()` only works with objects. Wrapping a primitive loses reactivity
|
|
280
|
+
silently. Reassigning the entire reactive object also breaks reactivity.
|
|
281
|
+
**Fix:** Use `ref()` for primitives and single values. Prefer `ref()` as the default
|
|
282
|
+
unless you have a complex nested object with no reassignment.
|
|
283
|
+
|
|
284
|
+
### 2.3 Destructuring Reactive Objects
|
|
285
|
+
|
|
286
|
+
**Problem:** `const { name, age } = reactive(user)` produces plain (non-reactive) values.
|
|
287
|
+
Changes to `name` do not trigger re-renders.
|
|
288
|
+
**Fix:** Use `toRefs()`: `const { name, age } = toRefs(reactiveUser)` or use `ref()`.
|
|
289
|
+
In Vue 3.5+, `defineProps` supports reactive destructuring natively.
|
|
290
|
+
|
|
291
|
+
### 2.4 Combining `v-if` and `v-for` on the Same Element
|
|
292
|
+
|
|
293
|
+
**Problem:** In Vue 3, `v-if` has higher precedence than `v-for`, so the `v-if` condition
|
|
294
|
+
cannot access the `v-for` iteration variable. Even when it works, it re-evaluates the
|
|
295
|
+
condition on every render for every item.
|
|
296
|
+
**Fix:** Use a computed property to pre-filter the list, or wrap with a `<template v-for>`.
|
|
297
|
+
|
|
298
|
+
### 2.5 Using `v-html` with Untrusted Content
|
|
299
|
+
|
|
300
|
+
**Problem:** `v-html` renders raw HTML, bypassing Vue's automatic XSS escaping. User input
|
|
301
|
+
rendered via `v-html` is a direct XSS vector.
|
|
302
|
+
**Fix:** Sanitize with DOMPurify before rendering, or avoid `v-html` entirely for user content.
|
|
303
|
+
|
|
304
|
+
### 2.6 Overusing `$refs` / Template Refs for Data Flow
|
|
305
|
+
|
|
306
|
+
**Problem:** Reaching into child components via refs to read/write state bypasses Vue's
|
|
307
|
+
reactive data flow, making components tightly coupled and hard to test.
|
|
308
|
+
**Fix:** Use props/events or provide/inject. Reserve refs for imperative DOM operations
|
|
309
|
+
(focus, scroll, third-party library integration).
|
|
310
|
+
|
|
311
|
+
### 2.7 Forgetting to Clean Up Side Effects
|
|
312
|
+
|
|
313
|
+
**Problem:** Event listeners, timers, or subscriptions created in `onMounted` without
|
|
314
|
+
cleanup in `onUnmounted` cause memory leaks, especially in SPA navigation.
|
|
315
|
+
**Fix:** Always pair setup with teardown. Vue auto-cleans watchers and computed, but
|
|
316
|
+
manual listeners (window.addEventListener, WebSocket, setInterval) need explicit cleanup.
|
|
317
|
+
|
|
318
|
+
### 2.8 Making Computed Properties with Side Effects
|
|
319
|
+
|
|
320
|
+
**Problem:** Computed properties should be pure derivations. Mutating state, making API
|
|
321
|
+
calls, or triggering DOM changes inside computed breaks caching assumptions and causes
|
|
322
|
+
unpredictable behavior.
|
|
323
|
+
**Fix:** Use `watch` or `watchEffect` for side effects. Keep computed pure.
|
|
324
|
+
|
|
325
|
+
### 2.9 Deeply Nested Component Trees without Keys
|
|
326
|
+
|
|
327
|
+
**Problem:** Vue reuses DOM elements by default during list rendering. Without `:key`,
|
|
328
|
+
component state leaks between items during reorder/insert/delete operations.
|
|
329
|
+
**Fix:** Always use `:key` with `v-for`, binding to a unique stable identifier (not array index).
|
|
330
|
+
|
|
331
|
+
### 2.10 Using Array Index as `:key`
|
|
332
|
+
|
|
333
|
+
**Problem:** Array indices change when items are added, removed, or reordered. This causes
|
|
334
|
+
Vue to incorrectly reuse component instances, leading to stale state and visual glitches.
|
|
335
|
+
**Fix:** Use a unique business identifier (id, slug, UUID) as the key.
|
|
336
|
+
|
|
337
|
+
### 2.11 Giant Monolithic Components (>300 lines)
|
|
338
|
+
|
|
339
|
+
**Problem:** Components that handle fetching, state, logic, and presentation become
|
|
340
|
+
untestable and hard to maintain. Changes in one concern risk breaking others.
|
|
341
|
+
**Fix:** Extract logic into composables, split into container/presentational components,
|
|
342
|
+
and keep each component focused on a single responsibility.
|
|
343
|
+
|
|
344
|
+
### 2.12 Prop Drilling Through 3+ Levels
|
|
345
|
+
|
|
346
|
+
**Problem:** Passing props through intermediate components that don't use them creates
|
|
347
|
+
maintenance burden and tight coupling across the tree.
|
|
348
|
+
**Fix:** Use `provide/inject` for subtree data, or Pinia for cross-tree state.
|
|
349
|
+
|
|
350
|
+
### 2.13 Watchers That Trigger Themselves
|
|
351
|
+
|
|
352
|
+
**Problem:** A watcher that modifies the same reactive source it watches creates an
|
|
353
|
+
infinite loop (Vue has a recursion guard, but the logic is still wrong).
|
|
354
|
+
**Fix:** Use `computed` for derived state. If a watcher must write, ensure it writes to a
|
|
355
|
+
*different* source or use a guard condition.
|
|
356
|
+
|
|
357
|
+
### 2.14 Not Using `shallowRef` for Large Non-Reactive Data
|
|
358
|
+
|
|
359
|
+
**Problem:** `ref()` deeply proxies its value. For large datasets (10K+ items) that are
|
|
360
|
+
replaced wholesale but never deeply mutated, deep reactivity wastes memory and CPU.
|
|
361
|
+
**Fix:** Use `shallowRef()` and trigger updates via reassignment: `data.value = newData`.
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## 3. Testing Strategy
|
|
366
|
+
|
|
367
|
+
### 3.1 Component Testing (Vitest + Vue Test Utils / @testing-library/vue)
|
|
368
|
+
|
|
369
|
+
Vitest is the recommended test runner for Vue 3 + Vite projects. It shares Vite's config
|
|
370
|
+
and transform pipeline, ensuring consistency between dev and test environments.
|
|
371
|
+
|
|
372
|
+
```typescript
|
|
373
|
+
// UserCard.test.ts
|
|
374
|
+
import { describe, it, expect } from 'vitest'
|
|
375
|
+
import { mount } from '@vue/test-utils'
|
|
376
|
+
import UserCard from './UserCard.vue'
|
|
377
|
+
|
|
378
|
+
describe('UserCard', () => {
|
|
379
|
+
it('renders user name', () => {
|
|
380
|
+
const wrapper = mount(UserCard, {
|
|
381
|
+
props: { name: 'Ada Lovelace', role: 'Engineer' }
|
|
382
|
+
})
|
|
383
|
+
expect(wrapper.text()).toContain('Ada Lovelace')
|
|
384
|
+
})
|
|
385
|
+
|
|
386
|
+
it('emits select event on click', async () => {
|
|
387
|
+
const wrapper = mount(UserCard, {
|
|
388
|
+
props: { name: 'Ada', role: 'Engineer' }
|
|
389
|
+
})
|
|
390
|
+
await wrapper.find('[data-testid="select-btn"]').trigger('click')
|
|
391
|
+
expect(wrapper.emitted('select')).toHaveLength(1)
|
|
392
|
+
})
|
|
393
|
+
})
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
**@testing-library/vue** — tests from the user's perspective (queries by role, text, label):
|
|
397
|
+
|
|
398
|
+
```typescript
|
|
399
|
+
import { render, screen, fireEvent } from '@testing-library/vue'
|
|
400
|
+
|
|
401
|
+
it('shows greeting after button click', async () => {
|
|
402
|
+
render(GreetingButton, { props: { name: 'Ada' } })
|
|
403
|
+
await fireEvent.click(screen.getByRole('button', { name: /greet/i }))
|
|
404
|
+
expect(screen.getByText('Hello, Ada!')).toBeInTheDocument()
|
|
405
|
+
})
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### 3.2 Composable Testing
|
|
409
|
+
|
|
410
|
+
Test composables by mounting them inside a minimal host component:
|
|
411
|
+
|
|
412
|
+
```typescript
|
|
413
|
+
import { mount } from '@vue/test-utils'
|
|
414
|
+
import { defineComponent } from 'vue'
|
|
415
|
+
import { useCounter } from './useCounter'
|
|
416
|
+
|
|
417
|
+
function withSetup<T>(composable: () => T) {
|
|
418
|
+
let result: T
|
|
419
|
+
const comp = defineComponent({
|
|
420
|
+
setup() {
|
|
421
|
+
result = composable()
|
|
422
|
+
return {}
|
|
423
|
+
},
|
|
424
|
+
render: () => null
|
|
425
|
+
})
|
|
426
|
+
const wrapper = mount(comp)
|
|
427
|
+
return { result: result!, wrapper }
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
it('increments count', () => {
|
|
431
|
+
const { result } = withSetup(() => useCounter(5))
|
|
432
|
+
expect(result.count.value).toBe(5)
|
|
433
|
+
result.increment()
|
|
434
|
+
expect(result.count.value).toBe(6)
|
|
435
|
+
})
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
For composables that do not depend on lifecycle hooks or provide/inject, test them
|
|
439
|
+
as plain functions without a host component.
|
|
440
|
+
|
|
441
|
+
### 3.3 Pinia Store Testing
|
|
442
|
+
|
|
443
|
+
Use `@pinia/testing` with `createTestingPinia`:
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
import { setActivePinia, createPinia } from 'pinia'
|
|
447
|
+
import { useCartStore } from './useCartStore'
|
|
448
|
+
|
|
449
|
+
describe('CartStore', () => {
|
|
450
|
+
beforeEach(() => {
|
|
451
|
+
setActivePinia(createPinia())
|
|
452
|
+
})
|
|
453
|
+
|
|
454
|
+
it('calculates total price', () => {
|
|
455
|
+
const cart = useCartStore()
|
|
456
|
+
cart.items = [
|
|
457
|
+
{ id: '1', name: 'Widget', price: 10, qty: 2 },
|
|
458
|
+
{ id: '2', name: 'Gadget', price: 25, qty: 1 }
|
|
459
|
+
]
|
|
460
|
+
expect(cart.totalPrice).toBe(45)
|
|
461
|
+
})
|
|
462
|
+
})
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
For component tests that need Pinia, use `createTestingPinia({ createSpy: vi.fn })` as a
|
|
466
|
+
plugin. Actions are auto-stubbed with `vi.fn`, allowing assertion without side effects.
|
|
467
|
+
|
|
468
|
+
### 3.4 E2E Testing (Playwright / Cypress)
|
|
469
|
+
|
|
470
|
+
**Playwright (recommended for new projects in 2025+):**
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
import { test, expect } from '@playwright/test'
|
|
474
|
+
|
|
475
|
+
test('user can log in and see dashboard', async ({ page }) => {
|
|
476
|
+
await page.goto('/login')
|
|
477
|
+
await page.getByLabel('Email').fill('user@example.com')
|
|
478
|
+
await page.getByLabel('Password').fill('secret')
|
|
479
|
+
await page.getByRole('button', { name: 'Sign in' }).click()
|
|
480
|
+
await expect(page.getByRole('heading', { name: 'Dashboard' })).toBeVisible()
|
|
481
|
+
})
|
|
482
|
+
```
|
|
483
|
+
|
|
484
|
+
**Recommended testing distribution (inverted pyramid):**
|
|
485
|
+
- ~70% — Integration tests (Vitest browser mode, component + composable together)
|
|
486
|
+
- ~20% — Unit tests for pure logic (composables, utils, store getters)
|
|
487
|
+
- ~10% — E2E tests for critical user flows (login, checkout, onboarding)
|
|
488
|
+
|
|
489
|
+
### 3.5 Snapshot Testing
|
|
490
|
+
|
|
491
|
+
Use sparingly. Snapshots are useful for catching unintended template changes in stable,
|
|
492
|
+
presentational components. Avoid for components with dynamic data (timestamps, IDs).
|
|
493
|
+
|
|
494
|
+
```typescript
|
|
495
|
+
it('matches snapshot', () => {
|
|
496
|
+
const wrapper = mount(AppFooter)
|
|
497
|
+
expect(wrapper.html()).toMatchSnapshot()
|
|
498
|
+
})
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## 4. Performance Considerations
|
|
504
|
+
|
|
505
|
+
### 4.1 Virtual DOM Optimization
|
|
506
|
+
|
|
507
|
+
- **`v-once`** — renders an element/component once, skips all future re-renders. Use for
|
|
508
|
+
truly static content (legal text, copyright notices).
|
|
509
|
+
- **`v-memo`** (Vue 3.2+) — conditionally memoizes a subtree. Re-renders only when
|
|
510
|
+
specified dependencies change. Especially impactful in large `v-for` lists:
|
|
511
|
+
|
|
512
|
+
```vue
|
|
513
|
+
<div v-for="item in list" :key="item.id" v-memo="[item.id, item.selected]">
|
|
514
|
+
<ExpensiveComponent :item="item" />
|
|
515
|
+
</div>
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
- **`shallowRef` / `shallowReactive`** — avoids deep proxy overhead for large data that is
|
|
519
|
+
replaced wholesale rather than mutated in place.
|
|
520
|
+
- **Stable `:key` values** — prevent unnecessary component destruction/recreation.
|
|
521
|
+
|
|
522
|
+
### 4.2 Code Splitting
|
|
523
|
+
|
|
524
|
+
**`defineAsyncComponent`** for lazy-loading heavy components:
|
|
525
|
+
|
|
526
|
+
```typescript
|
|
527
|
+
import { defineAsyncComponent } from 'vue'
|
|
528
|
+
|
|
529
|
+
const HeavyChart = defineAsyncComponent({
|
|
530
|
+
loader: () => import('./HeavyChart.vue'),
|
|
531
|
+
loadingComponent: ChartSkeleton,
|
|
532
|
+
delay: 200, // Show loading after 200ms
|
|
533
|
+
timeout: 10000 // Fail after 10s
|
|
534
|
+
})
|
|
535
|
+
```
|
|
536
|
+
|
|
537
|
+
**Route-level splitting** — Vue Router and Nuxt both support lazy route imports by default.
|
|
538
|
+
In Nuxt, every page is automatically code-split.
|
|
539
|
+
|
|
540
|
+
### 4.3 SSR / SSG with Nuxt 3
|
|
541
|
+
|
|
542
|
+
Nuxt 3 supports hybrid rendering via `routeRules` in `nuxt.config.ts`:
|
|
543
|
+
|
|
544
|
+
```typescript
|
|
545
|
+
export default defineNuxtConfig({
|
|
546
|
+
routeRules: {
|
|
547
|
+
'/': { prerender: true }, // SSG at build time
|
|
548
|
+
'/dashboard/**': { ssr: false }, // SPA (client-only)
|
|
549
|
+
'/blog/**': { isr: 3600 }, // ISR, revalidate every hour
|
|
550
|
+
'/api/**': { cors: true, headers: { 'cache-control': 's-maxage=600' } }
|
|
551
|
+
}
|
|
552
|
+
})
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
Rendering modes:
|
|
556
|
+
| Mode | When HTML is Generated | Best For |
|
|
557
|
+
|------|--------------------------------|-----------------------------------|
|
|
558
|
+
| SSR | Every request (server) | Dynamic, personalized pages |
|
|
559
|
+
| SSG | Build time | Marketing, docs, blogs |
|
|
560
|
+
| ISR | First request, then cached | Content that changes periodically |
|
|
561
|
+
| SPA | Client-side only | Admin panels, authenticated apps |
|
|
562
|
+
|
|
563
|
+
### 4.4 Bundle Size Optimization
|
|
564
|
+
|
|
565
|
+
- **Tree shaking** — Vue 3 and Pinia are fully tree-shakable. Import only what you use.
|
|
566
|
+
- **Analyze bundles** with `npx vite-bundle-visualizer` or `nuxt analyze`
|
|
567
|
+
- **Externalize large deps** — move heavy libraries (chart.js, monaco) to async components
|
|
568
|
+
- **Image optimization** — use `<NuxtImage>` or `<NuxtPicture>` for automatic format
|
|
569
|
+
conversion (WebP/AVIF), resizing, and lazy loading
|
|
570
|
+
- **Font optimization** — use `@nuxtjs/fontaine` to reduce CLS from web fonts
|
|
571
|
+
|
|
572
|
+
### 4.5 Core Web Vitals
|
|
573
|
+
|
|
574
|
+
| Metric | Target | Vue-Specific Strategy |
|
|
575
|
+
|--------|----------|----------------------------------------------------------|
|
|
576
|
+
| LCP | < 2.5s | SSR/SSG, preload hero images, font-display: swap |
|
|
577
|
+
| INP | < 200ms | Avoid long synchronous scripts in event handlers |
|
|
578
|
+
| CLS | < 0.1 | Set explicit dimensions on images/embeds, fontaine |
|
|
579
|
+
| FCP | < 1.8s | SSR, inline critical CSS, reduce JS bundle |
|
|
580
|
+
| TTFB | < 800ms | Edge deployment (Cloudflare Workers, Vercel Edge) |
|
|
581
|
+
|
|
582
|
+
---
|
|
583
|
+
|
|
584
|
+
## 5. Security Considerations
|
|
585
|
+
|
|
586
|
+
### 5.1 XSS Prevention
|
|
587
|
+
|
|
588
|
+
- Vue automatically escapes all interpolated content (`{{ }}`) — this is the primary defense
|
|
589
|
+
- **`v-html` bypasses escaping entirely.** Never use with user-supplied content unless
|
|
590
|
+
sanitized with DOMPurify:
|
|
591
|
+
|
|
592
|
+
```typescript
|
|
593
|
+
import DOMPurify from 'dompurify'
|
|
594
|
+
const safeHtml = computed(() => DOMPurify.sanitize(rawHtml.value))
|
|
595
|
+
```
|
|
596
|
+
|
|
597
|
+
- Avoid dynamically constructing `href` with `javascript:` protocol — Vue warns but does
|
|
598
|
+
not block this
|
|
599
|
+
- Do not use user input in `<component :is="userInput">` — this allows arbitrary component
|
|
600
|
+
instantiation
|
|
601
|
+
|
|
602
|
+
### 5.2 CSRF Protection
|
|
603
|
+
|
|
604
|
+
- Backend should issue CSRF tokens; Vue apps should send them via headers or hidden fields
|
|
605
|
+
- Nuxt's `useFetch` / `$fetch` (built on ofetch) can be configured to include credentials
|
|
606
|
+
and CSRF tokens automatically
|
|
607
|
+
- Use `SameSite=Lax` or `Strict` on session cookies
|
|
608
|
+
- For token-based auth (JWT), store tokens in `httpOnly` cookies (not localStorage)
|
|
609
|
+
|
|
610
|
+
### 5.3 Authentication Patterns in Nuxt
|
|
611
|
+
|
|
612
|
+
**Recommended modules (2025):**
|
|
613
|
+
|
|
614
|
+
- **nuxt-auth-utils** — minimalist, uses sealed cookies, supports OAuth providers (Google,
|
|
615
|
+
GitHub, etc.) and WebAuthn/passkeys
|
|
616
|
+
- **@sidebase/nuxt-auth** — full-featured, supports Auth.js/NextAuth providers and
|
|
617
|
+
credential-based local auth
|
|
618
|
+
- **Custom middleware** — for simple JWT flows, write route middleware that checks token
|
|
619
|
+
validity and redirects to login
|
|
620
|
+
|
|
621
|
+
Pattern: protect routes with named middleware:
|
|
622
|
+
|
|
623
|
+
```vue
|
|
624
|
+
<!-- pages/admin.vue -->
|
|
625
|
+
<script setup>
|
|
626
|
+
definePageMeta({ middleware: 'auth' })
|
|
627
|
+
</script>
|
|
628
|
+
```
|
|
629
|
+
|
|
630
|
+
### 5.4 Content Security Policy (CSP)
|
|
631
|
+
|
|
632
|
+
- Configure CSP headers in Nuxt via `nitro.routeRules` or server middleware
|
|
633
|
+
- Vue's runtime does not require `unsafe-eval` (unlike some older frameworks)
|
|
634
|
+
- If using Nuxt's inline styles, you may need `style-src 'unsafe-inline'` or use nonces
|
|
635
|
+
- Use `helmet` middleware in Nitro for comprehensive security headers
|
|
636
|
+
|
|
637
|
+
```typescript
|
|
638
|
+
// server/middleware/security.ts
|
|
639
|
+
export default defineEventHandler((event) => {
|
|
640
|
+
setResponseHeaders(event, {
|
|
641
|
+
'Content-Security-Policy': "default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'",
|
|
642
|
+
'X-Content-Type-Options': 'nosniff',
|
|
643
|
+
'X-Frame-Options': 'DENY'
|
|
644
|
+
})
|
|
645
|
+
})
|
|
646
|
+
```
|
|
647
|
+
|
|
648
|
+
---
|
|
649
|
+
|
|
650
|
+
## 6. Integration Patterns
|
|
651
|
+
|
|
652
|
+
### 6.1 API Integration
|
|
653
|
+
|
|
654
|
+
**Nuxt 3 — `useFetch` / `useAsyncData`:**
|
|
655
|
+
|
|
656
|
+
```vue
|
|
657
|
+
<script setup>
|
|
658
|
+
const { data: posts, pending, error, refresh } = await useFetch('/api/posts', {
|
|
659
|
+
query: { page: currentPage },
|
|
660
|
+
transform: (raw) => raw.map(normalizePost)
|
|
661
|
+
})
|
|
662
|
+
</script>
|
|
663
|
+
```
|
|
664
|
+
|
|
665
|
+
`useFetch` is SSR-safe (deduplicates requests between server and client), handles loading
|
|
666
|
+
and error states, and is auto-imported.
|
|
667
|
+
|
|
668
|
+
**ofetch (standalone Vue or Nuxt server routes):**
|
|
669
|
+
|
|
670
|
+
```typescript
|
|
671
|
+
import { ofetch } from 'ofetch'
|
|
672
|
+
|
|
673
|
+
const api = ofetch.create({
|
|
674
|
+
baseURL: '/api',
|
|
675
|
+
onRequest({ options }) {
|
|
676
|
+
options.headers.set('Authorization', `Bearer ${token.value}`)
|
|
677
|
+
},
|
|
678
|
+
onResponseError({ response }) {
|
|
679
|
+
if (response.status === 401) navigateTo('/login')
|
|
680
|
+
}
|
|
681
|
+
})
|
|
682
|
+
```
|
|
683
|
+
|
|
684
|
+
**TanStack Query (@tanstack/vue-query v5):**
|
|
685
|
+
|
|
686
|
+
Use when you need advanced caching, background refetching, optimistic updates, or
|
|
687
|
+
infinite scroll. Do NOT mix with Nuxt's `useFetch` — choose one data-fetching strategy.
|
|
688
|
+
|
|
689
|
+
```typescript
|
|
690
|
+
import { useQuery } from '@tanstack/vue-query'
|
|
691
|
+
|
|
692
|
+
const { data, isLoading, error } = useQuery({
|
|
693
|
+
queryKey: ['posts', page],
|
|
694
|
+
queryFn: () => $fetch(`/api/posts?page=${page.value}`),
|
|
695
|
+
staleTime: 5 * 60 * 1000 // 5 minutes
|
|
696
|
+
})
|
|
697
|
+
```
|
|
698
|
+
|
|
699
|
+
### 6.2 Form Handling
|
|
700
|
+
|
|
701
|
+
**VeeValidate 4 + Yup/Zod** — validation-first approach:
|
|
702
|
+
|
|
703
|
+
```vue
|
|
704
|
+
<script setup>
|
|
705
|
+
import { useForm, useField } from 'vee-validate'
|
|
706
|
+
import * as yup from 'yup'
|
|
707
|
+
|
|
708
|
+
const schema = yup.object({
|
|
709
|
+
email: yup.string().required().email(),
|
|
710
|
+
password: yup.string().required().min(8)
|
|
711
|
+
})
|
|
712
|
+
|
|
713
|
+
const { handleSubmit, errors } = useForm({ validationSchema: schema })
|
|
714
|
+
const { value: email } = useField('email')
|
|
715
|
+
const { value: password } = useField('password')
|
|
716
|
+
|
|
717
|
+
const onSubmit = handleSubmit(async (values) => {
|
|
718
|
+
await loginUser(values)
|
|
719
|
+
})
|
|
720
|
+
</script>
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
**FormKit** — form-building framework with built-in validation, schema-driven forms,
|
|
724
|
+
accessibility, and theming. Preferred for complex forms (wizards, repeating groups).
|
|
725
|
+
|
|
726
|
+
### 6.3 CMS Integration
|
|
727
|
+
|
|
728
|
+
- **Nuxt Content** — file-based CMS using Markdown/YAML/JSON in `content/` directory
|
|
729
|
+
- **Strapi / Directus / Sanity** — headless CMS with Nuxt modules for data fetching
|
|
730
|
+
- Use `useFetch` or TanStack Query for API-driven CMS content
|
|
731
|
+
- Leverage ISR (`routeRules: { '/blog/**': { isr: 3600 } }`) for CMS-driven pages
|
|
732
|
+
|
|
733
|
+
### 6.4 Real-Time Communication
|
|
734
|
+
|
|
735
|
+
**Socket.io:**
|
|
736
|
+
|
|
737
|
+
```typescript
|
|
738
|
+
// composables/useSocket.ts
|
|
739
|
+
import { io, Socket } from 'socket.io-client'
|
|
740
|
+
import { ref, onUnmounted } from 'vue'
|
|
741
|
+
|
|
742
|
+
export function useSocket(url: string) {
|
|
743
|
+
const socket: Socket = io(url)
|
|
744
|
+
const connected = ref(false)
|
|
745
|
+
|
|
746
|
+
socket.on('connect', () => { connected.value = true })
|
|
747
|
+
socket.on('disconnect', () => { connected.value = false })
|
|
748
|
+
|
|
749
|
+
onUnmounted(() => { socket.disconnect() })
|
|
750
|
+
|
|
751
|
+
return { socket, connected }
|
|
752
|
+
}
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
**Server-Sent Events (SSE):** Lighter alternative for one-way server-to-client streaming.
|
|
756
|
+
Use native `EventSource` API wrapped in a composable with reconnection logic.
|
|
757
|
+
|
|
758
|
+
---
|
|
759
|
+
|
|
760
|
+
## 7. DevOps & Deployment
|
|
761
|
+
|
|
762
|
+
### 7.1 Build Tools
|
|
763
|
+
|
|
764
|
+
- **Vite 6.x** — default build tool for Vue 3 and Nuxt 3. HMR in <50ms for most projects.
|
|
765
|
+
- **Nuxt 3 + Nitro** — Nitro compiles server code for multiple deployment targets
|
|
766
|
+
(Node.js, Cloudflare Workers, Vercel Edge, Deno, AWS Lambda)
|
|
767
|
+
- Use `vite-bundle-visualizer` or `nuxt analyze` to audit bundle composition
|
|
768
|
+
|
|
769
|
+
### 7.2 Docker Patterns
|
|
770
|
+
|
|
771
|
+
**Vue 3 SPA (multi-stage build):**
|
|
772
|
+
|
|
773
|
+
```dockerfile
|
|
774
|
+
# Build stage
|
|
775
|
+
FROM node:22-alpine AS build
|
|
776
|
+
WORKDIR /app
|
|
777
|
+
COPY package*.json ./
|
|
778
|
+
RUN npm ci
|
|
779
|
+
COPY . .
|
|
780
|
+
RUN npm run build
|
|
781
|
+
|
|
782
|
+
# Production stage
|
|
783
|
+
FROM nginx:alpine
|
|
784
|
+
COPY --from=build /app/dist /usr/share/nginx/html
|
|
785
|
+
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
|
786
|
+
EXPOSE 80
|
|
787
|
+
```
|
|
788
|
+
|
|
789
|
+
**Nuxt 3 SSR:**
|
|
790
|
+
|
|
791
|
+
```dockerfile
|
|
792
|
+
FROM node:22-alpine AS build
|
|
793
|
+
WORKDIR /app
|
|
794
|
+
COPY package*.json ./
|
|
795
|
+
RUN npm ci
|
|
796
|
+
COPY . .
|
|
797
|
+
RUN npx nuxt build
|
|
798
|
+
|
|
799
|
+
FROM node:22-alpine
|
|
800
|
+
WORKDIR /app
|
|
801
|
+
COPY --from=build /app/.output /app/.output
|
|
802
|
+
ENV NITRO_PORT=3000
|
|
803
|
+
EXPOSE 3000
|
|
804
|
+
CMD ["node", ".output/server/index.mjs"]
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
### 7.3 CI/CD & Preview Deployments
|
|
808
|
+
|
|
809
|
+
- Run `vitest run` and `vue-tsc --noEmit` in CI before build
|
|
810
|
+
- Use `npx playwright test` for E2E in CI (with `playwright install --with-deps` in setup)
|
|
811
|
+
- **Preview deployments:** Vercel, Netlify, and Cloudflare Pages auto-deploy PRs
|
|
812
|
+
- For self-hosted: use Docker + GitHub Actions to deploy per-PR containers
|
|
813
|
+
|
|
814
|
+
**GitHub Actions example (lint + test + build):**
|
|
815
|
+
|
|
816
|
+
```yaml
|
|
817
|
+
jobs:
|
|
818
|
+
ci:
|
|
819
|
+
runs-on: ubuntu-latest
|
|
820
|
+
steps:
|
|
821
|
+
- uses: actions/checkout@v4
|
|
822
|
+
- uses: actions/setup-node@v4
|
|
823
|
+
with: { node-version: 22 }
|
|
824
|
+
- run: npm ci
|
|
825
|
+
- run: npm run lint
|
|
826
|
+
- run: npm run type-check
|
|
827
|
+
- run: npm run test:unit -- --run
|
|
828
|
+
- run: npm run build
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
### 7.4 Environment Configuration
|
|
832
|
+
|
|
833
|
+
- **Vite:** `VITE_` prefixed env vars are exposed to client code via `import.meta.env`
|
|
834
|
+
- **Nuxt 3:** Use `runtimeConfig` in `nuxt.config.ts`:
|
|
835
|
+
|
|
836
|
+
```typescript
|
|
837
|
+
export default defineNuxtConfig({
|
|
838
|
+
runtimeConfig: {
|
|
839
|
+
secretApiKey: '', // Server-only (from NUXT_SECRET_API_KEY)
|
|
840
|
+
public: {
|
|
841
|
+
apiBase: '/api' // Client-exposed (from NUXT_PUBLIC_API_BASE)
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
})
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
Access in components: `useRuntimeConfig().public.apiBase`
|
|
848
|
+
Access in server routes: `useRuntimeConfig().secretApiKey`
|
|
849
|
+
|
|
850
|
+
### 7.5 Monitoring
|
|
851
|
+
|
|
852
|
+
- **Sentry** — `@sentry/vue` for error tracking; `@sentry/nuxt` for Nuxt integration
|
|
853
|
+
(includes server-side error capture via Nitro)
|
|
854
|
+
- **Vercel Analytics / Speed Insights** — Core Web Vitals monitoring for Vercel-deployed apps
|
|
855
|
+
- Use `reportWebVitals()` from `web-vitals` library for custom CWV reporting
|
|
856
|
+
- Nuxt DevTools (in development) provides component inspector, route visualization,
|
|
857
|
+
payload analysis, and server API testing
|
|
858
|
+
|
|
859
|
+
---
|
|
860
|
+
|
|
861
|
+
## 8. Decision Trees
|
|
862
|
+
|
|
863
|
+
### 8.1 Vue SPA vs Nuxt?
|
|
864
|
+
|
|
865
|
+
```
|
|
866
|
+
Need SSR, SSG, or SEO?
|
|
867
|
+
YES -> Nuxt 3
|
|
868
|
+
NO -> Do you need file-based routing, auto-imports, or server API routes?
|
|
869
|
+
YES -> Nuxt 3 (even as SPA via `ssr: false`)
|
|
870
|
+
NO -> Do you need maximum control over build config?
|
|
871
|
+
YES -> Vue 3 + Vite (standalone)
|
|
872
|
+
NO -> Nuxt 3 (convention > configuration saves time)
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
**Rule of thumb:** Default to Nuxt 3 unless you have a specific reason not to (e.g.,
|
|
876
|
+
embedding Vue in a non-Vue application, micro-frontend, or library development).
|
|
877
|
+
|
|
878
|
+
### 8.2 Pinia vs Composable-Based State?
|
|
879
|
+
|
|
880
|
+
```
|
|
881
|
+
Is the state shared across unrelated components or routes?
|
|
882
|
+
YES -> Pinia (global singleton, DevTools, SSR-safe)
|
|
883
|
+
NO -> Is the state scoped to a component subtree?
|
|
884
|
+
YES -> provide/inject or composable with shared ref
|
|
885
|
+
NO -> Is the state local to one component?
|
|
886
|
+
YES -> Component-local ref/reactive
|
|
887
|
+
NO -> Does the state need DevTools debugging or time-travel?
|
|
888
|
+
YES -> Pinia
|
|
889
|
+
NO -> Composable with module-level ref (singleton pattern)
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
### 8.3 Options API vs Composition API?
|
|
893
|
+
|
|
894
|
+
```
|
|
895
|
+
Is this a new project or new component?
|
|
896
|
+
YES -> Composition API with <script setup> (Vue 3 standard)
|
|
897
|
+
NO -> Is the existing codebase Options API?
|
|
898
|
+
YES -> Is there a migration plan?
|
|
899
|
+
YES -> Migrate incrementally (both APIs work in same app)
|
|
900
|
+
NO -> Continue Options API for consistency, but write new
|
|
901
|
+
composables in Composition API
|
|
902
|
+
NO -> Composition API
|
|
903
|
+
|
|
904
|
+
Note: Options API is NOT deprecated, but Composition API is the recommended
|
|
905
|
+
default for Vue 3.4+ projects. It offers better TypeScript support, better
|
|
906
|
+
logic reuse via composables, and more flexible code organization.
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
---
|
|
910
|
+
|
|
911
|
+
## 9. Code Examples
|
|
912
|
+
|
|
913
|
+
### 9.1 Composable with Async Data and Cleanup
|
|
914
|
+
|
|
915
|
+
```typescript
|
|
916
|
+
// composables/usePolling.ts
|
|
917
|
+
import { ref, onUnmounted } from 'vue'
|
|
918
|
+
|
|
919
|
+
export function usePolling<T>(fetcher: () => Promise<T>, intervalMs = 5000) {
|
|
920
|
+
const data = ref<T | null>(null) as Ref<T | null>
|
|
921
|
+
const error = ref<Error | null>(null)
|
|
922
|
+
const isPolling = ref(false)
|
|
923
|
+
let timerId: ReturnType<typeof setInterval> | null = null
|
|
924
|
+
|
|
925
|
+
async function poll() {
|
|
926
|
+
try {
|
|
927
|
+
data.value = await fetcher()
|
|
928
|
+
error.value = null
|
|
929
|
+
} catch (e) {
|
|
930
|
+
error.value = e instanceof Error ? e : new Error(String(e))
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
function start() {
|
|
935
|
+
if (isPolling.value) return
|
|
936
|
+
isPolling.value = true
|
|
937
|
+
poll() // Immediate first fetch
|
|
938
|
+
timerId = setInterval(poll, intervalMs)
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
function stop() {
|
|
942
|
+
if (timerId) clearInterval(timerId)
|
|
943
|
+
timerId = null
|
|
944
|
+
isPolling.value = false
|
|
945
|
+
}
|
|
946
|
+
|
|
947
|
+
onUnmounted(stop)
|
|
948
|
+
|
|
949
|
+
return { data, error, isPolling, start, stop }
|
|
950
|
+
}
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
### 9.2 Pinia Setup Store with Async Action
|
|
954
|
+
|
|
955
|
+
```typescript
|
|
956
|
+
// stores/useUserStore.ts
|
|
957
|
+
import { defineStore } from 'pinia'
|
|
958
|
+
import { ref, computed } from 'vue'
|
|
959
|
+
|
|
960
|
+
interface User { id: string; name: string; email: string; role: string }
|
|
961
|
+
|
|
962
|
+
export const useUserStore = defineStore('user', () => {
|
|
963
|
+
const user = ref<User | null>(null)
|
|
964
|
+
const loading = ref(false)
|
|
965
|
+
|
|
966
|
+
const isAdmin = computed(() => user.value?.role === 'admin')
|
|
967
|
+
const isAuthenticated = computed(() => user.value !== null)
|
|
968
|
+
|
|
969
|
+
async function fetchUser() {
|
|
970
|
+
loading.value = true
|
|
971
|
+
try {
|
|
972
|
+
user.value = await $fetch<User>('/api/me')
|
|
973
|
+
} catch {
|
|
974
|
+
user.value = null
|
|
975
|
+
} finally {
|
|
976
|
+
loading.value = false
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
function logout() {
|
|
981
|
+
user.value = null
|
|
982
|
+
navigateTo('/login')
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
return { user, loading, isAdmin, isAuthenticated, fetchUser, logout }
|
|
986
|
+
})
|
|
987
|
+
```
|
|
988
|
+
|
|
989
|
+
### 9.3 Component with defineModel (Vue 3.4+)
|
|
990
|
+
|
|
991
|
+
```vue
|
|
992
|
+
<!-- components/SearchInput.vue -->
|
|
993
|
+
<script setup lang="ts">
|
|
994
|
+
import { useTemplateRef } from 'vue'
|
|
995
|
+
|
|
996
|
+
const query = defineModel<string>('query', { default: '' })
|
|
997
|
+
const inputRef = useTemplateRef('search-input')
|
|
998
|
+
|
|
999
|
+
function focus() {
|
|
1000
|
+
inputRef.value?.focus()
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
defineExpose({ focus })
|
|
1004
|
+
</script>
|
|
1005
|
+
|
|
1006
|
+
<template>
|
|
1007
|
+
<div class="search-input">
|
|
1008
|
+
<input
|
|
1009
|
+
ref="search-input"
|
|
1010
|
+
v-model="query"
|
|
1011
|
+
type="search"
|
|
1012
|
+
placeholder="Search..."
|
|
1013
|
+
aria-label="Search"
|
|
1014
|
+
/>
|
|
1015
|
+
<button v-if="query" @click="query = ''" aria-label="Clear search">
|
|
1016
|
+
Clear
|
|
1017
|
+
</button>
|
|
1018
|
+
</div>
|
|
1019
|
+
</template>
|
|
1020
|
+
```
|
|
1021
|
+
|
|
1022
|
+
Usage: `<SearchInput v-model:query="searchTerm" />`
|
|
1023
|
+
|
|
1024
|
+
### 9.4 Nuxt Page with useFetch and Error Handling
|
|
1025
|
+
|
|
1026
|
+
```vue
|
|
1027
|
+
<!-- pages/posts/[id].vue -->
|
|
1028
|
+
<script setup lang="ts">
|
|
1029
|
+
const route = useRoute()
|
|
1030
|
+
|
|
1031
|
+
const { data: post, error } = await useFetch(`/api/posts/${route.params.id}`, {
|
|
1032
|
+
transform: (raw) => ({
|
|
1033
|
+
...raw,
|
|
1034
|
+
publishedAt: new Date(raw.publishedAt)
|
|
1035
|
+
})
|
|
1036
|
+
})
|
|
1037
|
+
|
|
1038
|
+
if (error.value) {
|
|
1039
|
+
throw createError({
|
|
1040
|
+
statusCode: error.value.statusCode || 404,
|
|
1041
|
+
statusMessage: 'Post not found'
|
|
1042
|
+
})
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
useHead({
|
|
1046
|
+
title: () => post.value?.title ?? 'Loading...',
|
|
1047
|
+
meta: [{ name: 'description', content: () => post.value?.excerpt ?? '' }]
|
|
1048
|
+
})
|
|
1049
|
+
</script>
|
|
1050
|
+
|
|
1051
|
+
<template>
|
|
1052
|
+
<article v-if="post">
|
|
1053
|
+
<h1>{{ post.title }}</h1>
|
|
1054
|
+
<time :datetime="post.publishedAt.toISOString()">
|
|
1055
|
+
{{ post.publishedAt.toLocaleDateString() }}
|
|
1056
|
+
</time>
|
|
1057
|
+
<div v-html="post.sanitizedContent" />
|
|
1058
|
+
</article>
|
|
1059
|
+
</template>
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
### 9.5 Error Boundary Usage
|
|
1063
|
+
|
|
1064
|
+
```vue
|
|
1065
|
+
<!-- pages/dashboard.vue -->
|
|
1066
|
+
<script setup lang="ts">
|
|
1067
|
+
import ErrorBoundary from '~/components/ErrorBoundary.vue'
|
|
1068
|
+
</script>
|
|
1069
|
+
|
|
1070
|
+
<template>
|
|
1071
|
+
<div class="dashboard">
|
|
1072
|
+
<h1>Dashboard</h1>
|
|
1073
|
+
<ErrorBoundary>
|
|
1074
|
+
<RiskyWidget />
|
|
1075
|
+
<template #fallback="{ error, reset }">
|
|
1076
|
+
<div class="error-card" role="alert">
|
|
1077
|
+
<p>Widget failed: {{ error.message }}</p>
|
|
1078
|
+
<button @click="reset">Retry</button>
|
|
1079
|
+
</div>
|
|
1080
|
+
</template>
|
|
1081
|
+
</ErrorBoundary>
|
|
1082
|
+
<StableWidget /> <!-- Unaffected by RiskyWidget errors -->
|
|
1083
|
+
</div>
|
|
1084
|
+
</template>
|
|
1085
|
+
```
|
|
1086
|
+
|
|
1087
|
+
---
|
|
1088
|
+
|
|
1089
|
+
*Researched: 2026-03-07 | Sources: [Vue.js Official Docs](https://vuejs.org/guide/best-practices/performance), [Vue 3.5 Announcement](https://blog.vuejs.org/posts/vue-3-5), [Vue 3.4 Announcement](https://blog.vuejs.org/posts/vue-3-4), [Pinia Official Docs](https://pinia.vuejs.org/core-concepts/), [Nuxt 3 Directory Structure](https://nuxt.com/docs/3.x/directory-structure), [eslint-plugin-vue Rules](https://eslint.vuejs.org/rules/), [Vue Security Guide](https://vuejs.org/guide/best-practices/security), [Vue Test Utils](https://test-utils.vuejs.org/guide/), [Nuxt Hybrid Rendering (Vue School)](https://vueschool.io/articles/vuejs-tutorials/hybrid-rendering-in-nuxt-js-3/), [Composables vs Pinia vs Provide/Inject](https://vueschool.io/articles/vuejs-tutorials/composables-vs-provide-inject-vs-pinia-when-to-use-what/), [TanStack Vue Query](https://tanstack.com/query/v5/docs/framework/vue/examples/nuxt3), [VeeValidate 4](https://vee-validate.logaretm.com/v4/), [FormKit](https://formkit.com/), [Sidebase Nuxt Auth](https://nuxt.com/modules/sidebase-auth), [Nuxt Auth Utils](https://nuxt.com/modules/auth-utils), [Vue Error Boundary (Vue School)](https://vueschool.io/articles/vuejs-tutorials/what-is-a-vue-js-error-boundary-component/), [Pinia Testing Docs](https://pinia.vuejs.org/cookbook/testing.html), [Vue 3 Docker Deployment](https://marcusn.dev/articles/2025-01/setup-vue-docker-nginx), [Nuxt 3 Docker](https://markus.oberlehner.net/blog/running-nuxt-3-in-a-docker-container)*
|