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,803 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: vanilla-javascript
|
|
3
|
+
description: Modern vanilla JavaScript patterns (ES2022+) without frameworks. Covers modules, async/await, Web APIs, DOM manipulation, event delegation, web components, Proxy/Reflect, iterators/generators, and no-framework application architecture.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Vanilla JavaScript Patterns (ES2022+)
|
|
8
|
+
|
|
9
|
+
Expert guidance for writing modern, production-grade JavaScript without frameworks. Covers ES modules, async patterns, Web APIs (IntersectionObserver, AbortController), DOM manipulation best practices, event delegation, Web Components, and the architectural patterns that make framework-free code maintainable.
|
|
10
|
+
|
|
11
|
+
## When to Use This Skill
|
|
12
|
+
|
|
13
|
+
- Building lightweight websites that do not need a framework
|
|
14
|
+
- Creating Web Components for use across any framework
|
|
15
|
+
- Adding interactive behavior to server-rendered pages
|
|
16
|
+
- Writing browser extensions or bookmarklets
|
|
17
|
+
- Building progressive enhancements for static sites
|
|
18
|
+
- Understanding core JavaScript before adopting a framework
|
|
19
|
+
- Creating embeddable widgets for third-party sites
|
|
20
|
+
|
|
21
|
+
## Core Concepts
|
|
22
|
+
|
|
23
|
+
### 1. Modules (import/export)
|
|
24
|
+
|
|
25
|
+
```javascript
|
|
26
|
+
// Named exports
|
|
27
|
+
// utils.js
|
|
28
|
+
export function debounce(fn, ms) {
|
|
29
|
+
let timer;
|
|
30
|
+
return (...args) => {
|
|
31
|
+
clearTimeout(timer);
|
|
32
|
+
timer = setTimeout(() => fn(...args), ms);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function throttle(fn, ms) {
|
|
37
|
+
let lastCall = 0;
|
|
38
|
+
return (...args) => {
|
|
39
|
+
const now = Date.now();
|
|
40
|
+
if (now - lastCall >= ms) {
|
|
41
|
+
lastCall = now;
|
|
42
|
+
return fn(...args);
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Default export
|
|
48
|
+
// logger.js
|
|
49
|
+
export default class Logger {
|
|
50
|
+
constructor(prefix) {
|
|
51
|
+
this.prefix = prefix;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
info(msg) {
|
|
55
|
+
console.log(`[${this.prefix}] ${msg}`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Importing
|
|
60
|
+
import Logger from "./logger.js";
|
|
61
|
+
import { debounce, throttle } from "./utils.js";
|
|
62
|
+
import * as utils from "./utils.js";
|
|
63
|
+
|
|
64
|
+
// Dynamic import (code splitting)
|
|
65
|
+
async function loadChart() {
|
|
66
|
+
const { Chart } = await import("./chart.js");
|
|
67
|
+
return new Chart(canvas);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Import in HTML
|
|
71
|
+
// <script type="module" src="./app.js"></script>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 2. Destructuring, Optional Chaining, Nullish Coalescing
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// Object destructuring with defaults
|
|
78
|
+
function createUser({ name, email, age = 0, role = "user" } = {}) {
|
|
79
|
+
return { name, email, age, role };
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Nested destructuring
|
|
83
|
+
const {
|
|
84
|
+
data: { users = [] },
|
|
85
|
+
meta: { total = 0 }
|
|
86
|
+
} = apiResponse;
|
|
87
|
+
|
|
88
|
+
// Array destructuring
|
|
89
|
+
const [first, second, ...rest] = items;
|
|
90
|
+
const [, , third] = items; // Skip first two
|
|
91
|
+
|
|
92
|
+
// Optional chaining (?.)
|
|
93
|
+
const city = user?.address?.city;
|
|
94
|
+
const firstItem = list?.[0];
|
|
95
|
+
const result = obj?.method?.();
|
|
96
|
+
|
|
97
|
+
// Nullish coalescing (??) -- only null/undefined, NOT 0 or ""
|
|
98
|
+
const port = config.port ?? 3000; // 0 is kept, null becomes 3000
|
|
99
|
+
const name = input ?? "anonymous";
|
|
100
|
+
|
|
101
|
+
// Nullish assignment (??=)
|
|
102
|
+
user.nickname ??= user.name; // Only assigns if null/undefined
|
|
103
|
+
|
|
104
|
+
// Logical assignment (&&=, ||=)
|
|
105
|
+
config.debug &&= process.env.NODE_ENV !== "production";
|
|
106
|
+
options.timeout ||= 5000;
|
|
107
|
+
|
|
108
|
+
// IMPORTANT: ?? vs ||
|
|
109
|
+
const count = data.count ?? 0; // Keeps 0, replaces null/undefined
|
|
110
|
+
const count2 = data.count || 0; // Replaces 0, "", false, null, undefined
|
|
111
|
+
// Use ?? when 0, "", or false are valid values
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### 3. Promises and async/await
|
|
115
|
+
|
|
116
|
+
```javascript
|
|
117
|
+
// async/await -- preferred syntax for promises
|
|
118
|
+
async function fetchUser(id) {
|
|
119
|
+
const response = await fetch(`/api/users/${id}`);
|
|
120
|
+
if (!response.ok) {
|
|
121
|
+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
|
|
122
|
+
}
|
|
123
|
+
return response.json();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Error handling with try/catch
|
|
127
|
+
async function loadData() {
|
|
128
|
+
try {
|
|
129
|
+
const user = await fetchUser("123");
|
|
130
|
+
const orders = await fetchOrders(user.id);
|
|
131
|
+
return { user, orders };
|
|
132
|
+
} catch (error) {
|
|
133
|
+
console.error("Failed to load data:", error.message);
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Concurrent execution with Promise.all
|
|
139
|
+
async function fetchAll(ids) {
|
|
140
|
+
const promises = ids.map((id) => fetchUser(id));
|
|
141
|
+
return Promise.all(promises); // Fails fast if any reject
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Promise.allSettled -- get all results regardless of failures
|
|
145
|
+
async function fetchAllSafe(ids) {
|
|
146
|
+
const results = await Promise.allSettled(ids.map((id) => fetchUser(id)));
|
|
147
|
+
return results
|
|
148
|
+
.filter((r) => r.status === "fulfilled")
|
|
149
|
+
.map((r) => r.value);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Promise.any -- first to resolve wins
|
|
153
|
+
async function fetchFromFastestMirror(urls) {
|
|
154
|
+
return Promise.any(urls.map((url) => fetch(url).then((r) => r.json())));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Timeout pattern
|
|
158
|
+
function withTimeout(promise, ms) {
|
|
159
|
+
const timeout = new Promise((_, reject) =>
|
|
160
|
+
setTimeout(() => reject(new Error(`Timeout after ${ms}ms`)), ms)
|
|
161
|
+
);
|
|
162
|
+
return Promise.race([promise, timeout]);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Sequential async iteration
|
|
166
|
+
async function processSequentially(items) {
|
|
167
|
+
const results = [];
|
|
168
|
+
for (const item of items) {
|
|
169
|
+
const result = await processItem(item);
|
|
170
|
+
results.push(result);
|
|
171
|
+
}
|
|
172
|
+
return results;
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### 4. Fetch API and AbortController
|
|
177
|
+
|
|
178
|
+
```javascript
|
|
179
|
+
// Basic fetch with error handling
|
|
180
|
+
async function apiRequest(url, options = {}) {
|
|
181
|
+
const response = await fetch(url, {
|
|
182
|
+
headers: {
|
|
183
|
+
"Content-Type": "application/json",
|
|
184
|
+
...options.headers,
|
|
185
|
+
},
|
|
186
|
+
...options,
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
if (!response.ok) {
|
|
190
|
+
const error = new Error(`HTTP ${response.status}`);
|
|
191
|
+
error.status = response.status;
|
|
192
|
+
try {
|
|
193
|
+
error.data = await response.json();
|
|
194
|
+
} catch {
|
|
195
|
+
error.data = null;
|
|
196
|
+
}
|
|
197
|
+
throw error;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
return response.json();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// POST request
|
|
204
|
+
async function createUser(userData) {
|
|
205
|
+
return apiRequest("/api/users", {
|
|
206
|
+
method: "POST",
|
|
207
|
+
body: JSON.stringify(userData),
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// AbortController for cancellation
|
|
212
|
+
function fetchWithAbort(url) {
|
|
213
|
+
const controller = new AbortController();
|
|
214
|
+
|
|
215
|
+
const promise = fetch(url, { signal: controller.signal })
|
|
216
|
+
.then((r) => r.json());
|
|
217
|
+
|
|
218
|
+
return { promise, abort: () => controller.abort() };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Timeout with AbortController
|
|
222
|
+
async function fetchWithTimeout(url, timeoutMs = 5000) {
|
|
223
|
+
const controller = new AbortController();
|
|
224
|
+
const timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
225
|
+
|
|
226
|
+
try {
|
|
227
|
+
const response = await fetch(url, { signal: controller.signal });
|
|
228
|
+
return await response.json();
|
|
229
|
+
} finally {
|
|
230
|
+
clearTimeout(timeoutId);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Abort previous request (search-as-you-type)
|
|
235
|
+
let currentController = null;
|
|
236
|
+
|
|
237
|
+
async function search(query) {
|
|
238
|
+
// Cancel previous request
|
|
239
|
+
currentController?.abort();
|
|
240
|
+
currentController = new AbortController();
|
|
241
|
+
|
|
242
|
+
try {
|
|
243
|
+
const response = await fetch(`/api/search?q=${encodeURIComponent(query)}`, {
|
|
244
|
+
signal: currentController.signal,
|
|
245
|
+
});
|
|
246
|
+
return await response.json();
|
|
247
|
+
} catch (error) {
|
|
248
|
+
if (error.name === "AbortError") {
|
|
249
|
+
return null; // Intentional cancellation, not an error
|
|
250
|
+
}
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
### 5. Web APIs
|
|
257
|
+
|
|
258
|
+
```javascript
|
|
259
|
+
// IntersectionObserver -- lazy loading, infinite scroll, animations
|
|
260
|
+
const observer = new IntersectionObserver(
|
|
261
|
+
(entries) => {
|
|
262
|
+
for (const entry of entries) {
|
|
263
|
+
if (entry.isIntersecting) {
|
|
264
|
+
entry.target.classList.add("visible");
|
|
265
|
+
observer.unobserve(entry.target); // One-time observation
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
{ threshold: 0.1, rootMargin: "50px" }
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
document.querySelectorAll(".lazy").forEach((el) => observer.observe(el));
|
|
273
|
+
|
|
274
|
+
// ResizeObserver -- respond to element size changes
|
|
275
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
276
|
+
for (const entry of entries) {
|
|
277
|
+
const { width, height } = entry.contentRect;
|
|
278
|
+
entry.target.dataset.size = width > 600 ? "large" : "small";
|
|
279
|
+
}
|
|
280
|
+
});
|
|
281
|
+
|
|
282
|
+
resizeObserver.observe(document.querySelector(".responsive-container"));
|
|
283
|
+
|
|
284
|
+
// MutationObserver -- watch DOM changes
|
|
285
|
+
const mutationObserver = new MutationObserver((mutations) => {
|
|
286
|
+
for (const mutation of mutations) {
|
|
287
|
+
if (mutation.type === "childList") {
|
|
288
|
+
console.log("Children changed:", mutation.addedNodes, mutation.removedNodes);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
mutationObserver.observe(container, { childList: true, subtree: true });
|
|
294
|
+
|
|
295
|
+
// Broadcast Channel -- communicate between tabs
|
|
296
|
+
const channel = new BroadcastChannel("app-events");
|
|
297
|
+
channel.postMessage({ type: "logout" });
|
|
298
|
+
channel.addEventListener("message", (event) => {
|
|
299
|
+
if (event.data.type === "logout") {
|
|
300
|
+
window.location.href = "/login";
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
// structuredClone -- deep copy (no functions or DOM nodes)
|
|
305
|
+
const original = { nested: { array: [1, 2, 3], date: new Date() } };
|
|
306
|
+
const cloned = structuredClone(original);
|
|
307
|
+
cloned.nested.array.push(4); // Does not affect original
|
|
308
|
+
|
|
309
|
+
// Clipboard API
|
|
310
|
+
async function copyToClipboard(text) {
|
|
311
|
+
try {
|
|
312
|
+
await navigator.clipboard.writeText(text);
|
|
313
|
+
return true;
|
|
314
|
+
} catch {
|
|
315
|
+
return false;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### 6. DOM Manipulation Best Practices
|
|
321
|
+
|
|
322
|
+
```javascript
|
|
323
|
+
// Query elements
|
|
324
|
+
const element = document.querySelector(".my-class");
|
|
325
|
+
const elements = document.querySelectorAll("[data-action]");
|
|
326
|
+
|
|
327
|
+
// Create elements efficiently
|
|
328
|
+
function createElement(tag, attrs = {}, children = []) {
|
|
329
|
+
const el = document.createElement(tag);
|
|
330
|
+
for (const [key, value] of Object.entries(attrs)) {
|
|
331
|
+
if (key === "class") {
|
|
332
|
+
el.className = value;
|
|
333
|
+
} else if (key === "style" && typeof value === "object") {
|
|
334
|
+
Object.assign(el.style, value);
|
|
335
|
+
} else if (key.startsWith("data-")) {
|
|
336
|
+
el.dataset[key.slice(5)] = value;
|
|
337
|
+
} else {
|
|
338
|
+
el.setAttribute(key, value);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
for (const child of children) {
|
|
342
|
+
if (typeof child === "string") {
|
|
343
|
+
el.append(document.createTextNode(child));
|
|
344
|
+
} else {
|
|
345
|
+
el.append(child);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
return el;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Batch DOM updates with DocumentFragment
|
|
352
|
+
function renderList(items, container) {
|
|
353
|
+
const fragment = document.createDocumentFragment();
|
|
354
|
+
for (const item of items) {
|
|
355
|
+
fragment.append(
|
|
356
|
+
createElement("li", { class: "item" }, [item.name])
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
container.replaceChildren(fragment);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Template element for complex HTML
|
|
363
|
+
function renderCard(data) {
|
|
364
|
+
const template = document.querySelector("#card-template");
|
|
365
|
+
const clone = template.content.cloneNode(true);
|
|
366
|
+
clone.querySelector(".title").textContent = data.title;
|
|
367
|
+
clone.querySelector(".body").textContent = data.body;
|
|
368
|
+
return clone;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// Avoid layout thrashing -- batch reads and writes
|
|
372
|
+
function resizeElements(elements) {
|
|
373
|
+
// Read all dimensions first
|
|
374
|
+
const measurements = elements.map((el) => ({
|
|
375
|
+
el,
|
|
376
|
+
width: el.offsetWidth,
|
|
377
|
+
height: el.offsetHeight,
|
|
378
|
+
}));
|
|
379
|
+
|
|
380
|
+
// Then write all changes
|
|
381
|
+
for (const { el, width, height } of measurements) {
|
|
382
|
+
el.style.width = `${width * 2}px`;
|
|
383
|
+
el.style.height = `${height * 2}px`;
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### 7. Event Delegation
|
|
389
|
+
|
|
390
|
+
```javascript
|
|
391
|
+
// Event delegation -- one listener handles many elements
|
|
392
|
+
document.querySelector(".todo-list").addEventListener("click", (event) => {
|
|
393
|
+
const target = event.target;
|
|
394
|
+
|
|
395
|
+
if (target.matches(".delete-btn")) {
|
|
396
|
+
const todoItem = target.closest(".todo-item");
|
|
397
|
+
todoItem.remove();
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (target.matches(".toggle-btn")) {
|
|
402
|
+
const todoItem = target.closest(".todo-item");
|
|
403
|
+
todoItem.classList.toggle("completed");
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (target.matches(".edit-btn")) {
|
|
408
|
+
const todoItem = target.closest(".todo-item");
|
|
409
|
+
startEditing(todoItem);
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Custom event system
|
|
415
|
+
class EventEmitter {
|
|
416
|
+
#listeners = new Map();
|
|
417
|
+
|
|
418
|
+
on(event, callback) {
|
|
419
|
+
if (!this.#listeners.has(event)) {
|
|
420
|
+
this.#listeners.set(event, new Set());
|
|
421
|
+
}
|
|
422
|
+
this.#listeners.get(event).add(callback);
|
|
423
|
+
return () => this.off(event, callback); // Return unsubscribe function
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
off(event, callback) {
|
|
427
|
+
this.#listeners.get(event)?.delete(callback);
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
emit(event, data) {
|
|
431
|
+
for (const callback of this.#listeners.get(event) ?? []) {
|
|
432
|
+
callback(data);
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// CustomEvent for DOM events
|
|
438
|
+
function dispatchCustomEvent(element, name, detail) {
|
|
439
|
+
element.dispatchEvent(
|
|
440
|
+
new CustomEvent(name, { detail, bubbles: true, composed: true })
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
### 8. WeakMap, WeakSet, and Private State
|
|
446
|
+
|
|
447
|
+
```javascript
|
|
448
|
+
// WeakMap for private data (no memory leak)
|
|
449
|
+
const _private = new WeakMap();
|
|
450
|
+
|
|
451
|
+
class SecureStore {
|
|
452
|
+
constructor(secret) {
|
|
453
|
+
_private.set(this, { secret, cache: new Map() });
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
getSecret() {
|
|
457
|
+
return _private.get(this).secret;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
// Private class fields (ES2022) -- preferred modern approach
|
|
462
|
+
class ModernStore {
|
|
463
|
+
#secret;
|
|
464
|
+
#cache = new Map();
|
|
465
|
+
|
|
466
|
+
constructor(secret) {
|
|
467
|
+
this.#secret = secret;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
get secret() {
|
|
471
|
+
return this.#secret;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
#internalMethod() {
|
|
475
|
+
// Truly private
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
// WeakSet for tracking objects without preventing GC
|
|
480
|
+
const processed = new WeakSet();
|
|
481
|
+
|
|
482
|
+
function processOnce(obj) {
|
|
483
|
+
if (processed.has(obj)) return;
|
|
484
|
+
processed.add(obj);
|
|
485
|
+
// Process object...
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
// WeakRef for caches (ES2021)
|
|
489
|
+
class ObjectCache {
|
|
490
|
+
#cache = new Map();
|
|
491
|
+
|
|
492
|
+
get(key) {
|
|
493
|
+
const ref = this.#cache.get(key);
|
|
494
|
+
if (!ref) return undefined;
|
|
495
|
+
const value = ref.deref();
|
|
496
|
+
if (value === undefined) {
|
|
497
|
+
this.#cache.delete(key);
|
|
498
|
+
}
|
|
499
|
+
return value;
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
set(key, value) {
|
|
503
|
+
this.#cache.set(key, new WeakRef(value));
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
```
|
|
507
|
+
|
|
508
|
+
### 9. Proxy and Reflect
|
|
509
|
+
|
|
510
|
+
```javascript
|
|
511
|
+
// Validation proxy
|
|
512
|
+
function createValidated(schema) {
|
|
513
|
+
return new Proxy(
|
|
514
|
+
{},
|
|
515
|
+
{
|
|
516
|
+
set(target, prop, value) {
|
|
517
|
+
const validator = schema[prop];
|
|
518
|
+
if (validator && !validator(value)) {
|
|
519
|
+
throw new TypeError(
|
|
520
|
+
`Invalid value for ${String(prop)}: ${value}`
|
|
521
|
+
);
|
|
522
|
+
}
|
|
523
|
+
return Reflect.set(target, prop, value);
|
|
524
|
+
},
|
|
525
|
+
}
|
|
526
|
+
);
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
const user = createValidated({
|
|
530
|
+
name: (v) => typeof v === "string" && v.length > 0,
|
|
531
|
+
age: (v) => typeof v === "number" && v >= 0 && v <= 150,
|
|
532
|
+
email: (v) => typeof v === "string" && v.includes("@"),
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
user.name = "Alice"; // OK
|
|
536
|
+
// user.age = -1; // Throws TypeError
|
|
537
|
+
|
|
538
|
+
// Observable proxy (reactive data)
|
|
539
|
+
function observable(target, onChange) {
|
|
540
|
+
return new Proxy(target, {
|
|
541
|
+
set(obj, prop, value) {
|
|
542
|
+
const oldValue = obj[prop];
|
|
543
|
+
const result = Reflect.set(obj, prop, value);
|
|
544
|
+
if (oldValue !== value) {
|
|
545
|
+
onChange(prop, value, oldValue);
|
|
546
|
+
}
|
|
547
|
+
return result;
|
|
548
|
+
},
|
|
549
|
+
deleteProperty(obj, prop) {
|
|
550
|
+
const oldValue = obj[prop];
|
|
551
|
+
const result = Reflect.deleteProperty(obj, prop);
|
|
552
|
+
onChange(prop, undefined, oldValue);
|
|
553
|
+
return result;
|
|
554
|
+
},
|
|
555
|
+
});
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
const state = observable({ count: 0 }, (prop, newVal) => {
|
|
559
|
+
console.log(`${String(prop)} changed to ${newVal}`);
|
|
560
|
+
render(); // Re-render on state change
|
|
561
|
+
});
|
|
562
|
+
|
|
563
|
+
state.count++; // Logs: "count changed to 1"
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
### 10. Web Components and Custom Elements
|
|
567
|
+
|
|
568
|
+
```javascript
|
|
569
|
+
// Custom element with Shadow DOM
|
|
570
|
+
class AppCounter extends HTMLElement {
|
|
571
|
+
#count = 0;
|
|
572
|
+
#shadow;
|
|
573
|
+
|
|
574
|
+
static get observedAttributes() {
|
|
575
|
+
return ["initial"];
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
constructor() {
|
|
579
|
+
super();
|
|
580
|
+
this.#shadow = this.attachShadow({ mode: "open" });
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
connectedCallback() {
|
|
584
|
+
this.#render();
|
|
585
|
+
this.#shadow
|
|
586
|
+
.querySelector(".increment")
|
|
587
|
+
.addEventListener("click", () => this.#increment());
|
|
588
|
+
this.#shadow
|
|
589
|
+
.querySelector(".decrement")
|
|
590
|
+
.addEventListener("click", () => this.#decrement());
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
attributeChangedCallback(name, oldValue, newValue) {
|
|
594
|
+
if (name === "initial") {
|
|
595
|
+
this.#count = parseInt(newValue, 10) || 0;
|
|
596
|
+
this.#render();
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
#increment() {
|
|
601
|
+
this.#count++;
|
|
602
|
+
this.#update();
|
|
603
|
+
this.dispatchEvent(
|
|
604
|
+
new CustomEvent("change", { detail: { count: this.#count } })
|
|
605
|
+
);
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
#decrement() {
|
|
609
|
+
this.#count--;
|
|
610
|
+
this.#update();
|
|
611
|
+
this.dispatchEvent(
|
|
612
|
+
new CustomEvent("change", { detail: { count: this.#count } })
|
|
613
|
+
);
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
#update() {
|
|
617
|
+
const display = this.#shadow.querySelector(".count");
|
|
618
|
+
if (display) display.textContent = this.#count;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
#render() {
|
|
622
|
+
this.#shadow.innerHTML = `
|
|
623
|
+
<style>
|
|
624
|
+
:host { display: inline-flex; gap: 8px; align-items: center; }
|
|
625
|
+
button { padding: 4px 12px; cursor: pointer; }
|
|
626
|
+
.count { font-weight: bold; min-width: 2ch; text-align: center; }
|
|
627
|
+
</style>
|
|
628
|
+
<button class="decrement">-</button>
|
|
629
|
+
<span class="count">${this.#count}</span>
|
|
630
|
+
<button class="increment">+</button>
|
|
631
|
+
`;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
customElements.define("app-counter", AppCounter);
|
|
636
|
+
|
|
637
|
+
// Usage in HTML:
|
|
638
|
+
// <app-counter initial="5"></app-counter>
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
### 11. Iterators and Generators
|
|
642
|
+
|
|
643
|
+
```javascript
|
|
644
|
+
// Custom iterable
|
|
645
|
+
class Range {
|
|
646
|
+
#start;
|
|
647
|
+
#end;
|
|
648
|
+
#step;
|
|
649
|
+
|
|
650
|
+
constructor(start, end, step = 1) {
|
|
651
|
+
this.#start = start;
|
|
652
|
+
this.#end = end;
|
|
653
|
+
this.#step = step;
|
|
654
|
+
}
|
|
655
|
+
|
|
656
|
+
[Symbol.iterator]() {
|
|
657
|
+
let current = this.#start;
|
|
658
|
+
const end = this.#end;
|
|
659
|
+
const step = this.#step;
|
|
660
|
+
|
|
661
|
+
return {
|
|
662
|
+
next() {
|
|
663
|
+
if (current < end) {
|
|
664
|
+
const value = current;
|
|
665
|
+
current += step;
|
|
666
|
+
return { value, done: false };
|
|
667
|
+
}
|
|
668
|
+
return { done: true };
|
|
669
|
+
},
|
|
670
|
+
};
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
for (const n of new Range(0, 10, 2)) {
|
|
675
|
+
console.log(n); // 0, 2, 4, 6, 8
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Generator function
|
|
679
|
+
function* fibonacci() {
|
|
680
|
+
let a = 0;
|
|
681
|
+
let b = 1;
|
|
682
|
+
while (true) {
|
|
683
|
+
yield a;
|
|
684
|
+
[a, b] = [b, a + b];
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Take first N from infinite generator
|
|
689
|
+
function* take(iterable, n) {
|
|
690
|
+
let count = 0;
|
|
691
|
+
for (const item of iterable) {
|
|
692
|
+
if (count >= n) return;
|
|
693
|
+
yield item;
|
|
694
|
+
count++;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
const first10 = [...take(fibonacci(), 10)];
|
|
699
|
+
|
|
700
|
+
// Async generator
|
|
701
|
+
async function* streamEvents(url) {
|
|
702
|
+
const response = await fetch(url);
|
|
703
|
+
const reader = response.body.getReader();
|
|
704
|
+
const decoder = new TextDecoder();
|
|
705
|
+
|
|
706
|
+
while (true) {
|
|
707
|
+
const { done, value } = await reader.read();
|
|
708
|
+
if (done) break;
|
|
709
|
+
yield decoder.decode(value, { stream: true });
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
// Consuming async generator
|
|
714
|
+
for await (const chunk of streamEvents("/api/stream")) {
|
|
715
|
+
processChunk(chunk);
|
|
716
|
+
}
|
|
717
|
+
```
|
|
718
|
+
|
|
719
|
+
## Anti-Patterns
|
|
720
|
+
|
|
721
|
+
| Anti-Pattern | Why It Is Bad | Do This Instead |
|
|
722
|
+
|-------------|--------------|----------------|
|
|
723
|
+
| `var` declarations | Function-scoped, hoisting bugs | Use `const` by default, `let` when needed |
|
|
724
|
+
| `==` comparison | Type coercion surprises | Always use `===` and `!==` |
|
|
725
|
+
| `innerHTML` with user data | XSS vulnerability | Use `textContent` or sanitize |
|
|
726
|
+
| `document.write()` | Blocks parsing, breaks streaming | Use DOM APIs |
|
|
727
|
+
| Nested callbacks | Callback hell, hard to debug | Use async/await |
|
|
728
|
+
| `for...in` on arrays | Iterates prototype properties | Use `for...of` or array methods |
|
|
729
|
+
| `.then().catch()` chains | Harder to read and debug | Use async/await with try/catch |
|
|
730
|
+
| Modifying built-in prototypes | Breaks other code, conflicts | Use utility functions or subclassing |
|
|
731
|
+
|
|
732
|
+
## No-Framework Application Architecture
|
|
733
|
+
|
|
734
|
+
```javascript
|
|
735
|
+
// Simple state management
|
|
736
|
+
class Store {
|
|
737
|
+
#state;
|
|
738
|
+
#listeners = new Set();
|
|
739
|
+
|
|
740
|
+
constructor(initialState) {
|
|
741
|
+
this.#state = structuredClone(initialState);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
getState() {
|
|
745
|
+
return this.#state;
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
setState(updater) {
|
|
749
|
+
const newState =
|
|
750
|
+
typeof updater === "function" ? updater(this.#state) : updater;
|
|
751
|
+
this.#state = { ...this.#state, ...newState };
|
|
752
|
+
this.#notify();
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
subscribe(listener) {
|
|
756
|
+
this.#listeners.add(listener);
|
|
757
|
+
return () => this.#listeners.delete(listener);
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
#notify() {
|
|
761
|
+
for (const listener of this.#listeners) {
|
|
762
|
+
listener(this.#state);
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// Router
|
|
768
|
+
class Router {
|
|
769
|
+
#routes = new Map();
|
|
770
|
+
|
|
771
|
+
addRoute(path, handler) {
|
|
772
|
+
this.#routes.set(path, handler);
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
start() {
|
|
776
|
+
window.addEventListener("popstate", () => this.#resolve());
|
|
777
|
+
document.addEventListener("click", (e) => {
|
|
778
|
+
const link = e.target.closest("a[data-route]");
|
|
779
|
+
if (link) {
|
|
780
|
+
e.preventDefault();
|
|
781
|
+
history.pushState(null, "", link.href);
|
|
782
|
+
this.#resolve();
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
this.#resolve();
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
#resolve() {
|
|
789
|
+
const path = location.pathname;
|
|
790
|
+
const handler = this.#routes.get(path);
|
|
791
|
+
if (handler) handler();
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
## Resources
|
|
797
|
+
|
|
798
|
+
- **MDN Web Docs**: https://developer.mozilla.org/
|
|
799
|
+
- **JavaScript.info**: https://javascript.info/
|
|
800
|
+
- **Web Components MDN**: https://developer.mozilla.org/en-US/docs/Web/API/Web_components
|
|
801
|
+
- **Can I Use**: https://caniuse.com/
|
|
802
|
+
- **TC39 Proposals**: https://github.com/tc39/proposals
|
|
803
|
+
- **Web Platform Tests**: https://web-platform-tests.org/
|