claude-code-templates 1.21.11 → 1.21.13
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/.claude/agents/agent-expert.md +477 -0
- package/.claude/agents/cli-ui-designer.md +405 -0
- package/.claude/agents/command-expert.md +421 -0
- package/.claude/agents/docusaurus-expert.md +173 -0
- package/.claude/agents/frontend-developer.md +32 -0
- package/.claude/agents/mcp-expert.md +258 -0
- package/.claude/commands/lint.md +111 -0
- package/.claude/commands/test.md +73 -0
- package/.claude/settings.local.json +56 -0
- package/.env.example +26 -0
- package/.github/WORKFLOWS_REFERENCE.md +88 -0
- package/.github/workflows/deploy-docusaurus.yml +31 -0
- package/.github/workflows/deploy.yml +33 -0
- package/.github/workflows/publish-package.yml +125 -0
- package/.mcp.json +4 -0
- package/AGENTS.md +4 -0
- package/CLAUDE.md +482 -0
- package/CLAUDE_JOBS_README.md +148 -0
- package/CODE_OF_CONDUCT.md +82 -0
- package/CONTRIBUTING.md +505 -0
- package/DEPLOYMENT.md +60 -0
- package/LICENSE +21 -0
- package/README.md +77 -79
- package/ROADMAP.md +278 -0
- package/SECURITY.md +65 -0
- package/api/index.html +1 -0
- package/api/package.json +7 -0
- package/api/track-download-supabase.js +150 -0
- package/cli-tool/Makefile +102 -0
- package/cli-tool/README.md +126 -0
- package/cli-tool/TESTING.md +262 -0
- package/cli-tool/components/agents/ai-specialists/ai-ethics-advisor.md +195 -0
- package/cli-tool/components/agents/ai-specialists/hackathon-ai-strategist.md +46 -0
- package/cli-tool/components/agents/ai-specialists/llms-maintainer.md +94 -0
- package/cli-tool/components/agents/ai-specialists/model-evaluator.md +150 -0
- package/cli-tool/components/agents/ai-specialists/prompt-engineer.md +112 -0
- package/cli-tool/components/agents/ai-specialists/search-specialist.md +59 -0
- package/cli-tool/components/agents/ai-specialists/task-decomposition-expert.md +97 -0
- package/cli-tool/components/agents/api-graphql/graphql-architect.md +208 -0
- package/cli-tool/components/agents/api-graphql/graphql-performance-optimizer.md +357 -0
- package/cli-tool/components/agents/api-graphql/graphql-security-specialist.md +519 -0
- package/cli-tool/components/agents/blockchain-web3/smart-contract-auditor.md +32 -0
- package/cli-tool/components/agents/blockchain-web3/smart-contract-specialist.md +32 -0
- package/cli-tool/components/agents/blockchain-web3/web3-integration-specialist.md +32 -0
- package/cli-tool/components/agents/business-marketing/business-analyst.md +194 -0
- package/cli-tool/components/agents/business-marketing/content-marketer.md +36 -0
- package/cli-tool/components/agents/business-marketing/customer-support.md +36 -0
- package/cli-tool/components/agents/business-marketing/legal-advisor.md +50 -0
- package/cli-tool/components/agents/business-marketing/marketing-attribution-analyst.md +352 -0
- package/cli-tool/components/agents/business-marketing/payment-integration.md +33 -0
- package/cli-tool/components/agents/business-marketing/product-strategist.md +212 -0
- package/cli-tool/components/agents/business-marketing/risk-manager.md +42 -0
- package/cli-tool/components/agents/business-marketing/sales-automator.md +36 -0
- package/cli-tool/components/agents/data-ai/ai-engineer.md +33 -0
- package/cli-tool/components/agents/data-ai/computer-vision-engineer.md +562 -0
- package/cli-tool/components/agents/data-ai/data-engineer.md +33 -0
- package/cli-tool/components/agents/data-ai/data-scientist.md +337 -0
- package/cli-tool/components/agents/data-ai/ml-engineer.md +33 -0
- package/cli-tool/components/agents/data-ai/mlops-engineer.md +58 -0
- package/cli-tool/components/agents/data-ai/nlp-engineer.md +680 -0
- package/cli-tool/components/agents/data-ai/quant-analyst.md +33 -0
- package/cli-tool/components/agents/database/database-admin.md +33 -0
- package/cli-tool/components/agents/database/database-architect.md +590 -0
- package/cli-tool/components/agents/database/database-optimization.md +33 -0
- package/cli-tool/components/agents/database/database-optimizer.md +33 -0
- package/cli-tool/components/agents/database/neon-auth-specialist.md +175 -0
- package/cli-tool/components/agents/database/neon-database-architect.md +141 -0
- package/cli-tool/components/agents/database/neon-expert.md +846 -0
- package/cli-tool/components/agents/database/nosql-specialist.md +708 -0
- package/cli-tool/components/agents/database/supabase-schema-architect.md +138 -0
- package/cli-tool/components/agents/deep-research-team/academic-researcher.md +33 -0
- package/cli-tool/components/agents/deep-research-team/agent-overview.md +235 -0
- package/cli-tool/components/agents/deep-research-team/competitive-intelligence-analyst.md +530 -0
- package/cli-tool/components/agents/deep-research-team/data-analyst.md +112 -0
- package/cli-tool/components/agents/deep-research-team/fact-checker.md +553 -0
- package/cli-tool/components/agents/deep-research-team/query-clarifier.md +73 -0
- package/cli-tool/components/agents/deep-research-team/report-generator.md +108 -0
- package/cli-tool/components/agents/deep-research-team/research-brief-generator.md +108 -0
- package/cli-tool/components/agents/deep-research-team/research-coordinator.md +94 -0
- package/cli-tool/components/agents/deep-research-team/research-orchestrator.md +119 -0
- package/cli-tool/components/agents/deep-research-team/research-synthesizer.md +109 -0
- package/cli-tool/components/agents/deep-research-team/technical-researcher.md +95 -0
- package/cli-tool/components/agents/development-team/backend-architect.md +31 -0
- package/cli-tool/components/agents/development-team/cli-ui-designer.md +405 -0
- package/cli-tool/components/agents/development-team/devops-engineer.md +886 -0
- package/cli-tool/components/agents/development-team/frontend-developer.md +32 -0
- package/cli-tool/components/agents/development-team/fullstack-developer.md +1205 -0
- package/cli-tool/components/agents/development-team/ios-developer.md +36 -0
- package/cli-tool/components/agents/development-team/mobile-developer.md +33 -0
- package/cli-tool/components/agents/development-team/ui-ux-designer.md +36 -0
- package/cli-tool/components/agents/development-tools/code-reviewer.md +30 -0
- package/cli-tool/components/agents/development-tools/command-expert.md +422 -0
- package/cli-tool/components/agents/development-tools/context-manager.md +65 -0
- package/cli-tool/components/agents/development-tools/debugger.md +31 -0
- package/cli-tool/components/agents/development-tools/dx-optimizer.md +64 -0
- package/cli-tool/components/agents/development-tools/error-detective.md +33 -0
- package/cli-tool/components/agents/development-tools/mcp-expert.md +259 -0
- package/cli-tool/components/agents/development-tools/performance-profiler.md +799 -0
- package/cli-tool/components/agents/development-tools/test-engineer.md +936 -0
- package/cli-tool/components/agents/devops-infrastructure/cloud-architect.md +33 -0
- package/cli-tool/components/agents/devops-infrastructure/deployment-engineer.md +33 -0
- package/cli-tool/components/agents/devops-infrastructure/devops-troubleshooter.md +33 -0
- package/cli-tool/components/agents/devops-infrastructure/monitoring-specialist.md +36 -0
- package/cli-tool/components/agents/devops-infrastructure/network-engineer.md +33 -0
- package/cli-tool/components/agents/devops-infrastructure/security-engineer.md +971 -0
- package/cli-tool/components/agents/devops-infrastructure/terraform-specialist.md +36 -0
- package/cli-tool/components/agents/devops-infrastructure/vercel-deployment-specialist.md +357 -0
- package/cli-tool/components/agents/documentation/api-documenter.md +33 -0
- package/cli-tool/components/agents/documentation/changelog-generator.md +37 -0
- package/cli-tool/components/agents/documentation/docusaurus-expert.md +175 -0
- package/cli-tool/components/agents/documentation/technical-writer.md +37 -0
- package/cli-tool/components/agents/expert-advisors/agent-expert.md +491 -0
- package/cli-tool/components/agents/expert-advisors/architect-review.md +50 -0
- package/cli-tool/components/agents/expert-advisors/dependency-manager.md +45 -0
- package/cli-tool/components/agents/expert-advisors/documentation-expert.md +47 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/audio-mixer.md +37 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/audio-quality-controller.md +100 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/podcast-content-analyzer.md +60 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/podcast-metadata-specialist.md +46 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/podcast-transcriber.md +68 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/social-media-clip-creator.md +69 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/timestamp-precision-specialist.md +98 -0
- package/cli-tool/components/agents/ffmpeg-clip-team/video-editor.md +37 -0
- package/cli-tool/components/agents/game-development/3d-artist.md +37 -0
- package/cli-tool/components/agents/game-development/game-designer.md +37 -0
- package/cli-tool/components/agents/game-development/unity-game-developer.md +110 -0
- package/cli-tool/components/agents/game-development/unreal-engine-developer.md +128 -0
- package/cli-tool/components/agents/git/git-flow-manager.md +329 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-deployment-orchestrator.md +101 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-integration-engineer.md +37 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-protocol-specialist.md +37 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-registry-navigator.md +112 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-security-auditor.md +70 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-server-architect.md +74 -0
- package/cli-tool/components/agents/mcp-dev-team/mcp-testing-engineer.md +106 -0
- package/cli-tool/components/agents/modernization/architecture-modernizer.md +37 -0
- package/cli-tool/components/agents/modernization/cloud-migration-specialist.md +37 -0
- package/cli-tool/components/agents/modernization/legacy-modernizer.md +33 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/daily_notes_connector.py +306 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/enhance_tag_standardizer.py +343 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/find_keyword_connections.py +216 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/fix_quoted_tags.py +82 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/implement_entity_connections.py +195 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/link_suggester.py +301 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/metadata_adder.py +197 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/moc_generator.py +296 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/parse_keyword_connections.py +122 -0
- package/cli-tool/components/agents/obsidian-ops-team/Scripts/tag_standardizer.py +387 -0
- package/cli-tool/components/agents/obsidian-ops-team/connection-agent.md +67 -0
- package/cli-tool/components/agents/obsidian-ops-team/content-curator.md +81 -0
- package/cli-tool/components/agents/obsidian-ops-team/metadata-agent.md +51 -0
- package/cli-tool/components/agents/obsidian-ops-team/moc-agent.md +112 -0
- package/cli-tool/components/agents/obsidian-ops-team/review-agent.md +94 -0
- package/cli-tool/components/agents/obsidian-ops-team/tag-agent.md +92 -0
- package/cli-tool/components/agents/obsidian-ops-team/vault-optimizer.md +76 -0
- package/cli-tool/components/agents/ocr-extraction-team/document-structure-analyzer.md +37 -0
- package/cli-tool/components/agents/ocr-extraction-team/markdown-syntax-formatter.md +58 -0
- package/cli-tool/components/agents/ocr-extraction-team/ocr-grammar-fixer.md +36 -0
- package/cli-tool/components/agents/ocr-extraction-team/ocr-preprocessing-optimizer.md +37 -0
- package/cli-tool/components/agents/ocr-extraction-team/ocr-quality-assurance.md +62 -0
- package/cli-tool/components/agents/ocr-extraction-team/text-comparison-validator.md +60 -0
- package/cli-tool/components/agents/ocr-extraction-team/visual-analysis-ocr.md +52 -0
- package/cli-tool/components/agents/performance-testing/load-testing-specialist.md +37 -0
- package/cli-tool/components/agents/performance-testing/performance-engineer.md +33 -0
- package/cli-tool/components/agents/performance-testing/react-performance-optimization.md +65 -0
- package/cli-tool/components/agents/performance-testing/test-automator.md +33 -0
- package/cli-tool/components/agents/performance-testing/web-vitals-optimizer.md +37 -0
- package/cli-tool/components/agents/podcast-creator-team/academic-research-synthesizer.md +61 -0
- package/cli-tool/components/agents/podcast-creator-team/comprehensive-researcher.md +49 -0
- package/cli-tool/components/agents/podcast-creator-team/episode-orchestrator.md +52 -0
- package/cli-tool/components/agents/podcast-creator-team/guest-outreach-coordinator.md +37 -0
- package/cli-tool/components/agents/podcast-creator-team/market-research-analyst.md +54 -0
- package/cli-tool/components/agents/podcast-creator-team/podcast-editor.md +37 -0
- package/cli-tool/components/agents/podcast-creator-team/podcast-trend-scout.md +60 -0
- package/cli-tool/components/agents/podcast-creator-team/project-supervisor-orchestrator.md +48 -0
- package/cli-tool/components/agents/podcast-creator-team/seo-podcast-optimizer.md +58 -0
- package/cli-tool/components/agents/podcast-creator-team/social-media-copywriter.md +57 -0
- package/cli-tool/components/agents/podcast-creator-team/twitter-ai-influencer-manager.md +62 -0
- package/cli-tool/components/agents/programming-languages/c-pro.md +36 -0
- package/cli-tool/components/agents/programming-languages/c-sharp-pro.md +40 -0
- package/cli-tool/components/agents/programming-languages/cpp-pro.md +39 -0
- package/cli-tool/components/agents/programming-languages/golang-pro.md +33 -0
- package/cli-tool/components/agents/programming-languages/javascript-pro.md +36 -0
- package/cli-tool/components/agents/programming-languages/php-pro.md +44 -0
- package/cli-tool/components/agents/programming-languages/python-pro.md +33 -0
- package/cli-tool/components/agents/programming-languages/rust-pro.md +36 -0
- package/cli-tool/components/agents/programming-languages/shell-scripting-pro.md +38 -0
- package/cli-tool/components/agents/programming-languages/sql-pro.md +36 -0
- package/cli-tool/components/agents/programming-languages/typescript-pro.md +38 -0
- package/cli-tool/components/agents/realtime/supabase-realtime-optimizer.md +193 -0
- package/cli-tool/components/agents/security/api-security-audit.md +93 -0
- package/cli-tool/components/agents/security/compliance-specialist.md +37 -0
- package/cli-tool/components/agents/security/incident-responder.md +75 -0
- package/cli-tool/components/agents/security/penetration-tester.md +37 -0
- package/cli-tool/components/agents/security/security-auditor.md +33 -0
- package/cli-tool/components/agents/web-tools/nextjs-architecture-expert.md +194 -0
- package/cli-tool/components/agents/web-tools/react-performance-optimizer.md +425 -0
- package/cli-tool/components/agents/web-tools/seo-analyzer.md +37 -0
- package/cli-tool/components/agents/web-tools/url-context-validator.md +61 -0
- package/cli-tool/components/agents/web-tools/url-link-extractor.md +59 -0
- package/cli-tool/components/agents/web-tools/web-accessibility-checker.md +37 -0
- package/cli-tool/components/commands/automation/act.md +57 -0
- package/cli-tool/components/commands/automation/ci-pipeline.md +378 -0
- package/cli-tool/components/commands/automation/husky.md +130 -0
- package/cli-tool/components/commands/automation/workflow-orchestrator.md +576 -0
- package/cli-tool/components/commands/database/supabase-backup-manager.md +37 -0
- package/cli-tool/components/commands/database/supabase-data-explorer.md +37 -0
- package/cli-tool/components/commands/database/supabase-migration-assistant.md +37 -0
- package/cli-tool/components/commands/database/supabase-performance-optimizer.md +37 -0
- package/cli-tool/components/commands/database/supabase-realtime-monitor.md +37 -0
- package/cli-tool/components/commands/database/supabase-schema-sync.md +37 -0
- package/cli-tool/components/commands/database/supabase-security-audit.md +37 -0
- package/cli-tool/components/commands/database/supabase-type-generator.md +37 -0
- package/cli-tool/components/commands/deployment/add-changelog.md +92 -0
- package/cli-tool/components/commands/deployment/blue-green-deployment.md +824 -0
- package/cli-tool/components/commands/deployment/changelog-demo-command.md +43 -0
- package/cli-tool/components/commands/deployment/ci-setup.md +323 -0
- package/cli-tool/components/commands/deployment/containerize-application.md +93 -0
- package/cli-tool/components/commands/deployment/deployment-monitoring.md +1228 -0
- package/cli-tool/components/commands/deployment/hotfix-deploy.md +283 -0
- package/cli-tool/components/commands/deployment/prepare-release.md +357 -0
- package/cli-tool/components/commands/deployment/rollback-deploy.md +145 -0
- package/cli-tool/components/commands/deployment/setup-automated-releases.md +143 -0
- package/cli-tool/components/commands/deployment/setup-kubernetes-deployment.md +93 -0
- package/cli-tool/components/commands/documentation/create-architecture-documentation.md +95 -0
- package/cli-tool/components/commands/documentation/create-onboarding-guide.md +93 -0
- package/cli-tool/components/commands/documentation/doc-api.md +242 -0
- package/cli-tool/components/commands/documentation/docs-maintenance.md +119 -0
- package/cli-tool/components/commands/documentation/generate-api-documentation.md +97 -0
- package/cli-tool/components/commands/documentation/interactive-documentation.md +133 -0
- package/cli-tool/components/commands/documentation/load-llms-txt.md +39 -0
- package/cli-tool/components/commands/documentation/migration-guide.md +250 -0
- package/cli-tool/components/commands/documentation/troubleshooting-guide.md +370 -0
- package/cli-tool/components/commands/documentation/update-docs.md +107 -0
- package/cli-tool/components/commands/game-development/game-analytics-integration.md +128 -0
- package/cli-tool/components/commands/game-development/game-asset-pipeline.md +108 -0
- package/cli-tool/components/commands/game-development/game-performance-profiler.md +78 -0
- package/cli-tool/components/commands/game-development/game-testing-framework.md +112 -0
- package/cli-tool/components/commands/game-development/unity-project-setup.md +190 -0
- package/cli-tool/components/commands/git/feature.md +196 -0
- package/cli-tool/components/commands/git/finish.md +528 -0
- package/cli-tool/components/commands/git/flow-status.md +438 -0
- package/cli-tool/components/commands/git/hotfix.md +456 -0
- package/cli-tool/components/commands/git/release.md +381 -0
- package/cli-tool/components/commands/git-workflow/branch-cleanup.md +181 -0
- package/cli-tool/components/commands/git-workflow/commit.md +167 -0
- package/cli-tool/components/commands/git-workflow/create-pr.md +19 -0
- package/cli-tool/components/commands/git-workflow/create-pull-request.md +126 -0
- package/cli-tool/components/commands/git-workflow/create-worktrees.md +174 -0
- package/cli-tool/components/commands/git-workflow/fix-github-issue.md +13 -0
- package/cli-tool/components/commands/git-workflow/git-bisect-helper.md +261 -0
- package/cli-tool/components/commands/git-workflow/pr-review.md +76 -0
- package/cli-tool/components/commands/git-workflow/update-branch-name.md +9 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-api-tester.md +480 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-bundle-analyzer.md +406 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-component-generator.md +489 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-middleware-creator.md +712 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-migration-helper.md +778 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-performance-audit.md +653 -0
- package/cli-tool/components/commands/nextjs-vercel/nextjs-scaffold.md +237 -0
- package/cli-tool/components/commands/nextjs-vercel/vercel-deploy-optimize.md +341 -0
- package/cli-tool/components/commands/nextjs-vercel/vercel-edge-function.md +810 -0
- package/cli-tool/components/commands/nextjs-vercel/vercel-env-sync.md +666 -0
- package/cli-tool/components/commands/orchestration/archive.md +414 -0
- package/cli-tool/components/commands/orchestration/commit.md +305 -0
- package/cli-tool/components/commands/orchestration/find.md +272 -0
- package/cli-tool/components/commands/orchestration/log.md +355 -0
- package/cli-tool/components/commands/orchestration/move.md +220 -0
- package/cli-tool/components/commands/orchestration/optimize.md +375 -0
- package/cli-tool/components/commands/orchestration/remove.md +301 -0
- package/cli-tool/components/commands/orchestration/report.md +292 -0
- package/cli-tool/components/commands/orchestration/resume.md +256 -0
- package/cli-tool/components/commands/orchestration/start.md +169 -0
- package/cli-tool/components/commands/orchestration/status.md +219 -0
- package/cli-tool/components/commands/orchestration/sync.md +294 -0
- package/cli-tool/components/commands/performance/add-performance-monitoring.md +84 -0
- package/cli-tool/components/commands/performance/implement-caching-strategy.md +84 -0
- package/cli-tool/components/commands/performance/optimize-api-performance.md +119 -0
- package/cli-tool/components/commands/performance/optimize-build.md +139 -0
- package/cli-tool/components/commands/performance/optimize-bundle-size.md +84 -0
- package/cli-tool/components/commands/performance/optimize-database-performance.md +84 -0
- package/cli-tool/components/commands/performance/optimize-memory-usage.md +91 -0
- package/cli-tool/components/commands/performance/performance-audit.md +89 -0
- package/cli-tool/components/commands/performance/setup-cdn-optimization.md +84 -0
- package/cli-tool/components/commands/performance/system-behavior-simulator.md +415 -0
- package/cli-tool/components/commands/project-management/add-package.md +90 -0
- package/cli-tool/components/commands/project-management/add-to-changelog.md +37 -0
- package/cli-tool/components/commands/project-management/create-feature.md +130 -0
- package/cli-tool/components/commands/project-management/create-jtbd.md +37 -0
- package/cli-tool/components/commands/project-management/create-prd.md +36 -0
- package/cli-tool/components/commands/project-management/create-prp.md +37 -0
- package/cli-tool/components/commands/project-management/init-project.md +80 -0
- package/cli-tool/components/commands/project-management/milestone-tracker.md +44 -0
- package/cli-tool/components/commands/project-management/pac-configure.md +32 -0
- package/cli-tool/components/commands/project-management/pac-create-epic.md +41 -0
- package/cli-tool/components/commands/project-management/pac-create-ticket.md +42 -0
- package/cli-tool/components/commands/project-management/pac-update-status.md +39 -0
- package/cli-tool/components/commands/project-management/pac-validate.md +35 -0
- package/cli-tool/components/commands/project-management/project-health-check.md +58 -0
- package/cli-tool/components/commands/project-management/project-timeline-simulator.md +37 -0
- package/cli-tool/components/commands/project-management/project-to-linear.md +38 -0
- package/cli-tool/components/commands/project-management/release.md +31 -0
- package/cli-tool/components/commands/project-management/todo.md +62 -0
- package/cli-tool/components/commands/security/add-authentication-system.md +34 -0
- package/cli-tool/components/commands/security/dependency-audit.md +32 -0
- package/cli-tool/components/commands/security/penetration-test.md +40 -0
- package/cli-tool/components/commands/security/secrets-scanner.md +39 -0
- package/cli-tool/components/commands/security/security-audit.md +82 -0
- package/cli-tool/components/commands/security/security-hardening.md +33 -0
- package/cli-tool/components/commands/setup/create-database-migrations.md +35 -0
- package/cli-tool/components/commands/setup/design-database-schema.md +37 -0
- package/cli-tool/components/commands/setup/design-rest-api.md +37 -0
- package/cli-tool/components/commands/setup/implement-graphql-api.md +37 -0
- package/cli-tool/components/commands/setup/migrate-to-typescript.md +37 -0
- package/cli-tool/components/commands/setup/setup-ci-cd-pipeline.md +37 -0
- package/cli-tool/components/commands/setup/setup-development-environment.md +37 -0
- package/cli-tool/components/commands/setup/setup-docker-containers.md +37 -0
- package/cli-tool/components/commands/setup/setup-formatting.md +37 -0
- package/cli-tool/components/commands/setup/setup-linting.md +37 -0
- package/cli-tool/components/commands/setup/setup-monitoring-observability.md +37 -0
- package/cli-tool/components/commands/setup/setup-monorepo.md +37 -0
- package/cli-tool/components/commands/setup/setup-rate-limiting.md +37 -0
- package/cli-tool/components/commands/setup/update-dependencies.md +35 -0
- package/cli-tool/components/commands/simulation/business-scenario-explorer.md +37 -0
- package/cli-tool/components/commands/simulation/constraint-modeler.md +37 -0
- package/cli-tool/components/commands/simulation/decision-tree-explorer.md +37 -0
- package/cli-tool/components/commands/simulation/digital-twin-creator.md +37 -0
- package/cli-tool/components/commands/simulation/future-scenario-generator.md +37 -0
- package/cli-tool/components/commands/simulation/market-response-modeler.md +37 -0
- package/cli-tool/components/commands/simulation/monte-carlo-simulator.md +37 -0
- package/cli-tool/components/commands/simulation/simulation-calibrator.md +37 -0
- package/cli-tool/components/commands/simulation/system-dynamics-modeler.md +37 -0
- package/cli-tool/components/commands/simulation/timeline-compressor.md +37 -0
- package/cli-tool/components/commands/svelte/svelte:a11y.md +105 -0
- package/cli-tool/components/commands/svelte/svelte:component.md +81 -0
- package/cli-tool/components/commands/svelte/svelte:debug.md +48 -0
- package/cli-tool/components/commands/svelte/svelte:migrate.md +79 -0
- package/cli-tool/components/commands/svelte/svelte:optimize.md +99 -0
- package/cli-tool/components/commands/svelte/svelte:scaffold.md +89 -0
- package/cli-tool/components/commands/svelte/svelte:storybook-migrate.md +204 -0
- package/cli-tool/components/commands/svelte/svelte:storybook-mock.md +213 -0
- package/cli-tool/components/commands/svelte/svelte:storybook-setup.md +113 -0
- package/cli-tool/components/commands/svelte/svelte:storybook-story.md +145 -0
- package/cli-tool/components/commands/svelte/svelte:storybook-troubleshoot.md +191 -0
- package/cli-tool/components/commands/svelte/svelte:storybook.md +48 -0
- package/cli-tool/components/commands/svelte/svelte:test-coverage.md +77 -0
- package/cli-tool/components/commands/svelte/svelte:test-fix.md +74 -0
- package/cli-tool/components/commands/svelte/svelte:test-setup.md +85 -0
- package/cli-tool/components/commands/svelte/svelte:test.md +60 -0
- package/cli-tool/components/commands/sync/bidirectional-sync.md +37 -0
- package/cli-tool/components/commands/sync/bulk-import-issues.md +37 -0
- package/cli-tool/components/commands/sync/cross-reference-manager.md +37 -0
- package/cli-tool/components/commands/sync/issue-to-linear-task.md +37 -0
- package/cli-tool/components/commands/sync/linear-task-to-issue.md +37 -0
- package/cli-tool/components/commands/sync/sync-automation-setup.md +37 -0
- package/cli-tool/components/commands/sync/sync-conflict-resolver.md +37 -0
- package/cli-tool/components/commands/sync/sync-health-monitor.md +37 -0
- package/cli-tool/components/commands/sync/sync-issues-to-linear.md +37 -0
- package/cli-tool/components/commands/sync/sync-linear-to-issues.md +37 -0
- package/cli-tool/components/commands/sync/sync-migration-assistant.md +37 -0
- package/cli-tool/components/commands/sync/sync-pr-to-task.md +37 -0
- package/cli-tool/components/commands/sync/sync-status.md +391 -0
- package/cli-tool/components/commands/sync/task-from-pr.md +37 -0
- package/cli-tool/components/commands/team/architecture-review.md +37 -0
- package/cli-tool/components/commands/team/decision-quality-analyzer.md +37 -0
- package/cli-tool/components/commands/team/dependency-mapper.md +37 -0
- package/cli-tool/components/commands/team/estimate-assistant.md +37 -0
- package/cli-tool/components/commands/team/issue-triage.md +37 -0
- package/cli-tool/components/commands/team/memory-spring-cleaning.md +37 -0
- package/cli-tool/components/commands/team/migration-assistant.md +37 -0
- package/cli-tool/components/commands/team/retrospective-analyzer.md +37 -0
- package/cli-tool/components/commands/team/session-learning-capture.md +37 -0
- package/cli-tool/components/commands/team/sprint-planning.md +189 -0
- package/cli-tool/components/commands/team/standup-report.md +37 -0
- package/cli-tool/components/commands/team/team-knowledge-mapper.md +37 -0
- package/cli-tool/components/commands/team/team-velocity-tracker.md +37 -0
- package/cli-tool/components/commands/team/team-workload-balancer.md +37 -0
- package/cli-tool/components/commands/testing/add-mutation-testing.md +37 -0
- package/cli-tool/components/commands/testing/add-property-based-testing.md +37 -0
- package/cli-tool/components/commands/testing/e2e-setup.md +37 -0
- package/cli-tool/components/commands/testing/generate-test-cases.md +37 -0
- package/cli-tool/components/commands/testing/generate-tests.md +82 -0
- package/cli-tool/components/commands/testing/setup-comprehensive-testing.md +37 -0
- package/cli-tool/components/commands/testing/setup-load-testing.md +37 -0
- package/cli-tool/components/commands/testing/setup-visual-testing.md +37 -0
- package/cli-tool/components/commands/testing/test-automation-orchestrator.md +37 -0
- package/cli-tool/components/commands/testing/test-changelog-automation.md +37 -0
- package/cli-tool/components/commands/testing/test-coverage.md +37 -0
- package/cli-tool/components/commands/testing/test-quality-analyzer.md +37 -0
- package/cli-tool/components/commands/testing/testing_plan_integration.md +37 -0
- package/cli-tool/components/commands/testing/write-tests.md +37 -0
- package/cli-tool/components/commands/utilities/all-tools.md +31 -0
- package/cli-tool/components/commands/utilities/architecture-scenario-explorer.md +375 -0
- package/cli-tool/components/commands/utilities/check-file.md +53 -0
- package/cli-tool/components/commands/utilities/clean-branches.md +243 -0
- package/cli-tool/components/commands/utilities/clean.md +1 -0
- package/cli-tool/components/commands/utilities/code-permutation-tester.md +341 -0
- package/cli-tool/components/commands/utilities/code-review.md +70 -0
- package/cli-tool/components/commands/utilities/code-to-task.md +583 -0
- package/cli-tool/components/commands/utilities/context-prime.md +1 -0
- package/cli-tool/components/commands/utilities/debug-error.md +121 -0
- package/cli-tool/components/commands/utilities/directory-deep-dive.md +34 -0
- package/cli-tool/components/commands/utilities/explain-code.md +194 -0
- package/cli-tool/components/commands/utilities/fix-issue.md +85 -0
- package/cli-tool/components/commands/utilities/generate-linear-worklog.md +113 -0
- package/cli-tool/components/commands/utilities/git-status.md +39 -0
- package/cli-tool/components/commands/utilities/initref.md +3 -0
- package/cli-tool/components/commands/utilities/prime.md +41 -0
- package/cli-tool/components/commands/utilities/refactor-code.md +116 -0
- package/cli-tool/components/commands/utilities/ultra-think.md +153 -0
- package/cli-tool/components/hooks/HOOK_PATTERNS_COMPRESSED.json +1 -0
- package/cli-tool/components/hooks/automation/agents-md-loader.json +17 -0
- package/cli-tool/components/hooks/automation/build-on-change.json +16 -0
- package/cli-tool/components/hooks/automation/dependency-checker.json +16 -0
- package/cli-tool/components/hooks/automation/deployment-health-monitor.json +29 -0
- package/cli-tool/components/hooks/automation/discord-detailed-notifications.json +26 -0
- package/cli-tool/components/hooks/automation/discord-error-notifications.json +37 -0
- package/cli-tool/components/hooks/automation/discord-notifications.json +25 -0
- package/cli-tool/components/hooks/automation/simple-notifications.json +16 -0
- package/cli-tool/components/hooks/automation/slack-detailed-notifications.json +26 -0
- package/cli-tool/components/hooks/automation/slack-error-notifications.json +37 -0
- package/cli-tool/components/hooks/automation/slack-notifications.json +25 -0
- package/cli-tool/components/hooks/automation/telegram-detailed-notifications.json +26 -0
- package/cli-tool/components/hooks/automation/telegram-error-notifications.json +37 -0
- package/cli-tool/components/hooks/automation/telegram-notifications.json +25 -0
- package/cli-tool/components/hooks/automation/vercel-auto-deploy.json +17 -0
- package/cli-tool/components/hooks/automation/vercel-environment-sync.json +29 -0
- package/cli-tool/components/hooks/development-tools/change-tracker.json +25 -0
- package/cli-tool/components/hooks/development-tools/command-logger.json +16 -0
- package/cli-tool/components/hooks/development-tools/file-backup.json +16 -0
- package/cli-tool/components/hooks/development-tools/lint-on-save.json +16 -0
- package/cli-tool/components/hooks/development-tools/nextjs-code-quality-enforcer.json +17 -0
- package/cli-tool/components/hooks/development-tools/smart-formatting.json +16 -0
- package/cli-tool/components/hooks/git/conventional-commits.json +16 -0
- package/cli-tool/components/hooks/git/conventional-commits.py +84 -0
- package/cli-tool/components/hooks/git/prevent-direct-push.json +16 -0
- package/cli-tool/components/hooks/git/prevent-direct-push.py +86 -0
- package/cli-tool/components/hooks/git/validate-branch-name.json +16 -0
- package/cli-tool/components/hooks/git/validate-branch-name.py +96 -0
- package/cli-tool/components/hooks/git-workflow/auto-git-add.json +16 -0
- package/cli-tool/components/hooks/git-workflow/smart-commit.json +25 -0
- package/cli-tool/components/hooks/performance/performance-budget-guard.json +27 -0
- package/cli-tool/components/hooks/performance/performance-monitor.json +27 -0
- package/cli-tool/components/hooks/post-tool/format-javascript-files.json +16 -0
- package/cli-tool/components/hooks/post-tool/format-python-files.json +16 -0
- package/cli-tool/components/hooks/post-tool/git-add-changes.json +25 -0
- package/cli-tool/components/hooks/post-tool/run-tests-after-changes.json +16 -0
- package/cli-tool/components/hooks/pre-tool/backup-before-edit.json +16 -0
- package/cli-tool/components/hooks/pre-tool/notify-before-bash.json +16 -0
- package/cli-tool/components/hooks/pre-tool/update-search-year.json +17 -0
- package/cli-tool/components/hooks/security/file-protection.json +16 -0
- package/cli-tool/components/hooks/security/security-scanner.json +16 -0
- package/cli-tool/components/hooks/testing/test-runner.json +16 -0
- package/cli-tool/components/mcps/browser_automation/browser-use-mcp-server.json +20 -0
- package/cli-tool/components/mcps/browser_automation/browsermcp.json +9 -0
- package/cli-tool/components/mcps/browser_automation/mcp-server-browserbase.json +14 -0
- package/cli-tool/components/mcps/browser_automation/mcp-server-playwright.json +9 -0
- package/cli-tool/components/mcps/browser_automation/playwright-mcp-server.json +9 -0
- package/cli-tool/components/mcps/browser_automation/playwright-mcp.json +11 -0
- package/cli-tool/components/mcps/database/mysql-integration.json +12 -0
- package/cli-tool/components/mcps/database/neon.json +9 -0
- package/cli-tool/components/mcps/database/postgresql-integration.json +12 -0
- package/cli-tool/components/mcps/database/supabase.json +17 -0
- package/cli-tool/components/mcps/deepgraph/deepgraph-nextjs.json +13 -0
- package/cli-tool/components/mcps/deepgraph/deepgraph-react.json +13 -0
- package/cli-tool/components/mcps/deepgraph/deepgraph-typescript.json +13 -0
- package/cli-tool/components/mcps/deepgraph/deepgraph-vue.json +13 -0
- package/cli-tool/components/mcps/devtools/azure-kubernetes-service.json +11 -0
- package/cli-tool/components/mcps/devtools/box.json +14 -0
- package/cli-tool/components/mcps/devtools/circleci.json +13 -0
- package/cli-tool/components/mcps/devtools/codacy.json +12 -0
- package/cli-tool/components/mcps/devtools/context7.json +9 -0
- package/cli-tool/components/mcps/devtools/dynatrace.json +13 -0
- package/cli-tool/components/mcps/devtools/elasticsearch.json +18 -0
- package/cli-tool/components/mcps/devtools/figma-dev-mode.json +8 -0
- package/cli-tool/components/mcps/devtools/firecrawl.json +12 -0
- package/cli-tool/components/mcps/devtools/firefly-mcp.json +13 -0
- package/cli-tool/components/mcps/devtools/huggingface.json +11 -0
- package/cli-tool/components/mcps/devtools/imagesorcery.json +11 -0
- package/cli-tool/components/mcps/devtools/ios-simulator-mcp.json +9 -0
- package/cli-tool/components/mcps/devtools/jfrog.json +8 -0
- package/cli-tool/components/mcps/devtools/just-mcp.json +9 -0
- package/cli-tool/components/mcps/devtools/launchdarkly.json +12 -0
- package/cli-tool/components/mcps/devtools/leetcode.json +8 -0
- package/cli-tool/components/mcps/devtools/logfire.json +9 -0
- package/cli-tool/components/mcps/devtools/markitdown.json +14 -0
- package/cli-tool/components/mcps/devtools/mcp-server-atlassian-bitbucket.json +9 -0
- package/cli-tool/components/mcps/devtools/mcp-server-trello.json +12 -0
- package/cli-tool/components/mcps/devtools/microsoft-clarity.json +11 -0
- package/cli-tool/components/mcps/devtools/microsoft-dev-box.json +9 -0
- package/cli-tool/components/mcps/devtools/mongodb.json +12 -0
- package/cli-tool/components/mcps/devtools/postman.json +12 -0
- package/cli-tool/components/mcps/devtools/sentry.json +8 -0
- package/cli-tool/components/mcps/devtools/serena.json +9 -0
- package/cli-tool/components/mcps/devtools/stripe.json +12 -0
- package/cli-tool/components/mcps/devtools/terraform.json +14 -0
- package/cli-tool/components/mcps/devtools/webflow.json +8 -0
- package/cli-tool/components/mcps/filesystem/filesystem-access.json +13 -0
- package/cli-tool/components/mcps/integration/github-integration.json +12 -0
- package/cli-tool/components/mcps/integration/memory-integration.json +9 -0
- package/cli-tool/components/mcps/marketing/facebook-ads-mcp-server.json +13 -0
- package/cli-tool/components/mcps/marketing/google-ads-mcp-server.json +11 -0
- package/cli-tool/components/mcps/productivity/monday.json +14 -0
- package/cli-tool/components/mcps/productivity/notion.json +12 -0
- package/cli-tool/components/mcps/web/web-fetch.json +9 -0
- package/cli-tool/components/settings/api/bedrock-configuration.json +7 -0
- package/cli-tool/components/settings/api/corporate-proxy.json +7 -0
- package/cli-tool/components/settings/api/custom-headers.json +6 -0
- package/cli-tool/components/settings/api/vertex-configuration.json +17 -0
- package/cli-tool/components/settings/authentication/api-key-helper.json +7 -0
- package/cli-tool/components/settings/authentication/force-claudeai-login.json +4 -0
- package/cli-tool/components/settings/authentication/force-console-login.json +4 -0
- package/cli-tool/components/settings/cleanup/retention-7-days.json +4 -0
- package/cli-tool/components/settings/cleanup/retention-90-days.json +4 -0
- package/cli-tool/components/settings/environment/bash-timeouts.json +8 -0
- package/cli-tool/components/settings/environment/development-utils.json +8 -0
- package/cli-tool/components/settings/environment/performance-optimization.json +8 -0
- package/cli-tool/components/settings/environment/privacy-focused.json +10 -0
- package/cli-tool/components/settings/git/git-flow-settings.json +79 -0
- package/cli-tool/components/settings/global/aws-credentials.json +5 -0
- package/cli-tool/components/settings/global/custom-model.json +7 -0
- package/cli-tool/components/settings/global/git-commit-settings.json +4 -0
- package/cli-tool/components/settings/mcp/disable-risky-servers.json +8 -0
- package/cli-tool/components/settings/mcp/enable-all-project-servers.json +4 -0
- package/cli-tool/components/settings/mcp/enable-specific-servers.json +8 -0
- package/cli-tool/components/settings/mcp/mcp-timeouts.json +8 -0
- package/cli-tool/components/settings/model/use-haiku.json +4 -0
- package/cli-tool/components/settings/model/use-sonnet.json +4 -0
- package/cli-tool/components/settings/permissions/additional-directories.json +11 -0
- package/cli-tool/components/settings/permissions/allow-git-operations.json +14 -0
- package/cli-tool/components/settings/permissions/allow-npm-commands.json +11 -0
- package/cli-tool/components/settings/permissions/deny-sensitive-files.json +11 -0
- package/cli-tool/components/settings/permissions/development-mode.json +31 -0
- package/cli-tool/components/settings/permissions/read-only-mode.json +18 -0
- package/cli-tool/components/settings/statusline/asset-pipeline-controller-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/bug-circus-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/code-casino-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/code-spaceship-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/colorful-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/command-statusline.json +8 -0
- package/cli-tool/components/settings/statusline/context-monitor.json +7 -0
- package/cli-tool/components/settings/statusline/context-monitor.py +236 -0
- package/cli-tool/components/settings/statusline/data-ocean-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/emotion-theater-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/game-performance-monitor-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/git-branch-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/git-flow-status.json +7 -0
- package/cli-tool/components/settings/statusline/minimal-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/multiplatform-build-status-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/neon-database-dev.json +7 -0
- package/cli-tool/components/settings/statusline/neon-database-resources.json +7 -0
- package/cli-tool/components/settings/statusline/productivity-rainbow-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/programmer-tamagotchi-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/programming-fitness-tracker-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/project-info-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/rpg-status-bar-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/time-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/unity-project-dashboard-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/vercel-deployment-monitor.json +7 -0
- package/cli-tool/components/settings/statusline/vercel-error-alert-system.json +7 -0
- package/cli-tool/components/settings/statusline/vercel-multi-env-status.json +7 -0
- package/cli-tool/components/settings/statusline/virtual-code-garden-statusline.json +7 -0
- package/cli-tool/components/settings/statusline/zero-config-deployment-monitor.json +7 -0
- package/cli-tool/components/settings/telemetry/custom-telemetry.json +7 -0
- package/cli-tool/components/settings/telemetry/disable-telemetry.json +6 -0
- package/cli-tool/components/settings/telemetry/enable-telemetry.json +6 -0
- package/cli-tool/docs_to_claude/ANALYTICS_STATE_DETECTION.md +183 -0
- package/cli-tool/docs_to_claude/ARCHITECTURE.md +472 -0
- package/cli-tool/docs_to_claude/BLOG_WRITING_GUIDE.md +438 -0
- package/cli-tool/docs_to_claude/CLAUDE_DATA_STRUCTURE.md +400 -0
- package/cli-tool/docs_to_claude/COMMANDS_GUIDE.md +1035 -0
- package/cli-tool/docs_to_claude/CONVERSATION_STATE_IMPROVEMENTS.md +154 -0
- package/cli-tool/docs_to_claude/DEBUG_TYPING_DETECTION.md +95 -0
- package/cli-tool/docs_to_claude/DOWNLOAD_TRACKING.md +291 -0
- package/cli-tool/docs_to_claude/ENHANCED_STATE_DETECTION.md +122 -0
- package/cli-tool/docs_to_claude/HEALTH_CHECK_IMPLEMENTATION.md +135 -0
- package/cli-tool/docs_to_claude/HOOKS_GUIDE.md +1249 -0
- package/cli-tool/docs_to_claude/STATUSLINE_GUIDE.md +1123 -0
- package/cli-tool/docs_to_claude/SUBAGENTS_GUIDE.md +566 -0
- package/cli-tool/docs_to_claude/SUB_AGENTS.md +329 -0
- package/cli-tool/jest.config.js +84 -0
- package/cli-tool/package-lock.json +5471 -0
- package/cli-tool/package.json +96 -0
- package/{src → cli-tool/src}/index.js +41 -1
- package/cli-tool/templates/common/.claude/commands/git-workflow.md +239 -0
- package/cli-tool/templates/common/.claude/commands/project-setup.md +316 -0
- package/cli-tool/templates/common/.mcp.json +41 -0
- package/cli-tool/templates/common/CLAUDE.md +109 -0
- package/cli-tool/templates/common/README.md +96 -0
- package/cli-tool/templates/go/.mcp.json +78 -0
- package/cli-tool/templates/go/README.md +25 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/api-endpoint.md +51 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/debug.md +52 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/lint.md +48 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/npm-scripts.md +48 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/refactor.md +55 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/test.md +61 -0
- package/cli-tool/templates/javascript-typescript/.claude/commands/typescript-migrate.md +51 -0
- package/cli-tool/templates/javascript-typescript/.claude/settings.json +142 -0
- package/cli-tool/templates/javascript-typescript/.mcp.json +80 -0
- package/cli-tool/templates/javascript-typescript/CLAUDE.md +185 -0
- package/cli-tool/templates/javascript-typescript/README.md +259 -0
- package/cli-tool/templates/javascript-typescript/examples/angular-app/.claude/commands/components.md +63 -0
- package/cli-tool/templates/javascript-typescript/examples/angular-app/.claude/commands/services.md +62 -0
- package/cli-tool/templates/javascript-typescript/examples/node-api/.claude/commands/api-endpoint.md +46 -0
- package/cli-tool/templates/javascript-typescript/examples/node-api/.claude/commands/database.md +56 -0
- package/cli-tool/templates/javascript-typescript/examples/node-api/.claude/commands/middleware.md +61 -0
- package/cli-tool/templates/javascript-typescript/examples/node-api/.claude/commands/route.md +57 -0
- package/cli-tool/templates/javascript-typescript/examples/node-api/CLAUDE.md +102 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/.claude/commands/component.md +29 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/.claude/commands/hooks.md +44 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/.claude/commands/state-management.md +45 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/CLAUDE.md +81 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/agents/react-performance-optimization.md +530 -0
- package/cli-tool/templates/javascript-typescript/examples/react-app/agents/react-state-management.md +295 -0
- package/cli-tool/templates/javascript-typescript/examples/vue-app/.claude/commands/components.md +46 -0
- package/cli-tool/templates/javascript-typescript/examples/vue-app/.claude/commands/composables.md +51 -0
- package/cli-tool/templates/python/.claude/commands/lint.md +111 -0
- package/cli-tool/templates/python/.claude/commands/test.md +73 -0
- package/cli-tool/templates/python/.claude/settings.json +153 -0
- package/cli-tool/templates/python/.mcp.json +78 -0
- package/cli-tool/templates/python/CLAUDE.md +276 -0
- package/cli-tool/templates/python/examples/django-app/.claude/commands/admin.md +264 -0
- package/cli-tool/templates/python/examples/django-app/.claude/commands/django-model.md +124 -0
- package/cli-tool/templates/python/examples/django-app/.claude/commands/views.md +222 -0
- package/cli-tool/templates/python/examples/django-app/CLAUDE.md +313 -0
- package/cli-tool/templates/python/examples/fastapi-app/.claude/commands/api-endpoints.md +513 -0
- package/cli-tool/templates/python/examples/fastapi-app/.claude/commands/auth.md +775 -0
- package/cli-tool/templates/python/examples/fastapi-app/.claude/commands/database.md +657 -0
- package/cli-tool/templates/python/examples/fastapi-app/.claude/commands/deployment.md +160 -0
- package/cli-tool/templates/python/examples/fastapi-app/.claude/commands/testing.md +927 -0
- package/cli-tool/templates/python/examples/fastapi-app/CLAUDE.md +229 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/app-factory.md +384 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/blueprint.md +243 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/database.md +410 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/deployment.md +620 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/flask-route.md +217 -0
- package/cli-tool/templates/python/examples/flask-app/.claude/commands/testing.md +559 -0
- package/cli-tool/templates/python/examples/flask-app/CLAUDE.md +391 -0
- package/cli-tool/templates/ruby/.claude/commands/model.md +360 -0
- package/cli-tool/templates/ruby/.claude/commands/test.md +480 -0
- package/cli-tool/templates/ruby/.claude/settings.json +146 -0
- package/cli-tool/templates/ruby/.mcp.json +83 -0
- package/cli-tool/templates/ruby/CLAUDE.md +284 -0
- package/cli-tool/templates/ruby/examples/rails-app/.claude/commands/authentication.md +490 -0
- package/cli-tool/templates/ruby/examples/rails-app/CLAUDE.md +376 -0
- package/cli-tool/templates/rust/.mcp.json +78 -0
- package/cli-tool/templates/rust/README.md +26 -0
- package/cli-tool/test-commands.sh +85 -0
- package/cli-tool/test-detailed.sh +267 -0
- package/dev-server.js +46 -0
- package/docs/CNAME +1 -0
- package/docs/README.md +49 -0
- package/docs/_config.yml +43 -0
- package/docs/api/agents.json +942 -0
- package/docs/blog/assets/aitmpl-nextjs-search.png +0 -0
- package/docs/blog/assets/aitmpl-supabase-search.png +0 -0
- package/docs/blog/assets/e2b-claude-code-sandbox-cover.png +0 -0
- package/docs/blog/assets/nextjs-vercel-claude-code-templates-cover.png +0 -0
- package/docs/blog/assets/supabase-claude-code-templates-cover.png +0 -0
- package/docs/blog/e2b-claude-code-sandbox/index.html +908 -0
- package/docs/blog/index.html +274 -0
- package/docs/blog/nextjs-vercel-claude-code-integration/index.html +1032 -0
- package/docs/blog/supabase-claude-code-integration/index.html +848 -0
- package/docs/claude-jobs.json +163 -0
- package/docs/component.html +506 -0
- package/docs/components-metadata.json +303 -0
- package/docs/components.json +4952 -0
- package/docs/css/blog.css +821 -0
- package/docs/css/component-page.css +1063 -0
- package/docs/css/stack-page.css +776 -0
- package/docs/css/styles.css +4540 -0
- package/docs/css/trending.css +1441 -0
- package/docs/css/workflows-modal.css +739 -0
- package/docs/css/workflows.css +1234 -0
- package/docs/download-stats.html +527 -0
- package/docs/index.html +627 -0
- package/docs/jobs.html +1059 -0
- package/docs/js/carousel.js +177 -0
- package/docs/js/cart-manager.js +658 -0
- package/docs/js/component-page.js +808 -0
- package/docs/js/data-loader.js +633 -0
- package/docs/js/generate-search-data.js +82 -0
- package/docs/js/index-events.js +1812 -0
- package/docs/js/modal-helpers.js +345 -0
- package/docs/js/script.js +2167 -0
- package/docs/js/search-functionality.js +1165 -0
- package/docs/js/stack-router.js +561 -0
- package/docs/js/trending.js +752 -0
- package/docs/js/utils.js +43 -0
- package/docs/js/workflows-events.js +1146 -0
- package/docs/js/workflows.js +627 -0
- package/docs/robots.txt +28 -0
- package/docs/sandbox-interface.html +1418 -0
- package/docs/sitemap.xml +193 -0
- package/docs/static/img/logo.png +0 -0
- package/docs/static/img/logo.svg +23 -0
- package/docs/trending-data.json +885 -0
- package/docs/trending.html +238 -0
- package/docs/vercel.json +36 -0
- package/docs/workflows.html +391 -0
- package/docu/README.md +41 -0
- package/docu/docs/cli-options.md +90 -0
- package/docu/docs/components/agents.md +113 -0
- package/docu/docs/components/commands.md +90 -0
- package/docu/docs/components/hooks.md +114 -0
- package/docu/docs/components/mcps.md +109 -0
- package/docu/docs/components/overview.md +73 -0
- package/docu/docs/components/settings.md +105 -0
- package/docu/docs/components/templates.md +119 -0
- package/docu/docs/intro.md +40 -0
- package/docu/docs/safety-features.md +13 -0
- package/docu/docs/support.md +13 -0
- package/docu/docs/tools/analytics.md +23 -0
- package/docu/docs/tools/chats.md +33 -0
- package/docu/docs/tools/health-check.md +60 -0
- package/docu/docs/tools/overview.md +39 -0
- package/docu/docs/tools/sandbox.md +61 -0
- package/docu/docs/tools/tunnel.md +38 -0
- package/docu/docusaurus.config.ts +169 -0
- package/docu/package-lock.json +16185 -0
- package/docu/package.json +47 -0
- package/docu/sidebars.ts +49 -0
- package/docu/src/components/HomepageFeatures/index.tsx +82 -0
- package/docu/src/components/HomepageFeatures/styles.module.css +131 -0
- package/docu/src/css/custom.css +849 -0
- package/docu/src/pages/index.module.css +111 -0
- package/docu/src/pages/index.tsx +65 -0
- package/docu/src/pages/markdown-page.md +7 -0
- package/docu/static/img/favicon.ico +0 -0
- package/docu/static/img/logo.svg +23 -0
- package/docu/tsconfig.json +8 -0
- package/docu/vercel.json +11 -0
- package/generate_agents_api.py +65 -0
- package/generate_claude_jobs.py +985 -0
- package/generate_components_json.py +391 -0
- package/package.json +21 -74
- package/social-preview.png +0 -0
- package/test_serpapi.py +36 -0
- package/vercel.json +111 -0
- /package/{bin → cli-tool/bin}/create-claude-config.js +0 -0
- /package/{components → cli-tool/components}/sandbox/README.md +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/.env.example +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/SANDBOX_DEBUGGING.md +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/claude-code-sandbox.md +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/e2b-launcher.py +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/e2b-monitor.py +0 -0
- /package/{components → cli-tool/components}/sandbox/e2b/requirements.txt +0 -0
- /package/{src → cli-tool/src}/agents.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/AgentAnalyzer.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/ConversationAnalyzer.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/FileWatcher.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/ProcessDetector.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/SessionAnalyzer.js +0 -0
- /package/{src → cli-tool/src}/analytics/core/StateCalculator.js +0 -0
- /package/{src → cli-tool/src}/analytics/data/DataCache.js +0 -0
- /package/{src → cli-tool/src}/analytics/notifications/NotificationManager.js +0 -0
- /package/{src → cli-tool/src}/analytics/notifications/WebSocketServer.js +0 -0
- /package/{src → cli-tool/src}/analytics/utils/PerformanceMonitor.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/FRONT_ARCHITECTURE.md +0 -0
- /package/{src → cli-tool/src}/analytics-web/assets/js/main.js.deprecated +0 -0
- /package/{src → cli-tool/src}/analytics-web/chats_mobile.html +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/ActivityHeatmap.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/AgentAnalytics.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/App.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/Charts.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/ConversationTable.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/DashboardPage.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/HeaderComponent.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/SessionTimer.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/Sidebar.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/components/ToolDisplay.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/index.html +0 -0
- /package/{src → cli-tool/src}/analytics-web/index.html.original +0 -0
- /package/{src → cli-tool/src}/analytics-web/services/DataService.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/services/StateService.js +0 -0
- /package/{src → cli-tool/src}/analytics-web/services/WebSocketService.js +0 -0
- /package/{src → cli-tool/src}/analytics.js +0 -0
- /package/{src → cli-tool/src}/chats-mobile.js +0 -0
- /package/{src → cli-tool/src}/claude-api-proxy.js +0 -0
- /package/{src → cli-tool/src}/command-scanner.js +0 -0
- /package/{src → cli-tool/src}/command-stats.js +0 -0
- /package/{src → cli-tool/src}/console-bridge.js +0 -0
- /package/{src → cli-tool/src}/file-operations.js +0 -0
- /package/{src → cli-tool/src}/health-check.js +0 -0
- /package/{src → cli-tool/src}/hook-scanner.js +0 -0
- /package/{src → cli-tool/src}/hook-stats.js +0 -0
- /package/{src → cli-tool/src}/mcp-stats.js +0 -0
- /package/{src → cli-tool/src}/prompts.js +0 -0
- /package/{src → cli-tool/src}/sandbox-interface.html +0 -0
- /package/{src → cli-tool/src}/sandbox-server.js +0 -0
- /package/{src → cli-tool/src}/sdk/global-agent-manager.js +0 -0
- /package/{src → cli-tool/src}/templates.js +0 -0
- /package/{src → cli-tool/src}/test-console-bridge.js +0 -0
- /package/{src → cli-tool/src}/tracking-service.js +0 -0
- /package/{src → cli-tool/src}/utils.js +0 -0
- /package/{src/analytics.log → docu/static/.nojekyll} +0 -0
|
@@ -0,0 +1,2167 @@
|
|
|
1
|
+
// GitHub repository configuration
|
|
2
|
+
const GITHUB_CONFIG = {
|
|
3
|
+
owner: 'davila7',
|
|
4
|
+
repo: 'claude-code-templates',
|
|
5
|
+
branch: 'main',
|
|
6
|
+
templatesPath: 'cli-tool/src/templates.js'
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
// Framework logos using Devicon CDN (https://devicon.dev/)
|
|
10
|
+
const FRAMEWORK_ICONS = {
|
|
11
|
+
// Languages
|
|
12
|
+
'common': 'devicon-gear-plain', // Generic gear icon
|
|
13
|
+
'javascript-typescript': 'devicon-javascript-plain',
|
|
14
|
+
'python': 'devicon-python-plain',
|
|
15
|
+
'ruby': 'devicon-ruby-plain',
|
|
16
|
+
'rust': 'devicon-rust-plain',
|
|
17
|
+
'go': 'devicon-go-plain',
|
|
18
|
+
|
|
19
|
+
// JavaScript/TypeScript frameworks
|
|
20
|
+
'react': 'devicon-react-original',
|
|
21
|
+
'vue': 'devicon-vuejs-plain',
|
|
22
|
+
'angular': 'devicon-angularjs-plain',
|
|
23
|
+
'node': 'devicon-nodejs-plain',
|
|
24
|
+
|
|
25
|
+
// Python frameworks
|
|
26
|
+
'django': 'devicon-django-plain',
|
|
27
|
+
'flask': 'devicon-flask-original',
|
|
28
|
+
'fastapi': 'devicon-fastapi-plain',
|
|
29
|
+
|
|
30
|
+
// Ruby frameworks
|
|
31
|
+
'rails': 'devicon-rails-plain',
|
|
32
|
+
'sinatra': 'devicon-ruby-plain', // Use Ruby icon for Sinatra
|
|
33
|
+
|
|
34
|
+
// Default fallback
|
|
35
|
+
'default': 'devicon-devicon-plain'
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
let templatesData = null;
|
|
39
|
+
|
|
40
|
+
// Fetch templates configuration from GitHub
|
|
41
|
+
async function fetchTemplatesConfig() {
|
|
42
|
+
const grid = document.getElementById('unifiedGrid') || document.getElementById('templatesGrid');
|
|
43
|
+
grid.innerHTML = '<div class="loading">Loading templates from GitHub...</div>';
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
// Add cache-busting parameter to ensure we get the latest version
|
|
47
|
+
const url = `https://raw.githubusercontent.com/${GITHUB_CONFIG.owner}/${GITHUB_CONFIG.repo}/${GITHUB_CONFIG.branch}/${GITHUB_CONFIG.templatesPath}?t=${Date.now()}`;
|
|
48
|
+
const response = await fetch(url);
|
|
49
|
+
|
|
50
|
+
if (!response.ok) {
|
|
51
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const templateFileContent = await response.text();
|
|
55
|
+
|
|
56
|
+
// Parse the JavaScript file to extract TEMPLATES_CONFIG
|
|
57
|
+
templatesData = parseTemplatesConfig(templateFileContent);
|
|
58
|
+
|
|
59
|
+
if (templatesData) {
|
|
60
|
+
generateTemplateCards();
|
|
61
|
+
} else {
|
|
62
|
+
throw new Error('Failed to parse templates configuration');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error('Error fetching templates:', error);
|
|
67
|
+
grid.innerHTML = `
|
|
68
|
+
<div class="error-message">
|
|
69
|
+
<h3>Error loading templates</h3>
|
|
70
|
+
<p>Could not fetch templates from GitHub. Please try again later.</p>
|
|
71
|
+
<button onclick="displayTemplates()" class="retry-btn">Retry</button>
|
|
72
|
+
</div>
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Parse the templates.js file content to extract TEMPLATES_CONFIG
|
|
78
|
+
function parseTemplatesConfig(fileContent) {
|
|
79
|
+
try {
|
|
80
|
+
// Extract TEMPLATES_CONFIG object from the file
|
|
81
|
+
const configMatch = fileContent.match(/const TEMPLATES_CONFIG = ({[\s\S]*?});/);
|
|
82
|
+
if (!configMatch) {
|
|
83
|
+
throw new Error('TEMPLATES_CONFIG not found in file');
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Clean up the extracted object string and make it valid JSON
|
|
87
|
+
let configString = configMatch[1];
|
|
88
|
+
|
|
89
|
+
// Replace single quotes with double quotes
|
|
90
|
+
configString = configString.replace(/'/g, '"');
|
|
91
|
+
|
|
92
|
+
// Handle object property names without quotes
|
|
93
|
+
configString = configString.replace(/(\w+):/g, '"$1":');
|
|
94
|
+
|
|
95
|
+
// Remove trailing commas
|
|
96
|
+
configString = configString.replace(/,(\s*[}\]])/g, '$1');
|
|
97
|
+
|
|
98
|
+
// Parse the JSON
|
|
99
|
+
const config = JSON.parse(configString);
|
|
100
|
+
|
|
101
|
+
return config;
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error('Error parsing templates config:', error);
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Generate template cards from fetched data
|
|
109
|
+
function generateTemplateCards() {
|
|
110
|
+
const grid = document.getElementById('unifiedGrid');
|
|
111
|
+
grid.innerHTML = '';
|
|
112
|
+
|
|
113
|
+
if (!templatesData) {
|
|
114
|
+
grid.innerHTML = '<div class="error-message">No templates data available</div>';
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Add the "Add New Template" card first
|
|
119
|
+
const addTemplateCard = createAddTemplateCard();
|
|
120
|
+
grid.appendChild(addTemplateCard);
|
|
121
|
+
|
|
122
|
+
Object.entries(templatesData).forEach(([languageKey, languageData]) => {
|
|
123
|
+
// Skip the 'common' template as we're replacing it with the Add Template card
|
|
124
|
+
if (languageKey === 'common') {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Create base language card (no framework)
|
|
129
|
+
const baseCard = createTemplateCard(languageKey, languageData, 'none', {
|
|
130
|
+
name: languageData.name,
|
|
131
|
+
icon: getFrameworkIcon(languageKey),
|
|
132
|
+
command: `npx claude-code-templates@latest --template=${languageKey} --yes`
|
|
133
|
+
});
|
|
134
|
+
grid.appendChild(baseCard);
|
|
135
|
+
|
|
136
|
+
// Create framework-specific cards
|
|
137
|
+
if (languageData.frameworks) {
|
|
138
|
+
Object.entries(languageData.frameworks).forEach(([frameworkKey, frameworkData]) => {
|
|
139
|
+
const frameworkCard = createTemplateCard(languageKey, languageData, frameworkKey, {
|
|
140
|
+
name: frameworkData.name,
|
|
141
|
+
icon: getFrameworkIcon(frameworkKey),
|
|
142
|
+
command: `npx claude-code-templates@latest --template=${languageKey} --yes`
|
|
143
|
+
});
|
|
144
|
+
grid.appendChild(frameworkCard);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function createAddTemplateCard() {
|
|
151
|
+
const card = document.createElement('div');
|
|
152
|
+
card.className = 'template-card add-template-card';
|
|
153
|
+
|
|
154
|
+
card.innerHTML = `
|
|
155
|
+
<div class="card-inner">
|
|
156
|
+
<div class="card-front">
|
|
157
|
+
<div class="framework-logo">
|
|
158
|
+
<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor">
|
|
159
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
|
|
160
|
+
</svg>
|
|
161
|
+
</div>
|
|
162
|
+
<h3 class="template-title">Add New Template</h3>
|
|
163
|
+
<p class="template-description">Contribute a new language or framework to the community</p>
|
|
164
|
+
</div>
|
|
165
|
+
</div>
|
|
166
|
+
`;
|
|
167
|
+
|
|
168
|
+
// Add click handler to open contribution modal directly (no flip)
|
|
169
|
+
card.addEventListener('click', () => {
|
|
170
|
+
showContributeModal();
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
return card;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function createTemplateCard(languageKey, languageData, frameworkKey, frameworkData) {
|
|
177
|
+
const card = document.createElement('div');
|
|
178
|
+
card.className = `template-card ${languageData.comingSoon ? 'coming-soon' : ''}`;
|
|
179
|
+
|
|
180
|
+
const displayName = frameworkKey === 'none' ?
|
|
181
|
+
frameworkData.name :
|
|
182
|
+
`${languageData.name.split('/')[0]}/${frameworkData.name}`;
|
|
183
|
+
|
|
184
|
+
// Get download count for this template
|
|
185
|
+
const templateKey = frameworkKey === 'none' ? languageKey : `${languageKey}/${frameworkKey}`;
|
|
186
|
+
const downloadCount = getDownloadCount(templateKey, 'template');
|
|
187
|
+
const downloadBadge = createDownloadBadge(downloadCount);
|
|
188
|
+
|
|
189
|
+
card.innerHTML = `
|
|
190
|
+
<div class="card-inner">
|
|
191
|
+
<div class="card-front">
|
|
192
|
+
${languageData.comingSoon ? '<div class="coming-soon-badge">Coming Soon</div>' : ''}
|
|
193
|
+
${downloadBadge}
|
|
194
|
+
<div class="framework-logo">
|
|
195
|
+
<i class="${frameworkData.icon} colored"></i>
|
|
196
|
+
</div>
|
|
197
|
+
<h3 class="template-title">${displayName}</h3>
|
|
198
|
+
<p class="template-description">${languageData.description || ''}</p>
|
|
199
|
+
</div>
|
|
200
|
+
<div class="card-back">
|
|
201
|
+
<div class="command-display">
|
|
202
|
+
<h3>Installation Options</h3>
|
|
203
|
+
<div class="command-code">${frameworkData.command}</div>
|
|
204
|
+
<div class="action-buttons">
|
|
205
|
+
<button class="view-files-btn" onclick="showInstallationFiles('${languageKey}', '${frameworkKey}', '${displayName}')">
|
|
206
|
+
📁 View Files
|
|
207
|
+
</button>
|
|
208
|
+
<button class="copy-command-btn" onclick="copyToClipboard('${frameworkData.command}')">
|
|
209
|
+
📋 Copy Command
|
|
210
|
+
</button>
|
|
211
|
+
</div>
|
|
212
|
+
</div>
|
|
213
|
+
</div>
|
|
214
|
+
</div>
|
|
215
|
+
`;
|
|
216
|
+
|
|
217
|
+
// Add click handler for card flip (only if not coming soon)
|
|
218
|
+
if (!languageData.comingSoon) {
|
|
219
|
+
card.addEventListener('click', (e) => {
|
|
220
|
+
// Don't flip if clicking on buttons
|
|
221
|
+
if (!e.target.closest('button')) {
|
|
222
|
+
card.classList.toggle('flipped');
|
|
223
|
+
}
|
|
224
|
+
});
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
return card;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Get framework icon from mapping
|
|
231
|
+
function getFrameworkIcon(framework) {
|
|
232
|
+
return FRAMEWORK_ICONS[framework] || FRAMEWORK_ICONS['default'];
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Get installation files for a specific template
|
|
236
|
+
function getInstallationFiles(languageKey, frameworkKey) {
|
|
237
|
+
if (!templatesData || !templatesData[languageKey]) {
|
|
238
|
+
return [];
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const languageData = templatesData[languageKey];
|
|
242
|
+
let files = [...(languageData.files || [])];
|
|
243
|
+
|
|
244
|
+
// Add framework-specific files if applicable
|
|
245
|
+
if (frameworkKey !== 'none' && languageData.frameworks && languageData.frameworks[frameworkKey]) {
|
|
246
|
+
const frameworkData = languageData.frameworks[frameworkKey];
|
|
247
|
+
if (frameworkData.additionalFiles) {
|
|
248
|
+
files = files.concat(frameworkData.additionalFiles);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return files;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Show installation files popup
|
|
256
|
+
function showInstallationFiles(languageKey, frameworkKey, displayName) {
|
|
257
|
+
const files = getInstallationFiles(languageKey, frameworkKey);
|
|
258
|
+
|
|
259
|
+
if (files.length === 0) {
|
|
260
|
+
showCopyFeedback('No files to display');
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Generate GitHub folder URL
|
|
265
|
+
const githubFolderUrl = getGithubFolderUrl(languageKey, frameworkKey);
|
|
266
|
+
|
|
267
|
+
// Create modal HTML
|
|
268
|
+
const modalHTML = `
|
|
269
|
+
<div class="modal-overlay" onclick="closeModal()">
|
|
270
|
+
<div class="modal-content" onclick="event.stopPropagation()">
|
|
271
|
+
<div class="modal-header">
|
|
272
|
+
<h3>📁 Installation Files - ${displayName}</h3>
|
|
273
|
+
<button class="modal-close" onclick="closeModal()">×</button>
|
|
274
|
+
</div>
|
|
275
|
+
<div class="modal-body">
|
|
276
|
+
<p class="modal-description">The following files will be installed in your project:</p>
|
|
277
|
+
<div class="files-table">
|
|
278
|
+
<div class="table-header">
|
|
279
|
+
<div class="column-header">File</div>
|
|
280
|
+
<div class="column-header">Destination</div>
|
|
281
|
+
<div class="column-header">Type</div>
|
|
282
|
+
</div>
|
|
283
|
+
${files.map(file => `
|
|
284
|
+
<div class="table-row">
|
|
285
|
+
<div class="file-source">
|
|
286
|
+
<a href="${getGithubFileUrl(languageKey, frameworkKey, file.source)}" target="_blank" class="file-link">
|
|
287
|
+
${file.source}
|
|
288
|
+
</a>
|
|
289
|
+
</div>
|
|
290
|
+
<div class="file-destination">${file.destination}</div>
|
|
291
|
+
<div class="file-type">${getFileType(file.destination)}</div>
|
|
292
|
+
</div>
|
|
293
|
+
`).join('')}
|
|
294
|
+
</div>
|
|
295
|
+
<div class="modal-footer">
|
|
296
|
+
<p class="file-count">Total: ${files.length} file${files.length > 1 ? 's' : ''}</p>
|
|
297
|
+
<div class="modal-actions">
|
|
298
|
+
<a href="${githubFolderUrl}" target="_blank" class="github-folder-link">
|
|
299
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
300
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.30.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
301
|
+
</svg>
|
|
302
|
+
View all files on GitHub
|
|
303
|
+
</a>
|
|
304
|
+
</div>
|
|
305
|
+
</div>
|
|
306
|
+
</div>
|
|
307
|
+
</div>
|
|
308
|
+
</div>
|
|
309
|
+
`;
|
|
310
|
+
|
|
311
|
+
// Remove existing modal if present
|
|
312
|
+
const existingModal = document.querySelector('.modal-overlay');
|
|
313
|
+
if (existingModal) {
|
|
314
|
+
existingModal.remove();
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Add modal to body
|
|
318
|
+
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
|
319
|
+
|
|
320
|
+
// Add event listener for ESC key
|
|
321
|
+
const handleEscape = (e) => {
|
|
322
|
+
if (e.key === 'Escape') {
|
|
323
|
+
closeComponentModal();
|
|
324
|
+
document.removeEventListener('keydown', handleEscape);
|
|
325
|
+
}
|
|
326
|
+
};
|
|
327
|
+
document.addEventListener('keydown', handleEscape);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// ===== ANALYTICS AND STATISTICS FUNCTIONALITY =====
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Load and display download statistics from GitHub-generated analytics
|
|
334
|
+
*/
|
|
335
|
+
async function loadDownloadStatistics() {
|
|
336
|
+
try {
|
|
337
|
+
// Fetch analytics data generated by GitHub Actions
|
|
338
|
+
const response = await fetch('analytics/download-stats.json?t=' + Date.now());
|
|
339
|
+
|
|
340
|
+
if (!response.ok) {
|
|
341
|
+
console.log('Analytics data not available yet');
|
|
342
|
+
hideStatisticsSection();
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const analyticsData = await response.json();
|
|
347
|
+
displayDownloadStatistics(analyticsData);
|
|
348
|
+
|
|
349
|
+
} catch (error) {
|
|
350
|
+
console.log('Analytics data not available:', error.message);
|
|
351
|
+
hideStatisticsSection();
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Display download statistics in the UI
|
|
357
|
+
*/
|
|
358
|
+
function displayDownloadStatistics(data) {
|
|
359
|
+
// Update total downloads
|
|
360
|
+
const totalElement = document.getElementById('totalDownloads');
|
|
361
|
+
if (totalElement) {
|
|
362
|
+
totalElement.textContent = formatNumber(data.total_downloads || 0);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// Update individual component type counts
|
|
366
|
+
const typeElements = {
|
|
367
|
+
agentDownloads: data.downloads_by_type?.agent || 0,
|
|
368
|
+
commandDownloads: data.downloads_by_type?.command || 0,
|
|
369
|
+
mcpDownloads: data.downloads_by_type?.mcp || 0,
|
|
370
|
+
templateDownloads: data.downloads_by_type?.template || 0
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
Object.entries(typeElements).forEach(([elementId, count]) => {
|
|
374
|
+
const element = document.getElementById(elementId);
|
|
375
|
+
if (element) {
|
|
376
|
+
element.textContent = formatNumber(count);
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
|
|
380
|
+
// Find and display most popular component
|
|
381
|
+
const popularElement = document.getElementById('popularComponent');
|
|
382
|
+
if (popularElement && data.downloads_by_component) {
|
|
383
|
+
const topComponent = Object.entries(data.downloads_by_component)[0];
|
|
384
|
+
if (topComponent) {
|
|
385
|
+
const [componentName, downloadCount] = topComponent;
|
|
386
|
+
popularElement.textContent = formatComponentNameForDisplay(componentName);
|
|
387
|
+
popularElement.setAttribute('title', `${formatNumber(downloadCount)} downloads`);
|
|
388
|
+
} else {
|
|
389
|
+
popularElement.textContent = '-';
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// Update last updated timestamp
|
|
394
|
+
const lastUpdatedElement = document.getElementById('statsLastUpdated');
|
|
395
|
+
if (lastUpdatedElement && data.last_updated) {
|
|
396
|
+
const lastUpdated = new Date(data.last_updated);
|
|
397
|
+
lastUpdatedElement.textContent = formatRelativeTime(lastUpdated);
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
// Show the statistics section
|
|
401
|
+
showStatisticsSection();
|
|
402
|
+
|
|
403
|
+
console.log('📊 Download statistics loaded successfully');
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Hide statistics section when data is not available
|
|
408
|
+
*/
|
|
409
|
+
function hideStatisticsSection() {
|
|
410
|
+
// Keep statistics section visible even when data is not available
|
|
411
|
+
// const statsSection = document.getElementById('downloadStatsSection');
|
|
412
|
+
// if (statsSection) {
|
|
413
|
+
// statsSection.style.display = 'none';
|
|
414
|
+
// }
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Show statistics section when data is available
|
|
419
|
+
* Note: Stats section has been moved to dedicated page at /download-stats.html
|
|
420
|
+
*/
|
|
421
|
+
function showStatisticsSection() {
|
|
422
|
+
// Stats section removed from main page - no action needed
|
|
423
|
+
console.log('Stats available at /download-stats.html');
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/**
|
|
427
|
+
* Format numbers with thousands separators
|
|
428
|
+
*/
|
|
429
|
+
function formatNumber(num) {
|
|
430
|
+
if (num === 0) return '0';
|
|
431
|
+
if (num < 1000) return num.toString();
|
|
432
|
+
if (num < 1000000) return (num / 1000).toFixed(1) + 'K';
|
|
433
|
+
return (num / 1000000).toFixed(1) + 'M';
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Format component name for display (remove prefixes, capitalize)
|
|
438
|
+
*/
|
|
439
|
+
function formatComponentNameForDisplay(componentName) {
|
|
440
|
+
if (!componentName || componentName === 'unknown') return '-';
|
|
441
|
+
|
|
442
|
+
// Handle template format (language/framework)
|
|
443
|
+
if (componentName.includes('/')) {
|
|
444
|
+
const parts = componentName.split('/');
|
|
445
|
+
return parts.map(part =>
|
|
446
|
+
part.replace(/-/g, ' ')
|
|
447
|
+
.replace(/\b\w/g, l => l.toUpperCase())
|
|
448
|
+
).join('/');
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
// Handle individual components
|
|
452
|
+
return componentName
|
|
453
|
+
.replace(/-/g, ' ')
|
|
454
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
/**
|
|
458
|
+
* Format relative time (e.g., "2 hours ago")
|
|
459
|
+
*/
|
|
460
|
+
function formatRelativeTime(date) {
|
|
461
|
+
const now = new Date();
|
|
462
|
+
const diffMs = now - date;
|
|
463
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
464
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
465
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
466
|
+
|
|
467
|
+
if (diffMins < 60) {
|
|
468
|
+
return diffMins <= 1 ? 'just now' : `${diffMins} minutes ago`;
|
|
469
|
+
} else if (diffHours < 24) {
|
|
470
|
+
return diffHours === 1 ? '1 hour ago' : `${diffHours} hours ago`;
|
|
471
|
+
} else if (diffDays < 7) {
|
|
472
|
+
return diffDays === 1 ? '1 day ago' : `${diffDays} days ago`;
|
|
473
|
+
} else {
|
|
474
|
+
return date.toLocaleDateString('en-US', {
|
|
475
|
+
month: 'short',
|
|
476
|
+
day: 'numeric',
|
|
477
|
+
year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Refresh statistics data
|
|
484
|
+
*/
|
|
485
|
+
async function refreshStatistics() {
|
|
486
|
+
const refreshButton = document.querySelector('.stats-refresh-btn');
|
|
487
|
+
if (refreshButton) {
|
|
488
|
+
refreshButton.textContent = 'Refreshing...';
|
|
489
|
+
refreshButton.disabled = true;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
await loadDownloadStatistics();
|
|
493
|
+
|
|
494
|
+
if (refreshButton) {
|
|
495
|
+
refreshButton.textContent = 'Refresh';
|
|
496
|
+
refreshButton.disabled = false;
|
|
497
|
+
}
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
// Auto-refresh statistics every 10 minutes
|
|
501
|
+
setInterval(loadDownloadStatistics, 10 * 60 * 1000);
|
|
502
|
+
|
|
503
|
+
// Close modal
|
|
504
|
+
function closeModal() {
|
|
505
|
+
const modal = document.querySelector('.modal');
|
|
506
|
+
if (modal) {
|
|
507
|
+
modal.remove();
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Show contribute modal
|
|
512
|
+
function showContributeModal() {
|
|
513
|
+
const modalHTML = `
|
|
514
|
+
<div class="modal-overlay" onclick="closeModal()">
|
|
515
|
+
<div class="modal-content contribute-modal" onclick="event.stopPropagation()">
|
|
516
|
+
<div class="modal-header">
|
|
517
|
+
<h3>🚀 Contribute a New Template</h3>
|
|
518
|
+
<button class="modal-close" onclick="closeModal()">×</button>
|
|
519
|
+
</div>
|
|
520
|
+
<div class="modal-body">
|
|
521
|
+
<div class="contribute-intro">
|
|
522
|
+
<p>Help expand Claude Code Templates by contributing new languages or frameworks! Follow these steps to submit your contribution:</p>
|
|
523
|
+
</div>
|
|
524
|
+
|
|
525
|
+
<div class="contribute-steps">
|
|
526
|
+
<div class="contribute-step">
|
|
527
|
+
<div class="step-number-contrib">1</div>
|
|
528
|
+
<div class="step-content-contrib">
|
|
529
|
+
<h4>Fork the Repository</h4>
|
|
530
|
+
<p>Go to the <a href="https://github.com/davila7/claude-code-templates" target="_blank">main repository</a> and click "Fork" to create your own copy.</p>
|
|
531
|
+
<div class="step-command">
|
|
532
|
+
<code>git clone https://github.com/YOUR_USERNAME/claude-code-templates.git</code>
|
|
533
|
+
<button class="copy-btn" onclick="copyToClipboard('git clone https://github.com/YOUR_USERNAME/claude-code-templates.git')">Copy</button>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
</div>
|
|
537
|
+
|
|
538
|
+
<div class="contribute-step">
|
|
539
|
+
<div class="step-number-contrib">2</div>
|
|
540
|
+
<div class="step-content-contrib">
|
|
541
|
+
<h4>Choose Your Contribution Type</h4>
|
|
542
|
+
<div class="contribution-types">
|
|
543
|
+
<div class="contrib-type">
|
|
544
|
+
<strong>New Language:</strong> Add to <code>cli-tool/templates/</code>
|
|
545
|
+
<br><small>Example: <code>cli-tool/templates/kotlin/</code></small>
|
|
546
|
+
</div>
|
|
547
|
+
<div class="contrib-type">
|
|
548
|
+
<strong>New Framework:</strong> Add to <code>cli-tool/templates/{language}/examples/</code>
|
|
549
|
+
<br><small>Example: <code>cli-tool/templates/python/examples/fastapi-app/</code></small>
|
|
550
|
+
</div>
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
</div>
|
|
554
|
+
|
|
555
|
+
<div class="contribute-step">
|
|
556
|
+
<div class="step-number-contrib">3</div>
|
|
557
|
+
<div class="step-content-contrib">
|
|
558
|
+
<h4>Use Claude Code to Generate the Template</h4>
|
|
559
|
+
<p>Copy this prompt and use it with Claude Code to automatically generate the template structure:</p>
|
|
560
|
+
<div class="claude-prompt">
|
|
561
|
+
<h5>📋 Claude Code Prompt:</h5>
|
|
562
|
+
<div class="prompt-text">
|
|
563
|
+
<pre>I want to contribute a new template to the claude-code-templates repository.
|
|
564
|
+
|
|
565
|
+
Please help me create:
|
|
566
|
+
- A new [LANGUAGE/FRAMEWORK] template
|
|
567
|
+
- All necessary configuration files (CLAUDE.md, .claude/, .mcp.json)
|
|
568
|
+
- Update cli-tool/src/templates.js with the new configuration
|
|
569
|
+
- Include appropriate hooks and commands for this technology
|
|
570
|
+
|
|
571
|
+
The template should follow the existing patterns in the repository and include:
|
|
572
|
+
1. CLAUDE.md with language/framework-specific guidelines
|
|
573
|
+
2. .claude/commands/ with relevant development commands
|
|
574
|
+
3. .mcp.json with appropriate MCP configurations
|
|
575
|
+
4. Update templates.js with the new template definition
|
|
576
|
+
|
|
577
|
+
Target: [SPECIFY: New language (e.g., "Kotlin") OR new framework (e.g., "FastAPI for Python")]
|
|
578
|
+
|
|
579
|
+
Please analyze the existing templates in the repository first to understand the structure and patterns, then create the new template following the same conventions.</pre>
|
|
580
|
+
</div>
|
|
581
|
+
<button class="copy-btn copy-prompt-btn" onclick="copyToClipboard(document.querySelector('.prompt-text pre').textContent)">Copy Prompt</button>
|
|
582
|
+
</div>
|
|
583
|
+
</div>
|
|
584
|
+
</div>
|
|
585
|
+
|
|
586
|
+
<div class="contribute-step">
|
|
587
|
+
<div class="step-number-contrib">4</div>
|
|
588
|
+
<div class="step-content-contrib">
|
|
589
|
+
<h4>Test Your Template</h4>
|
|
590
|
+
<p>Before submitting, test your template locally:</p>
|
|
591
|
+
<div class="step-command">
|
|
592
|
+
<code>cd cli-tool && npm test</code>
|
|
593
|
+
<button class="copy-btn" onclick="copyToClipboard('cd cli-tool && npm test')">Copy</button>
|
|
594
|
+
</div>
|
|
595
|
+
<div class="step-command">
|
|
596
|
+
<code>node src/index.js --language=YOUR_LANGUAGE</code>
|
|
597
|
+
<button class="copy-btn" onclick="copyToClipboard('node src/index.js --language=YOUR_LANGUAGE')">Copy</button>
|
|
598
|
+
</div>
|
|
599
|
+
</div>
|
|
600
|
+
</div>
|
|
601
|
+
|
|
602
|
+
<div class="contribute-step">
|
|
603
|
+
<div class="step-number-contrib">5</div>
|
|
604
|
+
<div class="step-content-contrib">
|
|
605
|
+
<h4>Submit Pull Request</h4>
|
|
606
|
+
<p>Create a pull request with your changes:</p>
|
|
607
|
+
<div class="step-command">
|
|
608
|
+
<code>git add . && git commit -m "feat: Add [LANGUAGE/FRAMEWORK] template"</code>
|
|
609
|
+
<button class="copy-btn" onclick="copyToClipboard('git add . && git commit -m \"feat: Add [LANGUAGE/FRAMEWORK] template\"')">Copy</button>
|
|
610
|
+
</div>
|
|
611
|
+
<div class="step-command">
|
|
612
|
+
<code>git push origin main</code>
|
|
613
|
+
<button class="copy-btn" onclick="copyToClipboard('git push origin main')">Copy</button>
|
|
614
|
+
</div>
|
|
615
|
+
<p>Then go to GitHub and create a Pull Request with:</p>
|
|
616
|
+
<ul>
|
|
617
|
+
<li>Clear title: "feat: Add [Language/Framework] template"</li>
|
|
618
|
+
<li>Description of the template and its use cases</li>
|
|
619
|
+
<li>Screenshots or examples if applicable</li>
|
|
620
|
+
</ul>
|
|
621
|
+
</div>
|
|
622
|
+
</div>
|
|
623
|
+
</div>
|
|
624
|
+
|
|
625
|
+
<div class="contribute-footer">
|
|
626
|
+
<div class="help-section">
|
|
627
|
+
<h4>Need Help?</h4>
|
|
628
|
+
<p>Check out <a href="https://github.com/davila7/claude-code-templates/blob/main/CONTRIBUTING.md" target="_blank">CONTRIBUTING.md</a> or open an issue on GitHub.</p>
|
|
629
|
+
</div>
|
|
630
|
+
</div>
|
|
631
|
+
</div>
|
|
632
|
+
</div>
|
|
633
|
+
</div>
|
|
634
|
+
`;
|
|
635
|
+
|
|
636
|
+
// Remove existing modal if present
|
|
637
|
+
const existingModal = document.querySelector('.modal-overlay');
|
|
638
|
+
if (existingModal) {
|
|
639
|
+
existingModal.remove();
|
|
640
|
+
}
|
|
641
|
+
|
|
642
|
+
// Add modal to body
|
|
643
|
+
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
|
644
|
+
|
|
645
|
+
// Add event listener for ESC key
|
|
646
|
+
const handleEscape = (e) => {
|
|
647
|
+
if (e.key === 'Escape') {
|
|
648
|
+
closeComponentModal();
|
|
649
|
+
document.removeEventListener('keydown', handleEscape);
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
document.addEventListener('keydown', handleEscape);
|
|
653
|
+
}
|
|
654
|
+
|
|
655
|
+
// ===== ANALYTICS AND STATISTICS FUNCTIONALITY =====
|
|
656
|
+
|
|
657
|
+
/**
|
|
658
|
+
* Load and display download statistics from GitHub-generated analytics
|
|
659
|
+
*/
|
|
660
|
+
async function loadDownloadStatistics() {
|
|
661
|
+
try {
|
|
662
|
+
// Fetch analytics data generated by GitHub Actions
|
|
663
|
+
const response = await fetch('analytics/download-stats.json?t=' + Date.now());
|
|
664
|
+
|
|
665
|
+
if (!response.ok) {
|
|
666
|
+
console.log('Analytics data not available yet');
|
|
667
|
+
hideStatisticsSection();
|
|
668
|
+
return;
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
const analyticsData = await response.json();
|
|
672
|
+
displayDownloadStatistics(analyticsData);
|
|
673
|
+
|
|
674
|
+
} catch (error) {
|
|
675
|
+
console.log('Analytics data not available:', error.message);
|
|
676
|
+
hideStatisticsSection();
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Display download statistics in the UI
|
|
682
|
+
*/
|
|
683
|
+
function displayDownloadStatistics(data) {
|
|
684
|
+
// Update total downloads
|
|
685
|
+
const totalElement = document.getElementById('totalDownloads');
|
|
686
|
+
if (totalElement) {
|
|
687
|
+
totalElement.textContent = formatNumber(data.total_downloads || 0);
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
// Update individual component type counts
|
|
691
|
+
const typeElements = {
|
|
692
|
+
agentDownloads: data.downloads_by_type?.agent || 0,
|
|
693
|
+
commandDownloads: data.downloads_by_type?.command || 0,
|
|
694
|
+
mcpDownloads: data.downloads_by_type?.mcp || 0,
|
|
695
|
+
templateDownloads: data.downloads_by_type?.template || 0
|
|
696
|
+
};
|
|
697
|
+
|
|
698
|
+
Object.entries(typeElements).forEach(([elementId, count]) => {
|
|
699
|
+
const element = document.getElementById(elementId);
|
|
700
|
+
if (element) {
|
|
701
|
+
element.textContent = formatNumber(count);
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
|
|
705
|
+
// Find and display most popular component
|
|
706
|
+
const popularElement = document.getElementById('popularComponent');
|
|
707
|
+
if (popularElement && data.downloads_by_component) {
|
|
708
|
+
const topComponent = Object.entries(data.downloads_by_component)[0];
|
|
709
|
+
if (topComponent) {
|
|
710
|
+
const [componentName, downloadCount] = topComponent;
|
|
711
|
+
popularElement.textContent = formatComponentNameForDisplay(componentName);
|
|
712
|
+
popularElement.setAttribute('title', `${formatNumber(downloadCount)} downloads`);
|
|
713
|
+
} else {
|
|
714
|
+
popularElement.textContent = '-';
|
|
715
|
+
}
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
// Update last updated timestamp
|
|
719
|
+
const lastUpdatedElement = document.getElementById('statsLastUpdated');
|
|
720
|
+
if (lastUpdatedElement && data.last_updated) {
|
|
721
|
+
const lastUpdated = new Date(data.last_updated);
|
|
722
|
+
lastUpdatedElement.textContent = formatRelativeTime(lastUpdated);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
// Show the statistics section
|
|
726
|
+
showStatisticsSection();
|
|
727
|
+
|
|
728
|
+
console.log('📊 Download statistics loaded successfully');
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/**
|
|
732
|
+
* Hide statistics section when data is not available
|
|
733
|
+
*/
|
|
734
|
+
function hideStatisticsSection() {
|
|
735
|
+
// Keep statistics section visible even when data is not available
|
|
736
|
+
// const statsSection = document.getElementById('downloadStatsSection');
|
|
737
|
+
// if (statsSection) {
|
|
738
|
+
// statsSection.style.display = 'none';
|
|
739
|
+
// }
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* Show statistics section when data is available
|
|
744
|
+
* Note: Stats section has been moved to dedicated page at /download-stats.html
|
|
745
|
+
*/
|
|
746
|
+
function showStatisticsSection() {
|
|
747
|
+
// Stats section removed from main page - no action needed
|
|
748
|
+
console.log('Stats available at /download-stats.html');
|
|
749
|
+
}
|
|
750
|
+
|
|
751
|
+
/**
|
|
752
|
+
* Format numbers with thousands separators
|
|
753
|
+
*/
|
|
754
|
+
function formatNumber(num) {
|
|
755
|
+
if (num === 0) return '0';
|
|
756
|
+
if (num < 1000) return num.toString();
|
|
757
|
+
if (num < 1000000) return (num / 1000).toFixed(1) + 'K';
|
|
758
|
+
return (num / 1000000).toFixed(1) + 'M';
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Format component name for display (remove prefixes, capitalize)
|
|
763
|
+
*/
|
|
764
|
+
function formatComponentNameForDisplay(componentName) {
|
|
765
|
+
if (!componentName || componentName === 'unknown') return '-';
|
|
766
|
+
|
|
767
|
+
// Handle template format (language/framework)
|
|
768
|
+
if (componentName.includes('/')) {
|
|
769
|
+
const parts = componentName.split('/');
|
|
770
|
+
return parts.map(part =>
|
|
771
|
+
part.replace(/-/g, ' ')
|
|
772
|
+
.replace(/\b\w/g, l => l.toUpperCase())
|
|
773
|
+
).join('/');
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
// Handle individual components
|
|
777
|
+
return componentName
|
|
778
|
+
.replace(/-/g, ' ')
|
|
779
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Format relative time (e.g., "2 hours ago")
|
|
784
|
+
*/
|
|
785
|
+
function formatRelativeTime(date) {
|
|
786
|
+
const now = new Date();
|
|
787
|
+
const diffMs = now - date;
|
|
788
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
789
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
790
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
791
|
+
|
|
792
|
+
if (diffMins < 60) {
|
|
793
|
+
return diffMins <= 1 ? 'just now' : `${diffMins} minutes ago`;
|
|
794
|
+
} else if (diffHours < 24) {
|
|
795
|
+
return diffHours === 1 ? '1 hour ago' : `${diffHours} hours ago`;
|
|
796
|
+
} else if (diffDays < 7) {
|
|
797
|
+
return diffDays === 1 ? '1 day ago' : `${diffDays} days ago`;
|
|
798
|
+
} else {
|
|
799
|
+
return date.toLocaleDateString('en-US', {
|
|
800
|
+
month: 'short',
|
|
801
|
+
day: 'numeric',
|
|
802
|
+
year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
/**
|
|
808
|
+
* Refresh statistics data
|
|
809
|
+
*/
|
|
810
|
+
async function refreshStatistics() {
|
|
811
|
+
const refreshButton = document.querySelector('.stats-refresh-btn');
|
|
812
|
+
if (refreshButton) {
|
|
813
|
+
refreshButton.textContent = 'Refreshing...';
|
|
814
|
+
refreshButton.disabled = true;
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
await loadDownloadStatistics();
|
|
818
|
+
|
|
819
|
+
if (refreshButton) {
|
|
820
|
+
refreshButton.textContent = 'Refresh';
|
|
821
|
+
refreshButton.disabled = false;
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
// Auto-refresh statistics every 10 minutes
|
|
826
|
+
setInterval(loadDownloadStatistics, 10 * 60 * 1000);
|
|
827
|
+
|
|
828
|
+
// Get file type based on extension/name
|
|
829
|
+
function getFileType(filename) {
|
|
830
|
+
if (filename.endsWith('.md')) return 'Documentation';
|
|
831
|
+
if (filename.endsWith('.json')) return 'Configuration';
|
|
832
|
+
if (filename.includes('.claude')) return 'Commands';
|
|
833
|
+
if (filename.includes('commands')) return 'Commands';
|
|
834
|
+
return 'Configuration';
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
// Generate GitHub folder URL for templates
|
|
838
|
+
function getGithubFolderUrl(languageKey, frameworkKey) {
|
|
839
|
+
const baseUrl = 'https://github.com/davila7/claude-code-templates/tree/main/cli-tool/templates';
|
|
840
|
+
|
|
841
|
+
if (frameworkKey === 'none' || !frameworkKey) {
|
|
842
|
+
// Base language template
|
|
843
|
+
return `${baseUrl}/${languageKey}`;
|
|
844
|
+
} else {
|
|
845
|
+
// Framework-specific template
|
|
846
|
+
return `${baseUrl}/${languageKey}/examples/${frameworkKey}-app`;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// Generate GitHub file URL for individual files
|
|
851
|
+
function getGithubFileUrl(languageKey, frameworkKey, filePath) {
|
|
852
|
+
const baseUrl = 'https://github.com/davila7/claude-code-templates/blob/main/cli-tool/templates';
|
|
853
|
+
return `${baseUrl}/${filePath}`;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
// Copy to clipboard function
|
|
857
|
+
function copyToClipboard(text) {
|
|
858
|
+
navigator.clipboard.writeText(text).then(() => {
|
|
859
|
+
showCopyFeedback();
|
|
860
|
+
}).catch(err => {
|
|
861
|
+
console.error('Failed to copy: ', err);
|
|
862
|
+
// Fallback for older browsers
|
|
863
|
+
const textArea = document.createElement('textarea');
|
|
864
|
+
textArea.value = text;
|
|
865
|
+
document.body.appendChild(textArea);
|
|
866
|
+
textArea.focus();
|
|
867
|
+
textArea.select();
|
|
868
|
+
try {
|
|
869
|
+
document.execCommand('copy');
|
|
870
|
+
showCopyFeedback();
|
|
871
|
+
} catch (err) {
|
|
872
|
+
console.error('Fallback copy failed: ', err);
|
|
873
|
+
}
|
|
874
|
+
document.body.removeChild(textArea);
|
|
875
|
+
});
|
|
876
|
+
}
|
|
877
|
+
|
|
878
|
+
function showCopyFeedback() {
|
|
879
|
+
// Create temporary feedback element
|
|
880
|
+
const feedback = document.createElement('div');
|
|
881
|
+
feedback.textContent = 'Copied to clipboard!';
|
|
882
|
+
feedback.style.cssText = `
|
|
883
|
+
position: fixed;
|
|
884
|
+
top: 20px;
|
|
885
|
+
right: 20px;
|
|
886
|
+
background: #48bb78;
|
|
887
|
+
color: white;
|
|
888
|
+
padding: 1rem 1.5rem;
|
|
889
|
+
border-radius: 8px;
|
|
890
|
+
font-weight: 500;
|
|
891
|
+
z-index: 1000;
|
|
892
|
+
animation: slideInRight 0.3s ease;
|
|
893
|
+
`;
|
|
894
|
+
|
|
895
|
+
document.body.appendChild(feedback);
|
|
896
|
+
|
|
897
|
+
// Remove feedback after 2 seconds
|
|
898
|
+
setTimeout(() => {
|
|
899
|
+
feedback.style.animation = 'slideOutRight 0.3s ease';
|
|
900
|
+
setTimeout(() => {
|
|
901
|
+
document.body.removeChild(feedback);
|
|
902
|
+
}, 300);
|
|
903
|
+
}, 2000);
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Add CSS animations for feedback and error states
|
|
907
|
+
const style = document.createElement('style');
|
|
908
|
+
style.textContent = `
|
|
909
|
+
@keyframes slideInRight {
|
|
910
|
+
from {
|
|
911
|
+
transform: translateX(100%);
|
|
912
|
+
opacity: 0;
|
|
913
|
+
}
|
|
914
|
+
to {
|
|
915
|
+
transform: translateX(0);
|
|
916
|
+
opacity: 1;
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
@keyframes slideOutRight {
|
|
921
|
+
from {
|
|
922
|
+
transform: translateX(0);
|
|
923
|
+
opacity: 1;
|
|
924
|
+
}
|
|
925
|
+
to {
|
|
926
|
+
transform: translateX(100%);
|
|
927
|
+
opacity: 0;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
.error-message {
|
|
932
|
+
grid-column: 1 / -1;
|
|
933
|
+
text-align: center;
|
|
934
|
+
color: white;
|
|
935
|
+
background: rgba(220, 53, 69, 0.2);
|
|
936
|
+
border: 1px solid rgba(220, 53, 69, 0.3);
|
|
937
|
+
border-radius: 12px;
|
|
938
|
+
padding: 2rem;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.error-message h3 {
|
|
942
|
+
margin-bottom: 1rem;
|
|
943
|
+
font-size: 1.2rem;
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
.retry-btn {
|
|
947
|
+
background: #dc3545;
|
|
948
|
+
color: white;
|
|
949
|
+
border: none;
|
|
950
|
+
padding: 0.75rem 1.5rem;
|
|
951
|
+
border-radius: 8px;
|
|
952
|
+
cursor: pointer;
|
|
953
|
+
margin-top: 1rem;
|
|
954
|
+
font-size: 0.9rem;
|
|
955
|
+
transition: background 0.2s ease;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
.retry-btn:hover {
|
|
959
|
+
background: #c82333;
|
|
960
|
+
}
|
|
961
|
+
`;
|
|
962
|
+
document.head.appendChild(style);
|
|
963
|
+
|
|
964
|
+
// Initialize the page
|
|
965
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
966
|
+
// Start with agents view (new default)
|
|
967
|
+
setUnifiedFilter('agents');
|
|
968
|
+
// Load download statistics
|
|
969
|
+
loadDownloadStatistics();
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
// Add keyboard navigation
|
|
973
|
+
document.addEventListener('keydown', (e) => {
|
|
974
|
+
if (e.key === 'Escape') {
|
|
975
|
+
// Close all flipped cards
|
|
976
|
+
document.querySelectorAll('.template-card.flipped').forEach(card => {
|
|
977
|
+
card.classList.remove('flipped');
|
|
978
|
+
});
|
|
979
|
+
}
|
|
980
|
+
});
|
|
981
|
+
|
|
982
|
+
// Auto-refresh templates every 5 minutes to pick up changes
|
|
983
|
+
setInterval(fetchTemplatesConfig, 5 * 60 * 1000);
|
|
984
|
+
|
|
985
|
+
// ===== UNIFIED COMPONENTS FUNCTIONALITY =====
|
|
986
|
+
|
|
987
|
+
let componentsData = {
|
|
988
|
+
agents: [],
|
|
989
|
+
commands: [],
|
|
990
|
+
mcps: []
|
|
991
|
+
};
|
|
992
|
+
|
|
993
|
+
let currentFilter = 'agents';
|
|
994
|
+
let currentCategoryFilter = 'all';
|
|
995
|
+
let allDataLoaded = false;
|
|
996
|
+
let downloadStats = null;
|
|
997
|
+
let availableCategories = {
|
|
998
|
+
agents: new Set(),
|
|
999
|
+
commands: new Set(),
|
|
1000
|
+
mcps: new Set()
|
|
1001
|
+
};
|
|
1002
|
+
|
|
1003
|
+
// Unified filter functionality
|
|
1004
|
+
function setUnifiedFilter(filter) {
|
|
1005
|
+
currentFilter = filter;
|
|
1006
|
+
currentCategoryFilter = 'all'; // Reset category filter when changing main filter
|
|
1007
|
+
|
|
1008
|
+
// Update filter buttons
|
|
1009
|
+
document.querySelectorAll('.filter-btn').forEach(btn => {
|
|
1010
|
+
btn.classList.remove('active');
|
|
1011
|
+
});
|
|
1012
|
+
const targetFilterBtn = document.querySelector(`[data-filter="${filter}"]`);
|
|
1013
|
+
if (targetFilterBtn) {
|
|
1014
|
+
targetFilterBtn.classList.add('active');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
// Load and display content
|
|
1018
|
+
if (filter === 'templates') {
|
|
1019
|
+
displayTemplates();
|
|
1020
|
+
} else {
|
|
1021
|
+
loadAndDisplayComponents();
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
// Set category filter
|
|
1026
|
+
function setCategoryFilter(category) {
|
|
1027
|
+
currentCategoryFilter = category;
|
|
1028
|
+
|
|
1029
|
+
// Update category filter buttons
|
|
1030
|
+
document.querySelectorAll('.category-filter-btn').forEach(btn => {
|
|
1031
|
+
btn.classList.remove('active');
|
|
1032
|
+
});
|
|
1033
|
+
const targetBtn = document.querySelector(`[data-category="${category}"]`);
|
|
1034
|
+
if (targetBtn) {
|
|
1035
|
+
targetBtn.classList.add('active');
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Regenerate the component display
|
|
1039
|
+
generateUnifiedComponentCards();
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
// Make setCategoryFilter available globally
|
|
1043
|
+
window.setCategoryFilter = setCategoryFilter;
|
|
1044
|
+
|
|
1045
|
+
// Display templates (existing functionality)
|
|
1046
|
+
function displayTemplates() {
|
|
1047
|
+
const unifiedGrid = document.getElementById('unifiedGrid');
|
|
1048
|
+
unifiedGrid.className = 'unified-grid templates-mode';
|
|
1049
|
+
|
|
1050
|
+
if (templatesData) {
|
|
1051
|
+
generateTemplateCards();
|
|
1052
|
+
} else {
|
|
1053
|
+
unifiedGrid.innerHTML = '<div class="loading">Loading templates from GitHub...</div>';
|
|
1054
|
+
fetchTemplatesConfig();
|
|
1055
|
+
}
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// Load and display components
|
|
1059
|
+
async function loadAndDisplayComponents() {
|
|
1060
|
+
const unifiedGrid = document.getElementById('unifiedGrid');
|
|
1061
|
+
unifiedGrid.className = 'unified-grid components-mode';
|
|
1062
|
+
|
|
1063
|
+
if (!allDataLoaded) {
|
|
1064
|
+
unifiedGrid.innerHTML = '<div class="loading">Loading components from GitHub...</div>';
|
|
1065
|
+
await loadAllComponentsData();
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
generateUnifiedComponentCards();
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// Load all components data
|
|
1072
|
+
async function loadAllComponentsData() {
|
|
1073
|
+
try {
|
|
1074
|
+
const response = await fetch('components.json');
|
|
1075
|
+
if (!response.ok) {
|
|
1076
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
|
1077
|
+
}
|
|
1078
|
+
const data = await response.json();
|
|
1079
|
+
componentsData = data;
|
|
1080
|
+
collectAvailableCategories();
|
|
1081
|
+
allDataLoaded = true;
|
|
1082
|
+
} catch (error) {
|
|
1083
|
+
console.error('Error loading components:', error);
|
|
1084
|
+
const unifiedGrid = document.getElementById('unifiedGrid');
|
|
1085
|
+
unifiedGrid.innerHTML = `
|
|
1086
|
+
<div class="error-message">
|
|
1087
|
+
<h3>Error loading components</h3>
|
|
1088
|
+
<p>Could not fetch components from local data. Please try again later.</p>
|
|
1089
|
+
<button onclick="loadAndDisplayComponents()" class="retry-btn">Retry</button>
|
|
1090
|
+
</div>
|
|
1091
|
+
`;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Update category sub-filters in the unified-filter-bar
|
|
1096
|
+
function updateCategorySubFilters() {
|
|
1097
|
+
const unifiedFilterBar = document.querySelector('.unified-filter-bar');
|
|
1098
|
+
|
|
1099
|
+
// Remove existing category filters
|
|
1100
|
+
const existingCategoryFilters = unifiedFilterBar.querySelector('.category-filter-row');
|
|
1101
|
+
if (existingCategoryFilters) {
|
|
1102
|
+
existingCategoryFilters.remove();
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// Get categories for current filter type
|
|
1106
|
+
const currentCategories = Array.from(availableCategories[currentFilter] || []).sort();
|
|
1107
|
+
|
|
1108
|
+
if (currentCategories.length <= 1 || currentFilter === 'templates') {
|
|
1109
|
+
// Don't show sub-filters if there's only one category, none, or templates
|
|
1110
|
+
return;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
// Create category filter row
|
|
1114
|
+
const categoryFilterRow = document.createElement('div');
|
|
1115
|
+
categoryFilterRow.className = 'category-filter-row';
|
|
1116
|
+
categoryFilterRow.innerHTML = `
|
|
1117
|
+
<div class="category-filter-label">Categories:</div>
|
|
1118
|
+
<div class="category-filter-buttons">
|
|
1119
|
+
<button class="category-filter-btn ${currentCategoryFilter === 'all' ? 'active' : ''}"
|
|
1120
|
+
data-category="all">
|
|
1121
|
+
All
|
|
1122
|
+
</button>
|
|
1123
|
+
${currentCategories.map(category => `
|
|
1124
|
+
<button class="category-filter-btn ${currentCategoryFilter === category ? 'active' : ''}"
|
|
1125
|
+
data-category="${category}">
|
|
1126
|
+
${formatComponentName(category)}
|
|
1127
|
+
</button>
|
|
1128
|
+
`).join('')}
|
|
1129
|
+
</div>
|
|
1130
|
+
`;
|
|
1131
|
+
|
|
1132
|
+
// Add click event listeners
|
|
1133
|
+
categoryFilterRow.querySelectorAll('.category-filter-btn').forEach(btn => {
|
|
1134
|
+
btn.addEventListener('click', () => {
|
|
1135
|
+
setCategoryFilter(btn.getAttribute('data-category'));
|
|
1136
|
+
});
|
|
1137
|
+
});
|
|
1138
|
+
|
|
1139
|
+
// Append to unified filter bar
|
|
1140
|
+
unifiedFilterBar.appendChild(categoryFilterRow);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// Generate unified component cards
|
|
1144
|
+
function generateUnifiedComponentCards() {
|
|
1145
|
+
const unifiedGrid = document.getElementById('unifiedGrid');
|
|
1146
|
+
unifiedGrid.innerHTML = '';
|
|
1147
|
+
|
|
1148
|
+
// Update category sub-filters in the unified-filter-bar
|
|
1149
|
+
updateCategorySubFilters();
|
|
1150
|
+
|
|
1151
|
+
// Get filtered components
|
|
1152
|
+
const filteredComponents = getFilteredComponents();
|
|
1153
|
+
|
|
1154
|
+
// Add "Add New" card based on current filter
|
|
1155
|
+
if (currentFilter !== 'templates') {
|
|
1156
|
+
const addCard = createAddComponentCard(currentFilter);
|
|
1157
|
+
unifiedGrid.appendChild(addCard);
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// Add component cards
|
|
1161
|
+
filteredComponents.forEach(component => {
|
|
1162
|
+
const card = createComponentCard(component);
|
|
1163
|
+
unifiedGrid.appendChild(card);
|
|
1164
|
+
});
|
|
1165
|
+
|
|
1166
|
+
// Update filter button with count
|
|
1167
|
+
updateFilterCount();
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
// Update filter button count
|
|
1171
|
+
function updateFilterCount() {
|
|
1172
|
+
const filterBtn = document.querySelector(`[data-filter="${currentFilter}"]`);
|
|
1173
|
+
if (filterBtn && currentFilter !== 'templates') {
|
|
1174
|
+
const components = componentsData[currentFilter];
|
|
1175
|
+
if (components && Array.isArray(components)) {
|
|
1176
|
+
const count = components.length;
|
|
1177
|
+
const originalText = filterBtn.textContent.split('(')[0].trim();
|
|
1178
|
+
filterBtn.textContent = `${originalText} (${count})`;
|
|
1179
|
+
}
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
// Get filtered components based on current filter and category filter
|
|
1184
|
+
function getFilteredComponents() {
|
|
1185
|
+
if (currentFilter === 'templates') {
|
|
1186
|
+
return [];
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
let components = componentsData[currentFilter] || [];
|
|
1190
|
+
|
|
1191
|
+
// Apply category filter if not 'all'
|
|
1192
|
+
if (currentCategoryFilter !== 'all') {
|
|
1193
|
+
components = components.filter(component => {
|
|
1194
|
+
const category = component.category || 'general';
|
|
1195
|
+
return category === currentCategoryFilter;
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1198
|
+
|
|
1199
|
+
return components;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
// Collect available categories from loaded components
|
|
1203
|
+
function collectAvailableCategories() {
|
|
1204
|
+
// Reset categories
|
|
1205
|
+
availableCategories.agents.clear();
|
|
1206
|
+
availableCategories.commands.clear();
|
|
1207
|
+
availableCategories.mcps.clear();
|
|
1208
|
+
|
|
1209
|
+
// Collect categories from each component type
|
|
1210
|
+
if (componentsData.agents && Array.isArray(componentsData.agents)) {
|
|
1211
|
+
componentsData.agents.forEach(component => {
|
|
1212
|
+
const category = component.category || 'general';
|
|
1213
|
+
availableCategories.agents.add(category);
|
|
1214
|
+
});
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
if (componentsData.commands && Array.isArray(componentsData.commands)) {
|
|
1218
|
+
componentsData.commands.forEach(component => {
|
|
1219
|
+
const category = component.category || 'general';
|
|
1220
|
+
availableCategories.commands.add(category);
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
|
|
1224
|
+
if (componentsData.mcps && Array.isArray(componentsData.mcps)) {
|
|
1225
|
+
componentsData.mcps.forEach(component => {
|
|
1226
|
+
const category = component.category || 'general';
|
|
1227
|
+
availableCategories.mcps.add(category);
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
// Load components data from GitHub (legacy function for compatibility)
|
|
1233
|
+
async function loadComponentsData() {
|
|
1234
|
+
// Redirect to unified loading function
|
|
1235
|
+
await loadAndDisplayComponents();
|
|
1236
|
+
}
|
|
1237
|
+
|
|
1238
|
+
// Load specific component type from GitHub
|
|
1239
|
+
async function loadComponentType(type) {
|
|
1240
|
+
const baseUrl = `https://api.github.com/repos/${GITHUB_CONFIG.owner}/${GITHUB_CONFIG.repo}/contents/cli-tool/components/${type}`;
|
|
1241
|
+
|
|
1242
|
+
try {
|
|
1243
|
+
const response = await fetch(baseUrl);
|
|
1244
|
+
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
|
1245
|
+
|
|
1246
|
+
const files = await response.json();
|
|
1247
|
+
const componentPromises = files.map(async (file) => {
|
|
1248
|
+
if (file.name.endsWith('.md') || file.name.endsWith('.json')) {
|
|
1249
|
+
// Direct file in root level
|
|
1250
|
+
const contentResponse = await fetch(file.download_url);
|
|
1251
|
+
const content = await contentResponse.text();
|
|
1252
|
+
|
|
1253
|
+
return {
|
|
1254
|
+
name: file.name.replace(/\.(md|json)$/, ''),
|
|
1255
|
+
type: type,
|
|
1256
|
+
filename: file.name,
|
|
1257
|
+
content: content,
|
|
1258
|
+
url: file.html_url,
|
|
1259
|
+
category: null // No category for root level components
|
|
1260
|
+
};
|
|
1261
|
+
} else if (file.type === 'dir') {
|
|
1262
|
+
// Handle subdirectories for all component types (categories)
|
|
1263
|
+
try {
|
|
1264
|
+
const categoryResponse = await fetch(`https://api.github.com/repos/${GITHUB_CONFIG.owner}/${GITHUB_CONFIG.repo}/contents/cli-tool/components/${type}/${file.name}`);
|
|
1265
|
+
if (categoryResponse.ok) {
|
|
1266
|
+
const categoryFiles = await categoryResponse.json();
|
|
1267
|
+
const categoryComponentPromises = categoryFiles.map(async (categoryFile) => {
|
|
1268
|
+
if (categoryFile.name.endsWith('.md') || categoryFile.name.endsWith('.json')) {
|
|
1269
|
+
const contentResponse = await fetch(categoryFile.download_url);
|
|
1270
|
+
const content = await contentResponse.text();
|
|
1271
|
+
|
|
1272
|
+
return {
|
|
1273
|
+
name: `${file.name}/${categoryFile.name.replace(/\.(md|json)$/, '')}`,
|
|
1274
|
+
type: type,
|
|
1275
|
+
filename: categoryFile.name,
|
|
1276
|
+
content: content,
|
|
1277
|
+
url: categoryFile.html_url,
|
|
1278
|
+
category: file.name
|
|
1279
|
+
};
|
|
1280
|
+
}
|
|
1281
|
+
return null;
|
|
1282
|
+
});
|
|
1283
|
+
|
|
1284
|
+
const categoryComponents = await Promise.all(categoryComponentPromises);
|
|
1285
|
+
return categoryComponents.filter(c => c !== null);
|
|
1286
|
+
}
|
|
1287
|
+
} catch (error) {
|
|
1288
|
+
console.warn(`Warning: Could not load category ${file.name}:`, error);
|
|
1289
|
+
return [];
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return null;
|
|
1293
|
+
});
|
|
1294
|
+
|
|
1295
|
+
const componentsNested = await Promise.all(componentPromises);
|
|
1296
|
+
// Flatten the array since subdirectories return arrays
|
|
1297
|
+
const components = componentsNested.flat().filter(c => c !== null);
|
|
1298
|
+
return components;
|
|
1299
|
+
|
|
1300
|
+
} catch (error) {
|
|
1301
|
+
console.error(`Error loading ${type}:`, error);
|
|
1302
|
+
return [];
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
|
|
1306
|
+
// Generate component cards with filter functionality
|
|
1307
|
+
function generateComponentCards() {
|
|
1308
|
+
const componentsGrid = document.getElementById('componentsGrid');
|
|
1309
|
+
|
|
1310
|
+
// Create filter bar
|
|
1311
|
+
const filterBar = createComponentFilterBar();
|
|
1312
|
+
|
|
1313
|
+
// Create components container
|
|
1314
|
+
const componentsContainer = document.createElement('div');
|
|
1315
|
+
componentsContainer.className = 'components-container';
|
|
1316
|
+
|
|
1317
|
+
// Create Add New cards for each category
|
|
1318
|
+
const addAgentCard = createAddComponentCard('agents');
|
|
1319
|
+
const addCommandCard = createAddComponentCard('commands');
|
|
1320
|
+
const addMcpCard = createAddComponentCard('mcps');
|
|
1321
|
+
|
|
1322
|
+
// Filter and display components
|
|
1323
|
+
const filteredComponents = getFilteredComponents();
|
|
1324
|
+
|
|
1325
|
+
componentsContainer.innerHTML = '';
|
|
1326
|
+
|
|
1327
|
+
// Add "Add New" cards based on filter
|
|
1328
|
+
if (currentFilter === 'all' || currentFilter === 'agents') {
|
|
1329
|
+
componentsContainer.appendChild(addAgentCard);
|
|
1330
|
+
}
|
|
1331
|
+
if (currentFilter === 'all' || currentFilter === 'commands') {
|
|
1332
|
+
componentsContainer.appendChild(addCommandCard);
|
|
1333
|
+
}
|
|
1334
|
+
if (currentFilter === 'all' || currentFilter === 'mcps') {
|
|
1335
|
+
componentsContainer.appendChild(addMcpCard);
|
|
1336
|
+
}
|
|
1337
|
+
|
|
1338
|
+
// Add component cards
|
|
1339
|
+
filteredComponents.forEach(component => {
|
|
1340
|
+
const card = createComponentCard(component);
|
|
1341
|
+
componentsContainer.appendChild(card);
|
|
1342
|
+
});
|
|
1343
|
+
|
|
1344
|
+
componentsGrid.innerHTML = '';
|
|
1345
|
+
componentsGrid.appendChild(filterBar);
|
|
1346
|
+
componentsGrid.appendChild(componentsContainer);
|
|
1347
|
+
}
|
|
1348
|
+
|
|
1349
|
+
// Create filter bar for components
|
|
1350
|
+
function createComponentFilterBar() {
|
|
1351
|
+
const filterBar = document.createElement('div');
|
|
1352
|
+
filterBar.className = 'component-filter-bar';
|
|
1353
|
+
|
|
1354
|
+
const totalCounts = {
|
|
1355
|
+
all: componentsData.agents.length + componentsData.commands.length + componentsData.mcps.length,
|
|
1356
|
+
agents: componentsData.agents.length,
|
|
1357
|
+
commands: componentsData.commands.length,
|
|
1358
|
+
mcps: componentsData.mcps.length
|
|
1359
|
+
};
|
|
1360
|
+
|
|
1361
|
+
filterBar.innerHTML = `
|
|
1362
|
+
<div class="filter-label">$ Filter Components</div>
|
|
1363
|
+
<div class="filter-buttons">
|
|
1364
|
+
<button class="filter-btn ${currentFilter === 'all' ? 'active' : ''}" onclick="setComponentFilter('all')">
|
|
1365
|
+
All (${totalCounts.all})
|
|
1366
|
+
</button>
|
|
1367
|
+
<button class="filter-btn ${currentFilter === 'agents' ? 'active' : ''}" onclick="setComponentFilter('agents')">
|
|
1368
|
+
🤖 Agents (${totalCounts.agents})
|
|
1369
|
+
</button>
|
|
1370
|
+
<button class="filter-btn ${currentFilter === 'commands' ? 'active' : ''}" onclick="setComponentFilter('commands')">
|
|
1371
|
+
⚡ Commands (${totalCounts.commands})
|
|
1372
|
+
</button>
|
|
1373
|
+
<button class="filter-btn ${currentFilter === 'mcps' ? 'active' : ''}" onclick="setComponentFilter('mcps')">
|
|
1374
|
+
🔌 MCPs (${totalCounts.mcps})
|
|
1375
|
+
</button>
|
|
1376
|
+
</div>
|
|
1377
|
+
`;
|
|
1378
|
+
|
|
1379
|
+
return filterBar;
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
// Set component filter
|
|
1383
|
+
function setComponentFilter(filter) {
|
|
1384
|
+
currentFilter = filter;
|
|
1385
|
+
generateComponentCards();
|
|
1386
|
+
}
|
|
1387
|
+
|
|
1388
|
+
|
|
1389
|
+
// Create Add Component card
|
|
1390
|
+
function createAddComponentCard(type) {
|
|
1391
|
+
const card = document.createElement('div');
|
|
1392
|
+
card.className = 'template-card add-template-card add-component-card';
|
|
1393
|
+
|
|
1394
|
+
const typeConfig = {
|
|
1395
|
+
agents: {
|
|
1396
|
+
icon: `<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor">
|
|
1397
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
|
|
1398
|
+
</svg>`,
|
|
1399
|
+
name: 'Agent',
|
|
1400
|
+
description: 'Create a new AI specialist agent'
|
|
1401
|
+
},
|
|
1402
|
+
commands: {
|
|
1403
|
+
icon: `<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor">
|
|
1404
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
|
|
1405
|
+
</svg>`,
|
|
1406
|
+
name: 'Command',
|
|
1407
|
+
description: 'Add a custom slash command'
|
|
1408
|
+
},
|
|
1409
|
+
mcps: {
|
|
1410
|
+
icon: `<svg width="32" height="32" viewBox="0 0 24 24" fill="currentColor">
|
|
1411
|
+
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm5 11h-4v4h-2v-4H7v-2h4V7h2v4h4v2z"/>
|
|
1412
|
+
</svg>`,
|
|
1413
|
+
name: 'MCP',
|
|
1414
|
+
description: 'Build a Model Context Protocol integration'
|
|
1415
|
+
}
|
|
1416
|
+
};
|
|
1417
|
+
|
|
1418
|
+
const config = typeConfig[type];
|
|
1419
|
+
|
|
1420
|
+
card.innerHTML = `
|
|
1421
|
+
<div class="card-inner">
|
|
1422
|
+
<div class="card-front">
|
|
1423
|
+
<div class="framework-logo">
|
|
1424
|
+
${config.icon}
|
|
1425
|
+
</div>
|
|
1426
|
+
<h3 class="template-title">Add New ${config.name}</h3>
|
|
1427
|
+
<p class="template-description">${config.description}</p>
|
|
1428
|
+
</div>
|
|
1429
|
+
</div>
|
|
1430
|
+
`;
|
|
1431
|
+
|
|
1432
|
+
// Add click handler to open contribution modal directly (no flip)
|
|
1433
|
+
card.addEventListener('click', () => {
|
|
1434
|
+
showComponentContributeModal(type);
|
|
1435
|
+
});
|
|
1436
|
+
|
|
1437
|
+
return card;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// Create individual component card
|
|
1441
|
+
function createComponentCard(component) {
|
|
1442
|
+
const card = document.createElement('div');
|
|
1443
|
+
card.className = 'template-card';
|
|
1444
|
+
|
|
1445
|
+
const typeConfig = {
|
|
1446
|
+
agent: { icon: '🤖', color: '#ff6b6b' },
|
|
1447
|
+
command: { icon: '⚡', color: '#4ecdc4' },
|
|
1448
|
+
mcp: { icon: '🔌', color: '#45b7d1' }
|
|
1449
|
+
};
|
|
1450
|
+
|
|
1451
|
+
const config = typeConfig[component.type];
|
|
1452
|
+
const installCommand = generateInstallCommand(component);
|
|
1453
|
+
|
|
1454
|
+
// Get download count for this component
|
|
1455
|
+
const downloadCount = getDownloadCount(component.name, component.type);
|
|
1456
|
+
const downloadBadge = createDownloadBadge(downloadCount);
|
|
1457
|
+
|
|
1458
|
+
// Create category label for all components (use "General" if no category)
|
|
1459
|
+
const categoryName = component.category || 'general';
|
|
1460
|
+
const categoryLabel = `<div class="category-label">${formatComponentName(categoryName)}</div>`;
|
|
1461
|
+
|
|
1462
|
+
card.innerHTML = `
|
|
1463
|
+
<div class="card-inner">
|
|
1464
|
+
<div class="card-front">
|
|
1465
|
+
${downloadBadge}
|
|
1466
|
+
${categoryLabel}
|
|
1467
|
+
<div class="framework-logo" style="color: ${config.color}">
|
|
1468
|
+
<span class="component-icon">${config.icon}</span>
|
|
1469
|
+
</div>
|
|
1470
|
+
<h3 class="template-title">${formatComponentName(component.name)}</h3>
|
|
1471
|
+
<p class="template-description">${getComponentDescription(component)}</p>
|
|
1472
|
+
</div>
|
|
1473
|
+
<div class="card-back">
|
|
1474
|
+
<div class="command-display">
|
|
1475
|
+
<h3>Installation Command</h3>
|
|
1476
|
+
<div class="command-code">${installCommand}</div>
|
|
1477
|
+
<div class="action-buttons">
|
|
1478
|
+
<button class="view-files-btn" onclick="showComponentDetails('${component.type}', '${component.name}')">
|
|
1479
|
+
📁 View Details
|
|
1480
|
+
</button>
|
|
1481
|
+
<button class="copy-command-btn" onclick="copyToClipboard('${installCommand}')">
|
|
1482
|
+
📋 Copy Command
|
|
1483
|
+
</button>
|
|
1484
|
+
</div>
|
|
1485
|
+
</div>
|
|
1486
|
+
</div>
|
|
1487
|
+
</div>
|
|
1488
|
+
`;
|
|
1489
|
+
|
|
1490
|
+
// Add click handler for card flip
|
|
1491
|
+
card.addEventListener('click', (e) => {
|
|
1492
|
+
if (!e.target.closest('button')) {
|
|
1493
|
+
card.classList.toggle('flipped');
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
|
|
1497
|
+
return card;
|
|
1498
|
+
}
|
|
1499
|
+
|
|
1500
|
+
// Generate install command for component
|
|
1501
|
+
function generateInstallCommand(component) {
|
|
1502
|
+
if (component.type === 'agent') {
|
|
1503
|
+
return `npx claude-code-templates@latest --agent=${component.name} --yes`;
|
|
1504
|
+
} else if (component.type === 'command') {
|
|
1505
|
+
return `npx claude-code-templates@latest --command=${component.name} --yes`;
|
|
1506
|
+
} else if (component.type === 'mcp') {
|
|
1507
|
+
// Remove .json extension from MCP names for the command
|
|
1508
|
+
const mcpName = component.name.replace(/\.json$/, '');
|
|
1509
|
+
return `npx claude-code-templates@latest --mcp=${mcpName} --yes`;
|
|
1510
|
+
}
|
|
1511
|
+
return `npx claude-code-templates@latest`;
|
|
1512
|
+
}
|
|
1513
|
+
|
|
1514
|
+
|
|
1515
|
+
// Get installation notes (removed to match template cards design)
|
|
1516
|
+
function getInstallationNotes() {
|
|
1517
|
+
return '';
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// Format component name for display
|
|
1521
|
+
function formatComponentName(name) {
|
|
1522
|
+
// Handle subcategorized agents (e.g., "deep-research-team/academic-researcher")
|
|
1523
|
+
if (name.includes('/')) {
|
|
1524
|
+
const parts = name.split('/');
|
|
1525
|
+
const actualName = parts[parts.length - 1]; // Get the last part after the slash
|
|
1526
|
+
return actualName
|
|
1527
|
+
.replace(/-/g, ' ')
|
|
1528
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
1529
|
+
}
|
|
1530
|
+
|
|
1531
|
+
return name
|
|
1532
|
+
.replace(/-/g, ' ')
|
|
1533
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// Get component description
|
|
1537
|
+
function getComponentDescription(component) {
|
|
1538
|
+
return `A component of type '${component.type}' for Claude Code.`;
|
|
1539
|
+
}
|
|
1540
|
+
|
|
1541
|
+
// Show component details modal
|
|
1542
|
+
async function showComponentDetails(type, name) {
|
|
1543
|
+
const component = componentsData[type + 's'].find(c => c.name === name);
|
|
1544
|
+
if (!component) return;
|
|
1545
|
+
|
|
1546
|
+
const modal = document.getElementById('componentModal');
|
|
1547
|
+
document.getElementById('componentModalTitle').textContent = name;
|
|
1548
|
+
document.getElementById('componentModalType').textContent = type;
|
|
1549
|
+
document.getElementById('componentModalCategory').textContent = component.category;
|
|
1550
|
+
document.getElementById('componentModalPath').textContent = component.path;
|
|
1551
|
+
document.getElementById('componentModalUsage').textContent = `cct --${type} "${component.path}"`;
|
|
1552
|
+
|
|
1553
|
+
const descriptionElement = document.getElementById('componentModalDescription');
|
|
1554
|
+
descriptionElement.textContent = component.content || 'No content available.';
|
|
1555
|
+
modal.style.display = 'block';
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
// Show component contribute modal
|
|
1559
|
+
function showComponentContributeModal(type) {
|
|
1560
|
+
const typeConfig = {
|
|
1561
|
+
agents: {
|
|
1562
|
+
name: 'Agent',
|
|
1563
|
+
description: 'AI specialist that handles specific development tasks',
|
|
1564
|
+
example: 'python-testing-specialist',
|
|
1565
|
+
structure: '- Agent metadata (name, description, color)\n- Core expertise areas\n- When to use guidelines\n- Code examples and patterns'
|
|
1566
|
+
},
|
|
1567
|
+
commands: {
|
|
1568
|
+
name: 'Command',
|
|
1569
|
+
description: 'Custom slash command for Claude Code',
|
|
1570
|
+
example: 'optimize-bundle',
|
|
1571
|
+
structure: '- Command description and usage\n- Task breakdown\n- Process steps\n- Best practices and examples'
|
|
1572
|
+
},
|
|
1573
|
+
mcps: {
|
|
1574
|
+
name: 'MCP',
|
|
1575
|
+
description: 'Model Context Protocol integration',
|
|
1576
|
+
example: 'redis-integration',
|
|
1577
|
+
structure: '- MCP server configuration\n- Connection parameters\n- Environment variables\n- Usage examples'
|
|
1578
|
+
}
|
|
1579
|
+
};
|
|
1580
|
+
|
|
1581
|
+
const config = typeConfig[type];
|
|
1582
|
+
|
|
1583
|
+
const modalHTML = `
|
|
1584
|
+
<div class="modal-overlay" onclick="closeModal()">
|
|
1585
|
+
<div class="modal-content contribute-modal" onclick="event.stopPropagation()">
|
|
1586
|
+
<div class="modal-header">
|
|
1587
|
+
<h3>📝 Contribute a New ${config.name}</h3>
|
|
1588
|
+
<button class="modal-close" onclick="closeModal()">×</button>
|
|
1589
|
+
</div>
|
|
1590
|
+
<div class="modal-body">
|
|
1591
|
+
<div class="contribute-intro">
|
|
1592
|
+
<p>Help expand Claude Code by contributing a new ${config.name.toLowerCase()}! Follow these steps:</p>
|
|
1593
|
+
</div>
|
|
1594
|
+
|
|
1595
|
+
<div class="contribute-steps">
|
|
1596
|
+
<div class="contribute-step">
|
|
1597
|
+
<div class="step-number-contrib">1</div>
|
|
1598
|
+
<div class="step-content-contrib">
|
|
1599
|
+
<h4>Create Your ${config.name}</h4>
|
|
1600
|
+
<p>Add your ${config.name.toLowerCase()} to: <code>cli-tool/components/${type}/</code></p>
|
|
1601
|
+
<div class="component-structure">
|
|
1602
|
+
<strong>Structure should include:</strong>
|
|
1603
|
+
<pre>${config.structure}</pre>
|
|
1604
|
+
</div>
|
|
1605
|
+
<div class="step-command">
|
|
1606
|
+
<strong>Example filename:</strong> <code>${config.example}.${type === 'mcps' ? 'json' : 'md'}</code>
|
|
1607
|
+
</div>
|
|
1608
|
+
</div>
|
|
1609
|
+
</div>
|
|
1610
|
+
|
|
1611
|
+
<div class="contribute-step">
|
|
1612
|
+
<div class="step-number-contrib">2</div>
|
|
1613
|
+
<div class="step-content-contrib">
|
|
1614
|
+
<h4>Follow the Pattern</h4>
|
|
1615
|
+
<p>Check existing ${type} in the repository to understand the structure and conventions.</p>
|
|
1616
|
+
<div class="step-command">
|
|
1617
|
+
<a href="https://github.com/davila7/claude-code-templates/tree/main/cli-tool/components/${type}" target="_blank" class="github-folder-link">
|
|
1618
|
+
📁 View existing ${type}
|
|
1619
|
+
</a>
|
|
1620
|
+
</div>
|
|
1621
|
+
</div>
|
|
1622
|
+
</div>
|
|
1623
|
+
|
|
1624
|
+
<div class="contribute-step">
|
|
1625
|
+
<div class="step-number-contrib">3</div>
|
|
1626
|
+
<div class="step-content-contrib">
|
|
1627
|
+
<h4>Test Your Component</h4>
|
|
1628
|
+
<p>Ensure your ${config.name.toLowerCase()} works correctly with Claude Code.</p>
|
|
1629
|
+
<div class="step-command">
|
|
1630
|
+
<code>cd cli-tool && npm test</code>
|
|
1631
|
+
<button class="copy-btn" onclick="copyToClipboard('cd cli-tool && npm test')">Copy</button>
|
|
1632
|
+
</div>
|
|
1633
|
+
</div>
|
|
1634
|
+
</div>
|
|
1635
|
+
|
|
1636
|
+
<div class="contribute-step">
|
|
1637
|
+
<div class="step-number-contrib">4</div>
|
|
1638
|
+
<div class="step-content-contrib">
|
|
1639
|
+
<h4>Submit Pull Request</h4>
|
|
1640
|
+
<p>Submit your contribution with proper documentation:</p>
|
|
1641
|
+
<div class="step-command">
|
|
1642
|
+
<code>git add cli-tool/components/${type}/${config.example}.${type === 'mcps' ? 'json' : 'md'}</code>
|
|
1643
|
+
<button class="copy-btn" onclick="copyToClipboard('git add cli-tool/components/${type}/${config.example}.${type === 'mcps' ? 'json' : 'md'}')">Copy</button>
|
|
1644
|
+
</div>
|
|
1645
|
+
<div class="step-command">
|
|
1646
|
+
<code>git commit -m "feat: Add ${config.example} ${config.name.toLowerCase()}"</code>
|
|
1647
|
+
<button class="copy-btn" onclick="copyToClipboard('git commit -m \"feat: Add ${config.example} ${config.name.toLowerCase()}\"')">Copy</button>
|
|
1648
|
+
</div>
|
|
1649
|
+
</div>
|
|
1650
|
+
</div>
|
|
1651
|
+
</div>
|
|
1652
|
+
|
|
1653
|
+
<div class="contribute-footer">
|
|
1654
|
+
<div class="help-section">
|
|
1655
|
+
<h4>Need Help?</h4>
|
|
1656
|
+
<p>Check existing ${type} for examples or open an issue on GitHub for guidance.</p>
|
|
1657
|
+
</div>
|
|
1658
|
+
</div>
|
|
1659
|
+
</div>
|
|
1660
|
+
</div>
|
|
1661
|
+
</div>
|
|
1662
|
+
`;
|
|
1663
|
+
|
|
1664
|
+
// Add modal to page
|
|
1665
|
+
const modal = document.createElement('div');
|
|
1666
|
+
modal.innerHTML = modalHTML;
|
|
1667
|
+
modal.className = 'modal contribute-component-modal';
|
|
1668
|
+
document.body.appendChild(modal);
|
|
1669
|
+
|
|
1670
|
+
// Add event listener for ESC key
|
|
1671
|
+
const handleEscape = (e) => {
|
|
1672
|
+
if (e.key === 'Escape') {
|
|
1673
|
+
closeComponentModal();
|
|
1674
|
+
document.removeEventListener('keydown', handleEscape);
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
1677
|
+
document.addEventListener('keydown', handleEscape);
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
// ===== ANALYTICS AND STATISTICS FUNCTIONALITY =====
|
|
1681
|
+
|
|
1682
|
+
/**
|
|
1683
|
+
* Load and display download statistics from GitHub-generated analytics
|
|
1684
|
+
*/
|
|
1685
|
+
async function loadDownloadStatistics() {
|
|
1686
|
+
try {
|
|
1687
|
+
// Fetch analytics data generated by GitHub Actions
|
|
1688
|
+
const response = await fetch('analytics/download-stats.json?t=' + Date.now());
|
|
1689
|
+
|
|
1690
|
+
if (!response.ok) {
|
|
1691
|
+
console.log('Analytics data not available yet');
|
|
1692
|
+
hideStatisticsSection();
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
const analyticsData = await response.json();
|
|
1697
|
+
displayDownloadStatistics(analyticsData);
|
|
1698
|
+
|
|
1699
|
+
} catch (error) {
|
|
1700
|
+
console.log('Analytics data not available:', error.message);
|
|
1701
|
+
hideStatisticsSection();
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
/**
|
|
1706
|
+
* Display download statistics in the UI
|
|
1707
|
+
*/
|
|
1708
|
+
function displayDownloadStatistics(data) {
|
|
1709
|
+
// Update total downloads
|
|
1710
|
+
const totalElement = document.getElementById('totalDownloads');
|
|
1711
|
+
if (totalElement) {
|
|
1712
|
+
totalElement.textContent = formatNumber(data.total_downloads || 0);
|
|
1713
|
+
}
|
|
1714
|
+
|
|
1715
|
+
// Update individual component type counts
|
|
1716
|
+
const typeElements = {
|
|
1717
|
+
agentDownloads: data.downloads_by_type?.agent || 0,
|
|
1718
|
+
commandDownloads: data.downloads_by_type?.command || 0,
|
|
1719
|
+
mcpDownloads: data.downloads_by_type?.mcp || 0,
|
|
1720
|
+
templateDownloads: data.downloads_by_type?.template || 0
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1723
|
+
Object.entries(typeElements).forEach(([elementId, count]) => {
|
|
1724
|
+
const element = document.getElementById(elementId);
|
|
1725
|
+
if (element) {
|
|
1726
|
+
element.textContent = formatNumber(count);
|
|
1727
|
+
}
|
|
1728
|
+
});
|
|
1729
|
+
|
|
1730
|
+
// Find and display most popular component
|
|
1731
|
+
const popularElement = document.getElementById('popularComponent');
|
|
1732
|
+
if (popularElement && data.downloads_by_component) {
|
|
1733
|
+
const topComponent = Object.entries(data.downloads_by_component)[0];
|
|
1734
|
+
if (topComponent) {
|
|
1735
|
+
const [componentName, downloadCount] = topComponent;
|
|
1736
|
+
popularElement.textContent = formatComponentNameForDisplay(componentName);
|
|
1737
|
+
popularElement.setAttribute('title', `${formatNumber(downloadCount)} downloads`);
|
|
1738
|
+
} else {
|
|
1739
|
+
popularElement.textContent = '-';
|
|
1740
|
+
}
|
|
1741
|
+
}
|
|
1742
|
+
|
|
1743
|
+
// Update last updated timestamp
|
|
1744
|
+
const lastUpdatedElement = document.getElementById('statsLastUpdated');
|
|
1745
|
+
if (lastUpdatedElement && data.last_updated) {
|
|
1746
|
+
const lastUpdated = new Date(data.last_updated);
|
|
1747
|
+
lastUpdatedElement.textContent = formatRelativeTime(lastUpdated);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// Show the statistics section
|
|
1751
|
+
showStatisticsSection();
|
|
1752
|
+
|
|
1753
|
+
console.log('📊 Download statistics loaded successfully');
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
/**
|
|
1757
|
+
* Hide statistics section when data is not available
|
|
1758
|
+
*/
|
|
1759
|
+
function hideStatisticsSection() {
|
|
1760
|
+
// Keep statistics section visible even when data is not available
|
|
1761
|
+
// const statsSection = document.getElementById('downloadStatsSection');
|
|
1762
|
+
// if (statsSection) {
|
|
1763
|
+
// statsSection.style.display = 'none';
|
|
1764
|
+
// }
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* Show statistics section when data is available
|
|
1769
|
+
* Note: Stats section has been moved to dedicated page at /download-stats.html
|
|
1770
|
+
*/
|
|
1771
|
+
function showStatisticsSection() {
|
|
1772
|
+
// Stats section removed from main page - no action needed
|
|
1773
|
+
console.log('Stats available at /download-stats.html');
|
|
1774
|
+
}
|
|
1775
|
+
|
|
1776
|
+
/**
|
|
1777
|
+
* Format numbers with thousands separators
|
|
1778
|
+
*/
|
|
1779
|
+
function formatNumber(num) {
|
|
1780
|
+
if (num === 0) return '0';
|
|
1781
|
+
if (num < 1000) return num.toString();
|
|
1782
|
+
if (num < 1000000) return (num / 1000).toFixed(1) + 'K';
|
|
1783
|
+
return (num / 1000000).toFixed(1) + 'M';
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
/**
|
|
1787
|
+
* Format component name for display (remove prefixes, capitalize)
|
|
1788
|
+
*/
|
|
1789
|
+
function formatComponentNameForDisplay(componentName) {
|
|
1790
|
+
if (!componentName || componentName === 'unknown') return '-';
|
|
1791
|
+
|
|
1792
|
+
// Handle template format (language/framework)
|
|
1793
|
+
if (componentName.includes('/')) {
|
|
1794
|
+
const parts = componentName.split('/');
|
|
1795
|
+
return parts.map(part =>
|
|
1796
|
+
part.replace(/-/g, ' ')
|
|
1797
|
+
.replace(/\b\w/g, l => l.toUpperCase())
|
|
1798
|
+
).join('/');
|
|
1799
|
+
}
|
|
1800
|
+
|
|
1801
|
+
// Handle individual components
|
|
1802
|
+
return componentName
|
|
1803
|
+
.replace(/-/g, ' ')
|
|
1804
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1807
|
+
/**
|
|
1808
|
+
* Format relative time (e.g., "2 hours ago")
|
|
1809
|
+
*/
|
|
1810
|
+
function formatRelativeTime(date) {
|
|
1811
|
+
const now = new Date();
|
|
1812
|
+
const diffMs = now - date;
|
|
1813
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
1814
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
1815
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
1816
|
+
|
|
1817
|
+
if (diffMins < 60) {
|
|
1818
|
+
return diffMins <= 1 ? 'just now' : `${diffMins} minutes ago`;
|
|
1819
|
+
} else if (diffHours < 24) {
|
|
1820
|
+
return diffHours === 1 ? '1 hour ago' : `${diffHours} hours ago`;
|
|
1821
|
+
} else if (diffDays < 7) {
|
|
1822
|
+
return diffDays === 1 ? '1 day ago' : `${diffDays} days ago`;
|
|
1823
|
+
} else {
|
|
1824
|
+
return date.toLocaleDateString('en-US', {
|
|
1825
|
+
month: 'short',
|
|
1826
|
+
day: 'numeric',
|
|
1827
|
+
year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
|
|
1832
|
+
/**
|
|
1833
|
+
* Refresh statistics data
|
|
1834
|
+
*/
|
|
1835
|
+
async function refreshStatistics() {
|
|
1836
|
+
const refreshButton = document.querySelector('.stats-refresh-btn');
|
|
1837
|
+
if (refreshButton) {
|
|
1838
|
+
refreshButton.textContent = 'Refreshing...';
|
|
1839
|
+
refreshButton.disabled = true;
|
|
1840
|
+
}
|
|
1841
|
+
|
|
1842
|
+
await loadDownloadStatistics();
|
|
1843
|
+
|
|
1844
|
+
if (refreshButton) {
|
|
1845
|
+
refreshButton.textContent = 'Refresh';
|
|
1846
|
+
refreshButton.disabled = false;
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
|
|
1850
|
+
// Auto-refresh statistics every 10 minutes
|
|
1851
|
+
setInterval(loadDownloadStatistics, 10 * 60 * 1000);
|
|
1852
|
+
|
|
1853
|
+
// Show detailed component modal
|
|
1854
|
+
function showComponentModal(component) {
|
|
1855
|
+
const typeConfig = {
|
|
1856
|
+
agent: { icon: '🤖', color: '#ff6b6b', label: 'AGENT' },
|
|
1857
|
+
command: { icon: '⚡', color: '#4ecdc4', label: 'COMMAND' },
|
|
1858
|
+
mcp: { icon: '🔌', color: '#45b7d1', label: 'MCP' }
|
|
1859
|
+
};
|
|
1860
|
+
|
|
1861
|
+
const config = typeConfig[component.type];
|
|
1862
|
+
const installCommand = generateInstallCommand(component);
|
|
1863
|
+
|
|
1864
|
+
const modalHTML = `
|
|
1865
|
+
<div class="modal-overlay" onclick="closeComponentModal()">
|
|
1866
|
+
<div class="modal-content component-modal" onclick="event.stopPropagation()">
|
|
1867
|
+
<div class="modal-header">
|
|
1868
|
+
<div class="component-modal-title">
|
|
1869
|
+
<span class="component-icon" style="color: ${config.color}">${config.icon}</span>
|
|
1870
|
+
<h3>${formatComponentName(component.name)}</h3>
|
|
1871
|
+
<span class="component-type-badge" style="background: ${config.color}">${config.label}</span>
|
|
1872
|
+
</div>
|
|
1873
|
+
<button class="modal-close" onclick="closeComponentModal()">×</button>
|
|
1874
|
+
</div>
|
|
1875
|
+
<div class="modal-body">
|
|
1876
|
+
<div class="component-details">
|
|
1877
|
+
<div class="component-description">
|
|
1878
|
+
${getComponentDescription(component)}
|
|
1879
|
+
</div>
|
|
1880
|
+
|
|
1881
|
+
<div class="installation-section">
|
|
1882
|
+
<h4>📦 Installation</h4>
|
|
1883
|
+
<div class="command-line">
|
|
1884
|
+
<code>${installCommand}</code>
|
|
1885
|
+
<button class="copy-btn" onclick="copyToClipboard('${installCommand}')">Copy</button>
|
|
1886
|
+
</div>
|
|
1887
|
+
</div>
|
|
1888
|
+
|
|
1889
|
+
<div class="component-content">
|
|
1890
|
+
<h4>📋 Component Details</h4>
|
|
1891
|
+
<div class="component-preview">
|
|
1892
|
+
<pre><code>${component.content ? component.content.substring(0, 500) : 'No content available'}${component.content && component.content.length > 500 ? '...' : ''}</code></pre>
|
|
1893
|
+
</div>
|
|
1894
|
+
</div>
|
|
1895
|
+
|
|
1896
|
+
<div class="modal-actions">
|
|
1897
|
+
<a href="${component.url}" target="_blank" class="github-folder-link">
|
|
1898
|
+
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor">
|
|
1899
|
+
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.30.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z"/>
|
|
1900
|
+
</svg>
|
|
1901
|
+
View on GitHub
|
|
1902
|
+
</a>
|
|
1903
|
+
</div>
|
|
1904
|
+
</div>
|
|
1905
|
+
</div>
|
|
1906
|
+
</div>
|
|
1907
|
+
</div>
|
|
1908
|
+
`;
|
|
1909
|
+
|
|
1910
|
+
// Remove existing modal if present
|
|
1911
|
+
const existingModal = document.querySelector('.modal-overlay');
|
|
1912
|
+
if (existingModal) {
|
|
1913
|
+
existingModal.remove();
|
|
1914
|
+
}
|
|
1915
|
+
|
|
1916
|
+
// Add modal to body
|
|
1917
|
+
document.body.insertAdjacentHTML('beforeend', modalHTML);
|
|
1918
|
+
|
|
1919
|
+
// Add event listener for ESC key
|
|
1920
|
+
const handleEscape = (e) => {
|
|
1921
|
+
if (e.key === 'Escape') {
|
|
1922
|
+
closeComponentModal();
|
|
1923
|
+
document.removeEventListener('keydown', handleEscape);
|
|
1924
|
+
}
|
|
1925
|
+
};
|
|
1926
|
+
document.addEventListener('keydown', handleEscape);
|
|
1927
|
+
}
|
|
1928
|
+
|
|
1929
|
+
// ===== ANALYTICS AND STATISTICS FUNCTIONALITY =====
|
|
1930
|
+
|
|
1931
|
+
/**
|
|
1932
|
+
* Load and display download statistics from GitHub-generated analytics
|
|
1933
|
+
*/
|
|
1934
|
+
async function loadDownloadStatistics() {
|
|
1935
|
+
try {
|
|
1936
|
+
// Fetch analytics data generated by GitHub Actions
|
|
1937
|
+
const response = await fetch('analytics/download-stats.json?t=' + Date.now());
|
|
1938
|
+
|
|
1939
|
+
if (!response.ok) {
|
|
1940
|
+
console.log('Analytics data not available yet');
|
|
1941
|
+
hideStatisticsSection();
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
const analyticsData = await response.json();
|
|
1946
|
+
displayDownloadStatistics(analyticsData);
|
|
1947
|
+
|
|
1948
|
+
} catch (error) {
|
|
1949
|
+
console.log('Analytics data not available:', error.message);
|
|
1950
|
+
hideStatisticsSection();
|
|
1951
|
+
}
|
|
1952
|
+
}
|
|
1953
|
+
|
|
1954
|
+
/**
|
|
1955
|
+
* Display download statistics in the UI
|
|
1956
|
+
*/
|
|
1957
|
+
function displayDownloadStatistics(data) {
|
|
1958
|
+
// Update total downloads
|
|
1959
|
+
// Store download stats globally for use in cards
|
|
1960
|
+
downloadStats = data;
|
|
1961
|
+
const totalElement = document.getElementById('totalDownloads');
|
|
1962
|
+
if (totalElement) {
|
|
1963
|
+
totalElement.textContent = formatNumber(data.total_downloads || 0);
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
// Update individual component type counts
|
|
1967
|
+
const typeElements = {
|
|
1968
|
+
agentDownloads: data.downloads_by_type?.agent || 0,
|
|
1969
|
+
commandDownloads: data.downloads_by_type?.command || 0,
|
|
1970
|
+
mcpDownloads: data.downloads_by_type?.mcp || 0,
|
|
1971
|
+
templateDownloads: data.downloads_by_type?.template || 0
|
|
1972
|
+
};
|
|
1973
|
+
|
|
1974
|
+
Object.entries(typeElements).forEach(([elementId, count]) => {
|
|
1975
|
+
const element = document.getElementById(elementId);
|
|
1976
|
+
if (element) {
|
|
1977
|
+
element.textContent = formatNumber(count);
|
|
1978
|
+
}
|
|
1979
|
+
});
|
|
1980
|
+
|
|
1981
|
+
// Find and display most popular component
|
|
1982
|
+
const popularElement = document.getElementById('popularComponent');
|
|
1983
|
+
if (popularElement && data.downloads_by_component) {
|
|
1984
|
+
const topComponent = Object.entries(data.downloads_by_component)[0];
|
|
1985
|
+
if (topComponent) {
|
|
1986
|
+
const [componentName, downloadCount] = topComponent;
|
|
1987
|
+
popularElement.textContent = formatComponentNameForDisplay(componentName);
|
|
1988
|
+
popularElement.setAttribute('title', `${formatNumber(downloadCount)} downloads`);
|
|
1989
|
+
} else {
|
|
1990
|
+
popularElement.textContent = '-';
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
|
|
1994
|
+
// Update last updated timestamp
|
|
1995
|
+
const lastUpdatedElement = document.getElementById('statsLastUpdated');
|
|
1996
|
+
if (lastUpdatedElement && data.last_updated) {
|
|
1997
|
+
const lastUpdated = new Date(data.last_updated);
|
|
1998
|
+
lastUpdatedElement.textContent = formatRelativeTime(lastUpdated);
|
|
1999
|
+
}
|
|
2000
|
+
|
|
2001
|
+
// Show the statistics section
|
|
2002
|
+
showStatisticsSection();
|
|
2003
|
+
|
|
2004
|
+
// Regenerate cards with download counts
|
|
2005
|
+
if (currentFilter === 'templates' && templatesData) {
|
|
2006
|
+
generateTemplateCards();
|
|
2007
|
+
} else if (allDataLoaded) {
|
|
2008
|
+
generateUnifiedComponentCards();
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
console.log('📊 Download statistics loaded successfully');
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
/**
|
|
2015
|
+
* Hide statistics section when data is not available
|
|
2016
|
+
*/
|
|
2017
|
+
function hideStatisticsSection() {
|
|
2018
|
+
// Keep statistics section visible even when data is not available
|
|
2019
|
+
// const statsSection = document.getElementById('downloadStatsSection');
|
|
2020
|
+
// if (statsSection) {
|
|
2021
|
+
// statsSection.style.display = 'none';
|
|
2022
|
+
// }
|
|
2023
|
+
}
|
|
2024
|
+
|
|
2025
|
+
/**
|
|
2026
|
+
* Show statistics section when data is available
|
|
2027
|
+
* Note: Stats section has been moved to dedicated page at /download-stats.html
|
|
2028
|
+
*/
|
|
2029
|
+
function showStatisticsSection() {
|
|
2030
|
+
// Stats section removed from main page - no action needed
|
|
2031
|
+
console.log('Stats available at /download-stats.html');
|
|
2032
|
+
}
|
|
2033
|
+
|
|
2034
|
+
/**
|
|
2035
|
+
* Format numbers with thousands separators
|
|
2036
|
+
*/
|
|
2037
|
+
function formatNumber(num) {
|
|
2038
|
+
if (num === 0) return '0';
|
|
2039
|
+
if (num < 1000) return num.toString();
|
|
2040
|
+
if (num < 1000000) return (num / 1000).toFixed(1) + 'K';
|
|
2041
|
+
return (num / 1000000).toFixed(1) + 'M';
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
/**
|
|
2045
|
+
* Format component name for display (remove prefixes, capitalize)
|
|
2046
|
+
*/
|
|
2047
|
+
function formatComponentNameForDisplay(componentName) {
|
|
2048
|
+
if (!componentName || componentName === 'unknown') return '-';
|
|
2049
|
+
|
|
2050
|
+
// Handle template format (language/framework)
|
|
2051
|
+
if (componentName.includes('/')) {
|
|
2052
|
+
const parts = componentName.split('/');
|
|
2053
|
+
return parts.map(part =>
|
|
2054
|
+
part.replace(/-/g, ' ')
|
|
2055
|
+
.replace(/\b\w/g, l => l.toUpperCase())
|
|
2056
|
+
).join('/');
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
// Handle individual components
|
|
2060
|
+
return componentName
|
|
2061
|
+
.replace(/-/g, ' ')
|
|
2062
|
+
.replace(/\b\w/g, l => l.toUpperCase());
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
/**
|
|
2066
|
+
* Format relative time (e.g., "2 hours ago")
|
|
2067
|
+
*/
|
|
2068
|
+
function formatRelativeTime(date) {
|
|
2069
|
+
const now = new Date();
|
|
2070
|
+
const diffMs = now - date;
|
|
2071
|
+
const diffMins = Math.floor(diffMs / (1000 * 60));
|
|
2072
|
+
const diffHours = Math.floor(diffMs / (1000 * 60 * 60));
|
|
2073
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
2074
|
+
|
|
2075
|
+
if (diffMins < 60) {
|
|
2076
|
+
return diffMins <= 1 ? 'just now' : `${diffMins} minutes ago`;
|
|
2077
|
+
} else if (diffHours < 24) {
|
|
2078
|
+
return diffHours === 1 ? '1 hour ago' : `${diffHours} hours ago`;
|
|
2079
|
+
} else if (diffDays < 7) {
|
|
2080
|
+
return diffDays === 1 ? '1 day ago' : `${diffDays} days ago`;
|
|
2081
|
+
} else {
|
|
2082
|
+
return date.toLocaleDateString('en-US', {
|
|
2083
|
+
month: 'short',
|
|
2084
|
+
day: 'numeric',
|
|
2085
|
+
year: date.getFullYear() !== now.getFullYear() ? 'numeric' : undefined
|
|
2086
|
+
});
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
/**
|
|
2091
|
+
* Refresh statistics data
|
|
2092
|
+
*/
|
|
2093
|
+
async function refreshStatistics() {
|
|
2094
|
+
const refreshButton = document.querySelector('.stats-refresh-btn');
|
|
2095
|
+
if (refreshButton) {
|
|
2096
|
+
refreshButton.textContent = 'Refreshing...';
|
|
2097
|
+
refreshButton.disabled = true;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
await loadDownloadStatistics();
|
|
2101
|
+
|
|
2102
|
+
if (refreshButton) {
|
|
2103
|
+
refreshButton.textContent = 'Refresh';
|
|
2104
|
+
refreshButton.disabled = false;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
// Auto-refresh statistics every 10 minutes
|
|
2109
|
+
setInterval(loadDownloadStatistics, 10 * 60 * 1000);
|
|
2110
|
+
|
|
2111
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
2112
|
+
const modal = document.getElementById('componentModal');
|
|
2113
|
+
const closeBtn = document.getElementById('closeComponentModal');
|
|
2114
|
+
const closeBtnFooter = document.getElementById('closeComponentModalBtn');
|
|
2115
|
+
|
|
2116
|
+
if (modal && closeBtn && closeBtnFooter) {
|
|
2117
|
+
const closeModal = () => {
|
|
2118
|
+
modal.style.display = 'none';
|
|
2119
|
+
};
|
|
2120
|
+
|
|
2121
|
+
closeBtn.addEventListener('click', closeModal);
|
|
2122
|
+
closeBtnFooter.addEventListener('click', closeModal);
|
|
2123
|
+
|
|
2124
|
+
window.addEventListener('click', (event) => {
|
|
2125
|
+
if (event.target === modal) {
|
|
2126
|
+
closeComponentModal();
|
|
2127
|
+
}
|
|
2128
|
+
});
|
|
2129
|
+
|
|
2130
|
+
document.addEventListener('keydown', (event) => {
|
|
2131
|
+
if (event.key === 'Escape') {
|
|
2132
|
+
closeComponentModal();
|
|
2133
|
+
}
|
|
2134
|
+
});
|
|
2135
|
+
}
|
|
2136
|
+
});
|
|
2137
|
+
|
|
2138
|
+
/**
|
|
2139
|
+
* Get download count for a specific component
|
|
2140
|
+
*/
|
|
2141
|
+
function getDownloadCount(componentName, componentType) {
|
|
2142
|
+
if (!downloadStats || !downloadStats.downloads_by_component) {
|
|
2143
|
+
return 0;
|
|
2144
|
+
}
|
|
2145
|
+
|
|
2146
|
+
// For templates, the name format is "language/framework"
|
|
2147
|
+
if (componentType === 'template') {
|
|
2148
|
+
return downloadStats.downloads_by_component[componentName] || 0;
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
// For individual components (agents, commands, mcps)
|
|
2152
|
+
return downloadStats.downloads_by_component[componentName] || 0;
|
|
2153
|
+
}
|
|
2154
|
+
|
|
2155
|
+
/**
|
|
2156
|
+
* Create download count badge HTML
|
|
2157
|
+
*/
|
|
2158
|
+
function createDownloadBadge(count) {
|
|
2159
|
+
if (count === 0) return '';
|
|
2160
|
+
|
|
2161
|
+
return `<div class="download-badge" title="${count} downloads">
|
|
2162
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="currentColor">
|
|
2163
|
+
<path d="M5 20h14v-2H5v2zM19 9h-4V3H9v6H5l7 7 7-7z"/>
|
|
2164
|
+
</svg>
|
|
2165
|
+
${formatNumber(count)}
|
|
2166
|
+
</div>`;
|
|
2167
|
+
}
|