cfsa-antigravity 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/bin/cli.mjs +324 -0
- package/package.json +34 -0
- package/template/.agent/instructions/commands.md +48 -0
- package/template/.agent/instructions/patterns.md +61 -0
- package/template/.agent/instructions/structure.md +29 -0
- package/template/.agent/instructions/tech-stack.md +43 -0
- package/template/.agent/instructions/workflow.md +41 -0
- package/template/.agent/kit-sync.md +15 -0
- package/template/.agent/rules/boundary-not-placeholder.md +146 -0
- package/template/.agent/rules/completion-checklist.md +48 -0
- package/template/.agent/rules/decision-classification.md +103 -0
- package/template/.agent/rules/extensibility.md +47 -0
- package/template/.agent/rules/question-vs-command.md +81 -0
- package/template/.agent/rules/security-first.md +43 -0
- package/template/.agent/rules/specificity-standards.md +54 -0
- package/template/.agent/rules/tdd-contract-first.md +57 -0
- package/template/.agent/rules/vertical-slices.md +42 -0
- package/template/.agent/skill-library/MANIFEST.md +480 -0
- package/template/.agent/skill-library/README.md +38 -0
- package/template/.agent/skill-library/meta/brand-guidelines/SKILL.md +73 -0
- package/template/.agent/skill-library/meta/claude-code/README.md +9 -0
- package/template/.agent/skill-library/meta/claude-code/agent-development/SKILL.md +415 -0
- package/template/.agent/skill-library/meta/claude-code/hook-development/SKILL.md +712 -0
- package/template/.agent/skill-library/meta/claude-code/plugin-structure/SKILL.md +476 -0
- package/template/.agent/skill-library/meta/git-advanced/SKILL.md +972 -0
- package/template/.agent/skill-library/meta/mcp-builder/SKILL.md +236 -0
- package/template/.agent/skill-library/meta/product-marketing-context/SKILL.md +241 -0
- package/template/.agent/skill-library/meta/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skill-library/meta/tmux-processes/SKILL.md +210 -0
- package/template/.agent/skill-library/meta/using-tmux-for-interactive-commands/SKILL.md +178 -0
- package/template/.agent/skill-library/stack/3d/threejs-pro/SKILL.md +300 -0
- package/template/.agent/skill-library/stack/ai/ai-sdk/SKILL.md +77 -0
- package/template/.agent/skill-library/stack/ai/langchain/SKILL.md +530 -0
- package/template/.agent/skill-library/stack/ai/ollama/SKILL.md +321 -0
- package/template/.agent/skill-library/stack/ai/openai-sdk/SKILL.md +549 -0
- package/template/.agent/skill-library/stack/analytics/google-analytics/SKILL.md +153 -0
- package/template/.agent/skill-library/stack/api/graphql/SKILL.md +1061 -0
- package/template/.agent/skill-library/stack/api/trpc/SKILL.md +576 -0
- package/template/.agent/skill-library/stack/auth/authjs/SKILL.md +569 -0
- package/template/.agent/skill-library/stack/auth/clerk/SKILL.md +590 -0
- package/template/.agent/skill-library/stack/auth/firebase-auth/SKILL.md +734 -0
- package/template/.agent/skill-library/stack/cms/payload-cms/SKILL.md +573 -0
- package/template/.agent/skill-library/stack/cms/shopify/SKILL.md +1193 -0
- package/template/.agent/skill-library/stack/cms/wordpress/SKILL.md +1104 -0
- package/template/.agent/skill-library/stack/css/sass-scss/SKILL.md +1121 -0
- package/template/.agent/skill-library/stack/css/tailwind-css-patterns/SKILL.md +863 -0
- package/template/.agent/skill-library/stack/css/tailwind-design-system/SKILL.md +490 -0
- package/template/.agent/skill-library/stack/css/vanilla-css/SKILL.md +1078 -0
- package/template/.agent/skill-library/stack/databases/clickhouse/SKILL.md +311 -0
- package/template/.agent/skill-library/stack/databases/influxdb/SKILL.md +280 -0
- package/template/.agent/skill-library/stack/databases/lancedb/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/databases/mongodb/SKILL.md +1169 -0
- package/template/.agent/skill-library/stack/databases/neo4j/SKILL.md +839 -0
- package/template/.agent/skill-library/stack/databases/pgvector/SKILL.md +241 -0
- package/template/.agent/skill-library/stack/databases/pinecone/SKILL.md +212 -0
- package/template/.agent/skill-library/stack/databases/postgresql/SKILL.md +658 -0
- package/template/.agent/skill-library/stack/databases/qdrant/SKILL.md +312 -0
- package/template/.agent/skill-library/stack/databases/redis/SKILL.md +1079 -0
- package/template/.agent/skill-library/stack/databases/spacetimedb/SKILL.md +532 -0
- package/template/.agent/skill-library/stack/databases/sqlite/SKILL.md +1132 -0
- package/template/.agent/skill-library/stack/databases/supabase/SKILL.md +640 -0
- package/template/.agent/skill-library/stack/databases/surrealdb-expert/SKILL.md +945 -0
- package/template/.agent/skill-library/stack/databases/timescaledb/SKILL.md +745 -0
- package/template/.agent/skill-library/stack/databases/weaviate/SKILL.md +218 -0
- package/template/.agent/skill-library/stack/devops/github-actions/SKILL.md +554 -0
- package/template/.agent/skill-library/stack/devops/kubernetes/SKILL.md +950 -0
- package/template/.agent/skill-library/stack/devops/nginx/SKILL.md +841 -0
- package/template/.agent/skill-library/stack/devops/terraform/SKILL.md +860 -0
- package/template/.agent/skill-library/stack/email/resend/SKILL.md +391 -0
- package/template/.agent/skill-library/stack/engines/godot/SKILL.md +488 -0
- package/template/.agent/skill-library/stack/extensions/chrome-extension/SKILL.md +375 -0
- package/template/.agent/skill-library/stack/extensions/vscode-extension/SKILL.md +453 -0
- package/template/.agent/skill-library/stack/frameworks/astro-framework/SKILL.md +162 -0
- package/template/.agent/skill-library/stack/frameworks/electron/SKILL.md +1286 -0
- package/template/.agent/skill-library/stack/frameworks/fastapi/SKILL.md +650 -0
- package/template/.agent/skill-library/stack/frameworks/hono/SKILL.md +90 -0
- package/template/.agent/skill-library/stack/frameworks/nestjs/SKILL.md +878 -0
- package/template/.agent/skill-library/stack/frameworks/nextjs/SKILL.md +635 -0
- package/template/.agent/skill-library/stack/frameworks/nuxt/SKILL.md +564 -0
- package/template/.agent/skill-library/stack/frameworks/sveltekit/SKILL.md +614 -0
- package/template/.agent/skill-library/stack/frameworks/tauri/SKILL.md +920 -0
- package/template/.agent/skill-library/stack/gamedev/godot/SKILL.md +1032 -0
- package/template/.agent/skill-library/stack/gamedev/unity/SKILL.md +1175 -0
- package/template/.agent/skill-library/stack/hosting/aws/SKILL.md +467 -0
- package/template/.agent/skill-library/stack/hosting/cloudflare/SKILL.md +201 -0
- package/template/.agent/skill-library/stack/hosting/docker-expert/SKILL.md +409 -0
- package/template/.agent/skill-library/stack/hosting/vercel/SKILL.md +484 -0
- package/template/.agent/skill-library/stack/languages/bash-scripting/SKILL.md +773 -0
- package/template/.agent/skill-library/stack/languages/c-cpp/SKILL.md +712 -0
- package/template/.agent/skill-library/stack/languages/gdscript/SKILL.md +789 -0
- package/template/.agent/skill-library/stack/languages/go/SKILL.md +664 -0
- package/template/.agent/skill-library/stack/languages/java/SKILL.md +778 -0
- package/template/.agent/skill-library/stack/languages/kotlin/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/languages/python/SKILL.md +678 -0
- package/template/.agent/skill-library/stack/languages/rust/SKILL.md +673 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/SKILL.md +141 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/advanced-generics.md +90 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/branded-types.md +57 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/builder-pattern.md +71 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/common-pitfalls.md +135 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/conditional-types.md +27 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/decorators.md +98 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/discriminated-unions.md +62 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/mapped-types.md +53 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/performance-best-practices.md +104 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/template-literal-types.md +49 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/testing-types.md +112 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-guards.md +70 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/type-inference.md +101 -0
- package/template/.agent/skill-library/stack/languages/typescript-advanced-patterns/references/utility-types.md +98 -0
- package/template/.agent/skill-library/stack/languages/vanilla-javascript/SKILL.md +803 -0
- package/template/.agent/skill-library/stack/messaging/kafka/SKILL.md +235 -0
- package/template/.agent/skill-library/stack/mobile/expo-react-native/SKILL.md +665 -0
- package/template/.agent/skill-library/stack/mobile/flutter/SKILL.md +316 -0
- package/template/.agent/skill-library/stack/mobile/react-native/SKILL.md +337 -0
- package/template/.agent/skill-library/stack/monitoring/posthog/SKILL.md +396 -0
- package/template/.agent/skill-library/stack/monitoring/sentry/SKILL.md +509 -0
- package/template/.agent/skill-library/stack/observability/datadog/SKILL.md +179 -0
- package/template/.agent/skill-library/stack/observability/distributed-tracing/SKILL.md +140 -0
- package/template/.agent/skill-library/stack/observability/logging-best-practices/SKILL.md +168 -0
- package/template/.agent/skill-library/stack/observability/opentelemetry/SKILL.md +164 -0
- package/template/.agent/skill-library/stack/observability/prometheus-grafana/SKILL.md +246 -0
- package/template/.agent/skill-library/stack/observability/python-observability/SKILL.md +158 -0
- package/template/.agent/skill-library/stack/orm/drizzle-orm/SKILL.md +613 -0
- package/template/.agent/skill-library/stack/orm/prisma/SKILL.md +744 -0
- package/template/.agent/skill-library/stack/payments/lemonsqueezy/SKILL.md +393 -0
- package/template/.agent/skill-library/stack/payments/stripe-integration/SKILL.md +457 -0
- package/template/.agent/skill-library/stack/queue/bullmq/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/queue/inngest/SKILL.md +438 -0
- package/template/.agent/skill-library/stack/realtime/socketio/SKILL.md +595 -0
- package/template/.agent/skill-library/stack/search/elasticsearch/SKILL.md +248 -0
- package/template/.agent/skill-library/stack/search/meilisearch/SKILL.md +385 -0
- package/template/.agent/skill-library/stack/security/crypto-patterns/SKILL.md +437 -0
- package/template/.agent/skill-library/stack/security/csp-cors-headers/SKILL.md +588 -0
- package/template/.agent/skill-library/stack/security/dependency-auditing/SKILL.md +560 -0
- package/template/.agent/skill-library/stack/security/input-sanitization/SKILL.md +430 -0
- package/template/.agent/skill-library/stack/security/owasp-web-security/SKILL.md +421 -0
- package/template/.agent/skill-library/stack/state/tanstack-query/SKILL.md +637 -0
- package/template/.agent/skill-library/stack/state/zustand/SKILL.md +483 -0
- package/template/.agent/skill-library/stack/storage/aws-s3/SKILL.md +415 -0
- package/template/.agent/skill-library/stack/testing/playwright/SKILL.md +641 -0
- package/template/.agent/skill-library/stack/testing/storybook/SKILL.md +923 -0
- package/template/.agent/skill-library/stack/testing/testing-library/SKILL.md +872 -0
- package/template/.agent/skill-library/stack/testing/vitest/SKILL.md +714 -0
- package/template/.agent/skill-library/stack/ui/react-best-practices/SKILL.md +877 -0
- package/template/.agent/skill-library/stack/ui/react-composition-patterns/SKILL.md +1107 -0
- package/template/.agent/skill-library/stack/ui/react-flow/SKILL.md +425 -0
- package/template/.agent/skill-library/stack/ui/shadcn-ui/SKILL.md +703 -0
- package/template/.agent/skill-library/surface/api/api-caching/SKILL.md +458 -0
- package/template/.agent/skill-library/surface/api/api-documentation-openapi/SKILL.md +697 -0
- package/template/.agent/skill-library/surface/api/api-error-handling/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/api-security-checklist/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/api-versioning/SKILL.md +420 -0
- package/template/.agent/skill-library/surface/api/email-best-practices/SKILL.md +59 -0
- package/template/.agent/skill-library/surface/api/rate-limiting-abuse-protection/SKILL.md +147 -0
- package/template/.agent/skill-library/surface/api/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skill-library/surface/api/webhook-design/SKILL.md +752 -0
- package/template/.agent/skill-library/surface/cli/cli-configuration-management/SKILL.md +445 -0
- package/template/.agent/skill-library/surface/cli/cli-error-diagnostics/SKILL.md +515 -0
- package/template/.agent/skill-library/surface/cli/cli-shell-integration/SKILL.md +479 -0
- package/template/.agent/skill-library/surface/cli/cli-ux-design/SKILL.md +477 -0
- package/template/.agent/skill-library/surface/desktop/desktop-app-distribution/SKILL.md +416 -0
- package/template/.agent/skill-library/surface/desktop/desktop-security-sandboxing/SKILL.md +407 -0
- package/template/.agent/skill-library/surface/desktop/desktop-ux-conventions/SKILL.md +361 -0
- package/template/.agent/skill-library/surface/desktop/native-os-integration/SKILL.md +563 -0
- package/template/.agent/skill-library/surface/extension/browser-extension-patterns/SKILL.md +482 -0
- package/template/.agent/skill-library/surface/extension/plugin-architecture-design/SKILL.md +632 -0
- package/template/.agent/skill-library/surface/extension/vscode-extension-development/SKILL.md +728 -0
- package/template/.agent/skill-library/surface/mobile/app-store-submission/SKILL.md +304 -0
- package/template/.agent/skill-library/surface/mobile/mobile-offline-sync/SKILL.md +443 -0
- package/template/.agent/skill-library/surface/mobile/mobile-responsive-patterns/SKILL.md +432 -0
- package/template/.agent/skill-library/surface/mobile/push-notifications/SKILL.md +495 -0
- package/template/.agent/skill-library/surface/web/accessibility-compliance/SKILL.md +827 -0
- package/template/.agent/skill-library/surface/web/ai-seo/SKILL.md +398 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/content-patterns.md +285 -0
- package/template/.agent/skill-library/surface/web/ai-seo/references/platform-ranking-factors.md +152 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/SKILL.md +309 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/event-library.md +260 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/ga4-implementation.md +300 -0
- package/template/.agent/skill-library/surface/web/analytics-tracking/references/gtm-implementation.md +390 -0
- package/template/.agent/skill-library/surface/web/authentication-ui-flows/SKILL.md +530 -0
- package/template/.agent/skill-library/surface/web/dark-mode-theming/SKILL.md +516 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/SKILL.md +105 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/charts.csv +26 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/colors.csv +97 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/landing.csv +31 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/styles.csv +59 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/typography.csv +58 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/data/ux-guidelines.csv +100 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/core.py +258 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/design_system.py +1067 -0
- package/template/.agent/skill-library/surface/web/design-reference-data/scripts/search.py +106 -0
- package/template/.agent/skill-library/surface/web/form-handling-validation/SKILL.md +675 -0
- package/template/.agent/skill-library/surface/web/frontend-design/SKILL.md +1393 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/cppn-hero.tsx +299 -0
- package/template/.agent/skill-library/surface/web/frontend-design/templates/wave-hero.tsx +875 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/SKILL.md +111 -0
- package/template/.agent/skill-library/surface/web/frontend-verification/scripts/ux_audit.py +739 -0
- package/template/.agent/skill-library/surface/web/i18n-localization/SKILL.md +154 -0
- package/template/.agent/skill-library/surface/web/offline-first-pwa/SKILL.md +657 -0
- package/template/.agent/skill-library/surface/web/page-cro/SKILL.md +182 -0
- package/template/.agent/skill-library/surface/web/page-cro/references/experiments.md +248 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/SKILL.md +238 -0
- package/template/.agent/skill-library/surface/web/programmatic-seo/references/playbooks.md +308 -0
- package/template/.agent/skill-library/surface/web/schema-markup/SKILL.md +179 -0
- package/template/.agent/skill-library/surface/web/schema-markup/references/schema-examples.md +398 -0
- package/template/.agent/skill-library/surface/web/seo-audit/SKILL.md +394 -0
- package/template/.agent/skill-library/surface/web/seo-audit/references/ai-writing-detection.md +200 -0
- package/template/.agent/skill-library/surface/web/web-performance-optimization/SKILL.md +646 -0
- package/template/.agent/skill-library/surface/web/web-scraping/SKILL.md +58 -0
- package/template/.agent/skills/accessibility/SKILL.md +522 -0
- package/template/.agent/skills/accessibility/references/WCAG.md +162 -0
- package/template/.agent/skills/adversarial-review/SKILL.md +90 -0
- package/template/.agent/skills/antigravity-workflows/SKILL.md +81 -0
- package/template/.agent/skills/antigravity-workflows/resources/implementation-playbook.md +36 -0
- package/template/.agent/skills/api-design-principles/SKILL.md +37 -0
- package/template/.agent/skills/api-design-principles/assets/api-design-checklist.md +155 -0
- package/template/.agent/skills/api-design-principles/assets/rest-api-template.py +182 -0
- package/template/.agent/skills/api-design-principles/references/graphql-schema-design.md +583 -0
- package/template/.agent/skills/api-design-principles/references/rest-best-practices.md +408 -0
- package/template/.agent/skills/api-design-principles/resources/implementation-playbook.md +513 -0
- package/template/.agent/skills/api-versioning/SKILL.md +420 -0
- package/template/.agent/skills/architecture-mapping/SKILL.md +219 -0
- package/template/.agent/skills/bootstrap-agents/SKILL.md +259 -0
- package/template/.agent/skills/brainstorming/SKILL.md +236 -0
- package/template/.agent/skills/brand-guidelines/SKILL.md +44 -0
- package/template/.agent/skills/clean-code/SKILL.md +94 -0
- package/template/.agent/skills/code-review-pro/SKILL.md +152 -0
- package/template/.agent/skills/concise-planning/SKILL.md +68 -0
- package/template/.agent/skills/cross-layer-consistency/SKILL.md +117 -0
- package/template/.agent/skills/database-schema-design/SKILL.md +429 -0
- package/template/.agent/skills/deployment-procedures/SKILL.md +241 -0
- package/template/.agent/skills/design-anti-cliche/SKILL.md +159 -0
- package/template/.agent/skills/design-direction/SKILL.md +45 -0
- package/template/.agent/skills/error-handling-patterns/SKILL.md +721 -0
- package/template/.agent/skills/find-skills/SKILL.md +145 -0
- package/template/.agent/skills/git-advanced/SKILL.md +972 -0
- package/template/.agent/skills/git-workflow/SKILL.md +420 -0
- package/template/.agent/skills/idea-extraction/SKILL.md +271 -0
- package/template/.agent/skills/logging-best-practices/SKILL.md +851 -0
- package/template/.agent/skills/migration-management/SKILL.md +384 -0
- package/template/.agent/skills/minimalist-surgical-development/SKILL.md +69 -0
- package/template/.agent/skills/parallel-agents/SKILL.md +165 -0
- package/template/.agent/skills/parallel-debugging/SKILL.md +135 -0
- package/template/.agent/skills/parallel-feature-development/SKILL.md +166 -0
- package/template/.agent/skills/performance-budgeting/SKILL.md +144 -0
- package/template/.agent/skills/pipeline-rubrics/SKILL.md +51 -0
- package/template/.agent/skills/pipeline-rubrics/references/architecture-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/be-rubric.md +21 -0
- package/template/.agent/skills/pipeline-rubrics/references/fe-rubric.md +20 -0
- package/template/.agent/skills/pipeline-rubrics/references/ia-rubric.md +19 -0
- package/template/.agent/skills/pipeline-rubrics/references/scoring.md +28 -0
- package/template/.agent/skills/pipeline-rubrics/references/vision-rubric.md +11 -0
- package/template/.agent/skills/prd-templates/SKILL.md +88 -0
- package/template/.agent/skills/prd-templates/references/architecture-design-template.md +88 -0
- package/template/.agent/skills/prd-templates/references/be-spec-template.md +101 -0
- package/template/.agent/skills/prd-templates/references/data-placement-template.md +74 -0
- package/template/.agent/skills/prd-templates/references/decomposition-templates.md +211 -0
- package/template/.agent/skills/prd-templates/references/design-system-decisions.md +198 -0
- package/template/.agent/skills/prd-templates/references/engineering-standards-template.md +124 -0
- package/template/.agent/skills/prd-templates/references/fe-classification-procedures.md +47 -0
- package/template/.agent/skills/prd-templates/references/fe-spec-template.md +84 -0
- package/template/.agent/skills/prd-templates/references/infrastructure-report-template.md +71 -0
- package/template/.agent/skills/prd-templates/references/operational-templates.md +116 -0
- package/template/.agent/skills/prd-templates/references/placeholder-guard-template.md +21 -0
- package/template/.agent/skills/prd-templates/references/surface-model.md +61 -0
- package/template/.agent/skills/prd-templates/references/vision-template.md +66 -0
- package/template/.agent/skills/prompt-engineer/README.md +659 -0
- package/template/.agent/skills/prompt-engineer/SKILL.md +249 -0
- package/template/.agent/skills/regex-patterns/SKILL.md +751 -0
- package/template/.agent/skills/resolve-ambiguity/SKILL.md +278 -0
- package/template/.agent/skills/rest-api-design/SKILL.md +478 -0
- package/template/.agent/skills/security-scanning-security-hardening/SKILL.md +231 -0
- package/template/.agent/skills/session-continuity/SKILL.md +730 -0
- package/template/.agent/skills/session-continuity/protocols/01-session-resumption.md +38 -0
- package/template/.agent/skills/session-continuity/protocols/02-progress-generation.md +85 -0
- package/template/.agent/skills/session-continuity/protocols/03-progress-update.md +70 -0
- package/template/.agent/skills/session-continuity/protocols/04-pattern-extraction.md +60 -0
- package/template/.agent/skills/session-continuity/protocols/05-session-close.md +37 -0
- package/template/.agent/skills/session-continuity/protocols/06-decision-analysis.md +84 -0
- package/template/.agent/skills/session-continuity/protocols/07-spec-pipeline-generation.md +48 -0
- package/template/.agent/skills/session-continuity/protocols/08-spec-pipeline-update.md +43 -0
- package/template/.agent/skills/session-continuity/protocols/09-parallel-claim.md +122 -0
- package/template/.agent/skills/session-continuity/protocols/10-placeholder-verification-gate.md +104 -0
- package/template/.agent/skills/session-continuity/protocols/ambiguity-gates.md +48 -0
- package/template/.agent/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agent/skills/skill-creator/README.md +270 -0
- package/template/.agent/skills/skill-creator/SKILL.md +590 -0
- package/template/.agent/skills/skill-creator/references/output-patterns.md +82 -0
- package/template/.agent/skills/skill-creator/references/workflows.md +28 -0
- package/template/.agent/skills/skill-creator/scripts/init_skill.py +303 -0
- package/template/.agent/skills/skill-creator/scripts/package_skill.py +110 -0
- package/template/.agent/skills/skill-creator/scripts/quick_validate.py +95 -0
- package/template/.agent/skills/spec-writing/SKILL.md +110 -0
- package/template/.agent/skills/systematic-debugging/CREATION-LOG.md +119 -0
- package/template/.agent/skills/systematic-debugging/SKILL.md +297 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting-example.ts +158 -0
- package/template/.agent/skills/systematic-debugging/condition-based-waiting.md +115 -0
- package/template/.agent/skills/systematic-debugging/defense-in-depth.md +122 -0
- package/template/.agent/skills/systematic-debugging/find-polluter.sh +63 -0
- package/template/.agent/skills/systematic-debugging/root-cause-tracing.md +169 -0
- package/template/.agent/skills/systematic-debugging/test-academic.md +14 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-1.md +58 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-2.md +68 -0
- package/template/.agent/skills/systematic-debugging/test-pressure-3.md +69 -0
- package/template/.agent/skills/tdd-workflow/SKILL.md +409 -0
- package/template/.agent/skills/tech-stack-catalog/SKILL.md +49 -0
- package/template/.agent/skills/tech-stack-catalog/references/constraint-questions.md +21 -0
- package/template/.agent/skills/tech-stack-catalog/references/dev-tooling-decisions.md +37 -0
- package/template/.agent/skills/tech-stack-catalog/references/surface-decision-tables.md +69 -0
- package/template/.agent/skills/technical-writer/SKILL.md +242 -0
- package/template/.agent/skills/testing-strategist/SKILL.md +932 -0
- package/template/.agent/skills/verification-before-completion/SKILL.md +145 -0
- package/template/.agent/skills/workflow-automation/SKILL.md +73 -0
- package/template/.agent/workflows/audit-ambiguity-execute.md +165 -0
- package/template/.agent/workflows/audit-ambiguity-rubrics.md +83 -0
- package/template/.agent/workflows/audit-ambiguity.md +64 -0
- package/template/.agent/workflows/bootstrap-agents-fill.md +201 -0
- package/template/.agent/workflows/bootstrap-agents-provision.md +197 -0
- package/template/.agent/workflows/bootstrap-agents.md +66 -0
- package/template/.agent/workflows/create-prd-architecture.md +119 -0
- package/template/.agent/workflows/create-prd-compile.md +138 -0
- package/template/.agent/workflows/create-prd-design-system.md +135 -0
- package/template/.agent/workflows/create-prd-security.md +113 -0
- package/template/.agent/workflows/create-prd-stack.md +91 -0
- package/template/.agent/workflows/create-prd.md +168 -0
- package/template/.agent/workflows/decompose-architecture-structure.md +82 -0
- package/template/.agent/workflows/decompose-architecture-validate.md +119 -0
- package/template/.agent/workflows/decompose-architecture.md +111 -0
- package/template/.agent/workflows/evolve-contract.md +98 -0
- package/template/.agent/workflows/evolve-feature-cascade.md +140 -0
- package/template/.agent/workflows/evolve-feature-classify.md +116 -0
- package/template/.agent/workflows/evolve-feature.md +56 -0
- package/template/.agent/workflows/ideate-discover.md +144 -0
- package/template/.agent/workflows/ideate-extract.md +129 -0
- package/template/.agent/workflows/ideate-validate.md +117 -0
- package/template/.agent/workflows/ideate.md +113 -0
- package/template/.agent/workflows/implement-slice-setup.md +113 -0
- package/template/.agent/workflows/implement-slice-tdd.md +198 -0
- package/template/.agent/workflows/implement-slice.md +50 -0
- package/template/.agent/workflows/plan-phase.md +202 -0
- package/template/.agent/workflows/propagate-decision-apply.md +135 -0
- package/template/.agent/workflows/propagate-decision-scan.md +147 -0
- package/template/.agent/workflows/propagate-decision.md +56 -0
- package/template/.agent/workflows/remediate-pipeline-assess.md +138 -0
- package/template/.agent/workflows/remediate-pipeline-execute.md +135 -0
- package/template/.agent/workflows/remediate-pipeline.md +55 -0
- package/template/.agent/workflows/resolve-ambiguity.md +82 -0
- package/template/.agent/workflows/sync-kit.md +209 -0
- package/template/.agent/workflows/update-architecture-map.md +74 -0
- package/template/.agent/workflows/validate-phase.md +219 -0
- package/template/.agent/workflows/verify-infrastructure.md +207 -0
- package/template/.agent/workflows/write-architecture-spec-deepen.md +139 -0
- package/template/.agent/workflows/write-architecture-spec-design.md +202 -0
- package/template/.agent/workflows/write-architecture-spec.md +63 -0
- package/template/.agent/workflows/write-be-spec-classify.md +165 -0
- package/template/.agent/workflows/write-be-spec-write.md +98 -0
- package/template/.agent/workflows/write-be-spec.md +76 -0
- package/template/.agent/workflows/write-fe-spec-classify.md +170 -0
- package/template/.agent/workflows/write-fe-spec-write.md +94 -0
- package/template/.agent/workflows/write-fe-spec.md +71 -0
- package/template/AGENTS.md +176 -0
- package/template/GEMINI.md +177 -0
- package/template/docs/README.md +187 -0
- package/template/docs/audits/.gitkeep +0 -0
- package/template/docs/audits/README.md +10 -0
- package/template/docs/plans/.gitkeep +0 -0
- package/template/docs/plans/README.md +21 -0
- package/template/docs/plans/be/.gitkeep +0 -0
- package/template/docs/plans/be/README.md +11 -0
- package/template/docs/plans/fe/.gitkeep +0 -0
- package/template/docs/plans/fe/README.md +11 -0
- package/template/docs/plans/ia/.gitkeep +0 -0
- package/template/docs/plans/ia/README.md +17 -0
- package/template/docs/plans/ia/deep-dives/.gitkeep +0 -0
- package/template/docs/plans/ia/deep-dives/README.md +5 -0
- package/template/docs/plans/phases/.gitkeep +0 -0
- package/template/docs/plans/phases/README.md +11 -0
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tanstack-query
|
|
3
|
+
description: |
|
|
4
|
+
Build with TanStack Query (React Query v5) — server state management with caching, mutations, optimistic updates, infinite queries, and SSR hydration. Use when: fetching/caching server data, performing mutations with cache invalidation, implementing optimistic UI, paginated/infinite scroll lists, prefetching, dependent queries, or integrating with Next.js SSR/RSC hydration patterns.
|
|
5
|
+
version: 1.0.0
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# TanStack Query (React Query v5)
|
|
9
|
+
|
|
10
|
+
**Status**: Production Ready
|
|
11
|
+
**Last Updated**: 2026-02-16
|
|
12
|
+
**Package**: `@tanstack/react-query@5.x`
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
## Setup
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pnpm add @tanstack/react-query
|
|
22
|
+
pnpm add -D @tanstack/react-query-devtools # Optional but recommended
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### QueryClientProvider
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
// src/providers/query-provider.tsx
|
|
29
|
+
"use client";
|
|
30
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
31
|
+
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
|
|
32
|
+
import { useState } from "react";
|
|
33
|
+
|
|
34
|
+
export function QueryProvider({ children }: { children: React.ReactNode }) {
|
|
35
|
+
// Create client inside useState to avoid sharing between requests in SSR
|
|
36
|
+
const [queryClient] = useState(
|
|
37
|
+
() =>
|
|
38
|
+
new QueryClient({
|
|
39
|
+
defaultOptions: {
|
|
40
|
+
queries: {
|
|
41
|
+
staleTime: 60 * 1000, // 1 minute — data considered fresh
|
|
42
|
+
gcTime: 5 * 60 * 1000, // 5 minutes — unused cache garbage collected
|
|
43
|
+
retry: 3,
|
|
44
|
+
refetchOnWindowFocus: true,
|
|
45
|
+
refetchOnReconnect: true,
|
|
46
|
+
},
|
|
47
|
+
mutations: {
|
|
48
|
+
retry: 0, // Do not retry mutations by default
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
})
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<QueryClientProvider client={queryClient}>
|
|
56
|
+
{children}
|
|
57
|
+
<ReactQueryDevtools initialIsOpen={false} />
|
|
58
|
+
</QueryClientProvider>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## useQuery Patterns
|
|
66
|
+
|
|
67
|
+
### Basic Query
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
import { useQuery } from "@tanstack/react-query";
|
|
71
|
+
|
|
72
|
+
function UserProfile({ userId }: { userId: string }) {
|
|
73
|
+
const { data, isPending, isError, error, isFetching } = useQuery({
|
|
74
|
+
queryKey: ["users", userId],
|
|
75
|
+
queryFn: () => fetch(`/api/users/${userId}`).then((res) => res.json()),
|
|
76
|
+
staleTime: 5 * 60 * 1000, // Override default per-query
|
|
77
|
+
enabled: !!userId, // Only fetch when userId is truthy
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
if (isPending) return <Skeleton />;
|
|
81
|
+
if (isError) return <ErrorDisplay error={error} />;
|
|
82
|
+
|
|
83
|
+
return <div>{data.name}</div>;
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Query Key Conventions
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
// Hierarchical keys — most specific last
|
|
91
|
+
["users"] // All users list
|
|
92
|
+
["users", userId] // Single user
|
|
93
|
+
["users", userId, "posts"] // User's posts
|
|
94
|
+
["users", { status: "active" }] // Filtered list
|
|
95
|
+
["posts", postId, "comments"] // Post comments
|
|
96
|
+
|
|
97
|
+
// Invalidation cascades up the hierarchy:
|
|
98
|
+
// invalidateQueries({ queryKey: ["users"] })
|
|
99
|
+
// ^^^ invalidates ALL queries starting with ["users"]
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Query Function with Type Safety
|
|
103
|
+
|
|
104
|
+
```typescript
|
|
105
|
+
// src/lib/api.ts
|
|
106
|
+
import { z } from "zod";
|
|
107
|
+
|
|
108
|
+
const UserSchema = z.object({
|
|
109
|
+
id: z.string(),
|
|
110
|
+
name: z.string(),
|
|
111
|
+
email: z.string().email(),
|
|
112
|
+
});
|
|
113
|
+
type User = z.infer<typeof UserSchema>;
|
|
114
|
+
|
|
115
|
+
async function fetchUser(userId: string): Promise<User> {
|
|
116
|
+
const res = await fetch(`/api/users/${userId}`);
|
|
117
|
+
if (!res.ok) throw new Error(`Failed to fetch user: ${res.status}`);
|
|
118
|
+
const data = await res.json();
|
|
119
|
+
return UserSchema.parse(data); // Runtime validation
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// src/hooks/use-user.ts
|
|
123
|
+
export function useUser(userId: string) {
|
|
124
|
+
return useQuery({
|
|
125
|
+
queryKey: ["users", userId],
|
|
126
|
+
queryFn: () => fetchUser(userId),
|
|
127
|
+
enabled: !!userId,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## useMutation Patterns
|
|
135
|
+
|
|
136
|
+
### Basic Mutation with Cache Invalidation
|
|
137
|
+
|
|
138
|
+
```typescript
|
|
139
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
140
|
+
|
|
141
|
+
function CreatePostForm() {
|
|
142
|
+
const queryClient = useQueryClient();
|
|
143
|
+
|
|
144
|
+
const createPost = useMutation({
|
|
145
|
+
mutationFn: (newPost: { title: string; body: string }) =>
|
|
146
|
+
fetch("/api/posts", {
|
|
147
|
+
method: "POST",
|
|
148
|
+
body: JSON.stringify(newPost),
|
|
149
|
+
headers: { "Content-Type": "application/json" },
|
|
150
|
+
}).then((res) => {
|
|
151
|
+
if (!res.ok) throw new Error("Failed to create post");
|
|
152
|
+
return res.json();
|
|
153
|
+
}),
|
|
154
|
+
onSuccess: (data) => {
|
|
155
|
+
// Invalidate and refetch posts list
|
|
156
|
+
queryClient.invalidateQueries({ queryKey: ["posts"] });
|
|
157
|
+
// Optionally seed the cache for the new post
|
|
158
|
+
queryClient.setQueryData(["posts", data.id], data);
|
|
159
|
+
},
|
|
160
|
+
onError: (error) => {
|
|
161
|
+
toast.error(error.message);
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
return (
|
|
166
|
+
<form
|
|
167
|
+
onSubmit={(e) => {
|
|
168
|
+
e.preventDefault();
|
|
169
|
+
createPost.mutate({ title, body });
|
|
170
|
+
}}
|
|
171
|
+
>
|
|
172
|
+
<button disabled={createPost.isPending}>
|
|
173
|
+
{createPost.isPending ? "Creating..." : "Create Post"}
|
|
174
|
+
</button>
|
|
175
|
+
</form>
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Optimistic Updates
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
const updateTodo = useMutation({
|
|
184
|
+
mutationFn: (updatedTodo: Todo) =>
|
|
185
|
+
fetch(`/api/todos/${updatedTodo.id}`, {
|
|
186
|
+
method: "PATCH",
|
|
187
|
+
body: JSON.stringify(updatedTodo),
|
|
188
|
+
}).then((res) => res.json()),
|
|
189
|
+
|
|
190
|
+
onMutate: async (newTodo) => {
|
|
191
|
+
// Cancel any outgoing refetches to avoid overwriting optimistic update
|
|
192
|
+
await queryClient.cancelQueries({ queryKey: ["todos", newTodo.id] });
|
|
193
|
+
|
|
194
|
+
// Snapshot previous value for rollback
|
|
195
|
+
const previousTodo = queryClient.getQueryData<Todo>(["todos", newTodo.id]);
|
|
196
|
+
|
|
197
|
+
// Optimistically update the cache
|
|
198
|
+
queryClient.setQueryData(["todos", newTodo.id], newTodo);
|
|
199
|
+
|
|
200
|
+
// Return context with snapshot for rollback
|
|
201
|
+
return { previousTodo };
|
|
202
|
+
},
|
|
203
|
+
|
|
204
|
+
onError: (_err, _newTodo, context) => {
|
|
205
|
+
// Rollback on error
|
|
206
|
+
if (context?.previousTodo) {
|
|
207
|
+
queryClient.setQueryData(["todos", context.previousTodo.id], context.previousTodo);
|
|
208
|
+
}
|
|
209
|
+
},
|
|
210
|
+
|
|
211
|
+
onSettled: (_data, _error, variables) => {
|
|
212
|
+
// Always refetch after mutation to ensure server state consistency
|
|
213
|
+
queryClient.invalidateQueries({ queryKey: ["todos", variables.id] });
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Optimistic Update on a List
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const deleteTodo = useMutation({
|
|
222
|
+
mutationFn: (todoId: string) =>
|
|
223
|
+
fetch(`/api/todos/${todoId}`, { method: "DELETE" }),
|
|
224
|
+
|
|
225
|
+
onMutate: async (todoId) => {
|
|
226
|
+
await queryClient.cancelQueries({ queryKey: ["todos"] });
|
|
227
|
+
|
|
228
|
+
const previousTodos = queryClient.getQueryData<Todo[]>(["todos"]);
|
|
229
|
+
|
|
230
|
+
queryClient.setQueryData<Todo[]>(["todos"], (old) =>
|
|
231
|
+
old?.filter((t) => t.id !== todoId) ?? []
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
return { previousTodos };
|
|
235
|
+
},
|
|
236
|
+
|
|
237
|
+
onError: (_err, _todoId, context) => {
|
|
238
|
+
queryClient.setQueryData(["todos"], context?.previousTodos);
|
|
239
|
+
},
|
|
240
|
+
|
|
241
|
+
onSettled: () => {
|
|
242
|
+
queryClient.invalidateQueries({ queryKey: ["todos"] });
|
|
243
|
+
},
|
|
244
|
+
});
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Query Invalidation Strategies
|
|
250
|
+
|
|
251
|
+
```typescript
|
|
252
|
+
const queryClient = useQueryClient();
|
|
253
|
+
|
|
254
|
+
// Invalidate everything
|
|
255
|
+
queryClient.invalidateQueries();
|
|
256
|
+
|
|
257
|
+
// Invalidate all queries starting with "posts"
|
|
258
|
+
queryClient.invalidateQueries({ queryKey: ["posts"] });
|
|
259
|
+
|
|
260
|
+
// Invalidate a specific post
|
|
261
|
+
queryClient.invalidateQueries({ queryKey: ["posts", postId] });
|
|
262
|
+
|
|
263
|
+
// Invalidate only active (mounted) queries
|
|
264
|
+
queryClient.invalidateQueries({ queryKey: ["posts"], type: "active" });
|
|
265
|
+
|
|
266
|
+
// Invalidate with predicate for fine-grained control
|
|
267
|
+
queryClient.invalidateQueries({
|
|
268
|
+
predicate: (query) =>
|
|
269
|
+
query.queryKey[0] === "posts" &&
|
|
270
|
+
(query.queryKey[1] as any)?.status === "draft",
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Reset queries — clear cache AND refetch
|
|
274
|
+
queryClient.resetQueries({ queryKey: ["posts"] });
|
|
275
|
+
|
|
276
|
+
// Remove queries — clear cache without refetching
|
|
277
|
+
queryClient.removeQueries({ queryKey: ["posts"] });
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## Infinite Queries
|
|
283
|
+
|
|
284
|
+
```typescript
|
|
285
|
+
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
286
|
+
|
|
287
|
+
interface PostsPage {
|
|
288
|
+
posts: Post[];
|
|
289
|
+
nextCursor: string | null;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
function PostFeed() {
|
|
293
|
+
const {
|
|
294
|
+
data,
|
|
295
|
+
fetchNextPage,
|
|
296
|
+
hasNextPage,
|
|
297
|
+
isFetchingNextPage,
|
|
298
|
+
isPending,
|
|
299
|
+
} = useInfiniteQuery({
|
|
300
|
+
queryKey: ["posts", "feed"],
|
|
301
|
+
queryFn: ({ pageParam }): Promise<PostsPage> =>
|
|
302
|
+
fetch(`/api/posts?cursor=${pageParam}&limit=20`).then((r) => r.json()),
|
|
303
|
+
initialPageParam: "",
|
|
304
|
+
getNextPageParam: (lastPage) => lastPage.nextCursor,
|
|
305
|
+
// getPreviousPageParam for bidirectional scrolling
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
// Flatten pages into single list
|
|
309
|
+
const allPosts = data?.pages.flatMap((page) => page.posts) ?? [];
|
|
310
|
+
|
|
311
|
+
return (
|
|
312
|
+
<div>
|
|
313
|
+
{allPosts.map((post) => (
|
|
314
|
+
<PostCard key={post.id} post={post} />
|
|
315
|
+
))}
|
|
316
|
+
{hasNextPage && (
|
|
317
|
+
<button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
|
|
318
|
+
{isFetchingNextPage ? "Loading more..." : "Load More"}
|
|
319
|
+
</button>
|
|
320
|
+
)}
|
|
321
|
+
</div>
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## Prefetching
|
|
329
|
+
|
|
330
|
+
### In Event Handlers (Hover Prefetch)
|
|
331
|
+
|
|
332
|
+
```typescript
|
|
333
|
+
function PostLink({ postId }: { postId: string }) {
|
|
334
|
+
const queryClient = useQueryClient();
|
|
335
|
+
|
|
336
|
+
const prefetch = () => {
|
|
337
|
+
queryClient.prefetchQuery({
|
|
338
|
+
queryKey: ["posts", postId],
|
|
339
|
+
queryFn: () => fetchPost(postId),
|
|
340
|
+
staleTime: 5 * 60 * 1000, // Only prefetch if data older than 5 min
|
|
341
|
+
});
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
return (
|
|
345
|
+
<Link href={`/posts/${postId}`} onMouseEnter={prefetch}>
|
|
346
|
+
View Post
|
|
347
|
+
</Link>
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
### In Loaders / Server Components (Next.js)
|
|
353
|
+
|
|
354
|
+
```typescript
|
|
355
|
+
// src/app/posts/[id]/page.tsx
|
|
356
|
+
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
|
|
357
|
+
|
|
358
|
+
export default async function PostPage({ params }: { params: { id: string } }) {
|
|
359
|
+
const queryClient = new QueryClient();
|
|
360
|
+
|
|
361
|
+
await queryClient.prefetchQuery({
|
|
362
|
+
queryKey: ["posts", params.id],
|
|
363
|
+
queryFn: () => fetchPost(params.id),
|
|
364
|
+
});
|
|
365
|
+
|
|
366
|
+
return (
|
|
367
|
+
<HydrationBoundary state={dehydrate(queryClient)}>
|
|
368
|
+
<PostContent postId={params.id} />
|
|
369
|
+
</HydrationBoundary>
|
|
370
|
+
);
|
|
371
|
+
}
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
---
|
|
375
|
+
|
|
376
|
+
## Dependent Queries
|
|
377
|
+
|
|
378
|
+
```typescript
|
|
379
|
+
function UserPosts({ userId }: { userId: string }) {
|
|
380
|
+
// First query: fetch user
|
|
381
|
+
const userQuery = useQuery({
|
|
382
|
+
queryKey: ["users", userId],
|
|
383
|
+
queryFn: () => fetchUser(userId),
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
// Second query: fetch posts only after user loaded
|
|
387
|
+
const postsQuery = useQuery({
|
|
388
|
+
queryKey: ["users", userId, "posts"],
|
|
389
|
+
queryFn: () => fetchPostsByTeam(userQuery.data!.teamId),
|
|
390
|
+
enabled: !!userQuery.data?.teamId, // Only runs when teamId is available
|
|
391
|
+
});
|
|
392
|
+
|
|
393
|
+
// ...
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Parallel Queries
|
|
400
|
+
|
|
401
|
+
```typescript
|
|
402
|
+
import { useQueries } from "@tanstack/react-query";
|
|
403
|
+
|
|
404
|
+
function Dashboard({ userIds }: { userIds: string[] }) {
|
|
405
|
+
const userQueries = useQueries({
|
|
406
|
+
queries: userIds.map((id) => ({
|
|
407
|
+
queryKey: ["users", id],
|
|
408
|
+
queryFn: () => fetchUser(id),
|
|
409
|
+
staleTime: Infinity,
|
|
410
|
+
})),
|
|
411
|
+
combine: (results) => ({
|
|
412
|
+
data: results.map((r) => r.data).filter(Boolean),
|
|
413
|
+
isPending: results.some((r) => r.isPending),
|
|
414
|
+
}),
|
|
415
|
+
});
|
|
416
|
+
|
|
417
|
+
if (userQueries.isPending) return <Skeleton />;
|
|
418
|
+
return <UserList users={userQueries.data} />;
|
|
419
|
+
}
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
---
|
|
423
|
+
|
|
424
|
+
## Query Cancellation
|
|
425
|
+
|
|
426
|
+
```typescript
|
|
427
|
+
// queryFn receives an AbortSignal for automatic cancellation
|
|
428
|
+
const { data } = useQuery({
|
|
429
|
+
queryKey: ["search", debouncedTerm],
|
|
430
|
+
queryFn: ({ signal }) =>
|
|
431
|
+
fetch(`/api/search?q=${debouncedTerm}`, { signal }).then((r) => r.json()),
|
|
432
|
+
enabled: debouncedTerm.length > 2,
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
// Manual cancellation
|
|
436
|
+
queryClient.cancelQueries({ queryKey: ["search"] });
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
---
|
|
440
|
+
|
|
441
|
+
## Suspense Integration
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
import { useSuspenseQuery } from "@tanstack/react-query";
|
|
445
|
+
import { Suspense } from "react";
|
|
446
|
+
|
|
447
|
+
function PostContent({ postId }: { postId: string }) {
|
|
448
|
+
// Throws promise — caught by nearest Suspense boundary
|
|
449
|
+
const { data } = useSuspenseQuery({
|
|
450
|
+
queryKey: ["posts", postId],
|
|
451
|
+
queryFn: () => fetchPost(postId),
|
|
452
|
+
});
|
|
453
|
+
|
|
454
|
+
// data is guaranteed non-null here
|
|
455
|
+
return <article>{data.title}</article>;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// Parent component
|
|
459
|
+
function PostPage({ postId }: { postId: string }) {
|
|
460
|
+
return (
|
|
461
|
+
<Suspense fallback={<PostSkeleton />}>
|
|
462
|
+
<PostContent postId={postId} />
|
|
463
|
+
</Suspense>
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
---
|
|
469
|
+
|
|
470
|
+
## SSR / Hydration (Next.js App Router)
|
|
471
|
+
|
|
472
|
+
```typescript
|
|
473
|
+
// src/app/posts/page.tsx — Server Component
|
|
474
|
+
import { dehydrate, HydrationBoundary, QueryClient } from "@tanstack/react-query";
|
|
475
|
+
import { PostList } from "./post-list";
|
|
476
|
+
|
|
477
|
+
export default async function PostsPage() {
|
|
478
|
+
const queryClient = new QueryClient();
|
|
479
|
+
|
|
480
|
+
await queryClient.prefetchQuery({
|
|
481
|
+
queryKey: ["posts"],
|
|
482
|
+
queryFn: fetchPosts,
|
|
483
|
+
});
|
|
484
|
+
|
|
485
|
+
return (
|
|
486
|
+
<HydrationBoundary state={dehydrate(queryClient)}>
|
|
487
|
+
<PostList /> {/* Client component — useQuery picks up prefetched data */}
|
|
488
|
+
</HydrationBoundary>
|
|
489
|
+
);
|
|
490
|
+
}
|
|
491
|
+
```
|
|
492
|
+
|
|
493
|
+
---
|
|
494
|
+
|
|
495
|
+
## Cache Manipulation
|
|
496
|
+
|
|
497
|
+
```typescript
|
|
498
|
+
const queryClient = useQueryClient();
|
|
499
|
+
|
|
500
|
+
// Read cache
|
|
501
|
+
const cachedUser = queryClient.getQueryData<User>(["users", userId]);
|
|
502
|
+
|
|
503
|
+
// Write cache directly (no refetch)
|
|
504
|
+
queryClient.setQueryData<User>(["users", userId], (old) => ({
|
|
505
|
+
...old!,
|
|
506
|
+
name: "Updated Name",
|
|
507
|
+
}));
|
|
508
|
+
|
|
509
|
+
// Ensure data exists (fetch if missing, return cached if present)
|
|
510
|
+
const user = await queryClient.ensureQueryData({
|
|
511
|
+
queryKey: ["users", userId],
|
|
512
|
+
queryFn: () => fetchUser(userId),
|
|
513
|
+
});
|
|
514
|
+
```
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## Retry and Error Handling
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
useQuery({
|
|
522
|
+
queryKey: ["data"],
|
|
523
|
+
queryFn: fetchData,
|
|
524
|
+
retry: 3, // Retry 3 times on failure
|
|
525
|
+
retryDelay: (attemptIndex) => Math.min(1000 * 2 ** attemptIndex, 30000), // Exponential backoff
|
|
526
|
+
});
|
|
527
|
+
|
|
528
|
+
// Global error handler
|
|
529
|
+
const queryClient = new QueryClient({
|
|
530
|
+
defaultOptions: {
|
|
531
|
+
queries: {
|
|
532
|
+
retry: (failureCount, error) => {
|
|
533
|
+
// Do not retry on 4xx errors
|
|
534
|
+
if (error instanceof ApiError && error.status >= 400 && error.status < 500) {
|
|
535
|
+
return false;
|
|
536
|
+
}
|
|
537
|
+
return failureCount < 3;
|
|
538
|
+
},
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
queryCache: new QueryCache({
|
|
542
|
+
onError: (error, query) => {
|
|
543
|
+
// Global error toast for background refetch failures
|
|
544
|
+
if (query.state.data !== undefined) {
|
|
545
|
+
toast.error(`Background update failed: ${error.message}`);
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
}),
|
|
549
|
+
});
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
---
|
|
553
|
+
|
|
554
|
+
## Placeholder Data vs Initial Data
|
|
555
|
+
|
|
556
|
+
```typescript
|
|
557
|
+
// placeholderData — shown while real data loads, NOT put in cache
|
|
558
|
+
useQuery({
|
|
559
|
+
queryKey: ["posts", postId],
|
|
560
|
+
queryFn: () => fetchPost(postId),
|
|
561
|
+
placeholderData: { id: postId, title: "Loading...", body: "" },
|
|
562
|
+
// isPlaceholderData === true while showing placeholder
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// Use cached list data as placeholder for detail view
|
|
566
|
+
useQuery({
|
|
567
|
+
queryKey: ["posts", postId],
|
|
568
|
+
queryFn: () => fetchPost(postId),
|
|
569
|
+
placeholderData: () =>
|
|
570
|
+
queryClient.getQueryData<Post[]>(["posts"])?.find((p) => p.id === postId),
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// initialData — treated as real data, IS cached, affects staleTime
|
|
574
|
+
useQuery({
|
|
575
|
+
queryKey: ["posts", postId],
|
|
576
|
+
queryFn: () => fetchPost(postId),
|
|
577
|
+
initialData: () =>
|
|
578
|
+
queryClient.getQueryData<Post[]>(["posts"])?.find((p) => p.id === postId),
|
|
579
|
+
initialDataUpdatedAt: () =>
|
|
580
|
+
queryClient.getQueryState(["posts"])?.dataUpdatedAt,
|
|
581
|
+
});
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
---
|
|
585
|
+
|
|
586
|
+
## Custom Hook Composition
|
|
587
|
+
|
|
588
|
+
```typescript
|
|
589
|
+
// src/hooks/use-posts.ts
|
|
590
|
+
export function usePosts(filters?: PostFilters) {
|
|
591
|
+
return useQuery({
|
|
592
|
+
queryKey: ["posts", filters ?? {}],
|
|
593
|
+
queryFn: () => fetchPosts(filters),
|
|
594
|
+
staleTime: 30 * 1000,
|
|
595
|
+
});
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
export function useCreatePost() {
|
|
599
|
+
const queryClient = useQueryClient();
|
|
600
|
+
return useMutation({
|
|
601
|
+
mutationFn: createPost,
|
|
602
|
+
onSuccess: () => queryClient.invalidateQueries({ queryKey: ["posts"] }),
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
export function useDeletePost() {
|
|
607
|
+
const queryClient = useQueryClient();
|
|
608
|
+
return useMutation({
|
|
609
|
+
mutationFn: (postId: string) => deletePost(postId),
|
|
610
|
+
onSuccess: (_data, postId) => {
|
|
611
|
+
queryClient.removeQueries({ queryKey: ["posts", postId] });
|
|
612
|
+
queryClient.invalidateQueries({ queryKey: ["posts"] });
|
|
613
|
+
},
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
---
|
|
619
|
+
|
|
620
|
+
## Anti-Patterns
|
|
621
|
+
|
|
622
|
+
| Anti-Pattern | Why It Breaks | Correct Approach |
|
|
623
|
+
|---|---|---|
|
|
624
|
+
| Putting derived/computed state in queryKey | Causes unnecessary refetches | Compute from cached data with `select` |
|
|
625
|
+
| Using `queryClient` in render without hooks | Breaks React rules, stale references | Use `useQueryClient()` hook |
|
|
626
|
+
| Setting `staleTime: 0` everywhere | Excessive network requests, poor UX | Set reasonable staleTime per data type |
|
|
627
|
+
| Not using `enabled` for conditional queries | Fires with undefined params, causes errors | Set `enabled: !!param` |
|
|
628
|
+
| Storing client state in React Query | Wrong tool — it is for server state | Use useState, Zustand, or Jotai for client state |
|
|
629
|
+
| Calling `queryClient.invalidateQueries()` with no key | Invalidates the entire cache | Always scope invalidation to specific keys |
|
|
630
|
+
| Mutating cached data directly | Bypasses React Query reactivity | Use `setQueryData` with immutable updates |
|
|
631
|
+
| Creating QueryClient outside component/useState | Shared across SSR requests, data leaks | Use `useState(() => new QueryClient())` |
|
|
632
|
+
| Forgetting `onSettled` invalidation in optimistic updates | Cache gets stuck with stale optimistic data | Always invalidate in onSettled |
|
|
633
|
+
| Using string query keys | No hierarchy, cannot invalidate groups | Use array keys: `["entity", id]` |
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
**Last verified**: 2026-02-16 | **Skill version**: 1.0.0
|