claudeinone-cli 1.0.2 → 1.0.3
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/kit/.claude/.ck.json +9 -0
- package/kit/.claude/.ckignore +12 -0
- package/kit/.claude/agents/accessibility-auditor.md +46 -0
- package/kit/.claude/agents/api-designer.md +43 -0
- package/kit/.claude/agents/backend-developer.md +54 -0
- package/kit/.claude/agents/brainstormer.md +33 -0
- package/kit/.claude/agents/campaign-manager.md +36 -0
- package/kit/.claude/agents/code-reviewer.md +39 -0
- package/kit/.claude/agents/content-creator.md +38 -0
- package/kit/.claude/agents/copywriter.md +42 -0
- package/kit/.claude/agents/database-admin.md +37 -0
- package/kit/.claude/agents/debugger.md +46 -0
- package/kit/.claude/agents/devops-engineer.md +41 -0
- package/kit/.claude/agents/docs-manager.md +33 -0
- package/kit/.claude/agents/email-wizard.md +40 -0
- package/kit/.claude/agents/frontend-developer.md +52 -0
- package/kit/.claude/agents/fullstack-developer.md +55 -0
- package/kit/.claude/agents/git-manager.md +40 -0
- package/kit/.claude/agents/i18n-specialist.md +46 -0
- package/kit/.claude/agents/integration-specialist.md +48 -0
- package/kit/.claude/agents/journal-writer.md +39 -0
- package/kit/.claude/agents/mcp-manager.md +57 -0
- package/kit/.claude/agents/mobile-developer.md +38 -0
- package/kit/.claude/agents/performance-optimizer.md +38 -0
- package/kit/.claude/agents/planner.md +56 -0
- package/kit/.claude/agents/project-manager.md +34 -0
- package/kit/.claude/agents/refactorer.md +43 -0
- package/kit/.claude/agents/researcher.md +45 -0
- package/kit/.claude/agents/risk-analyst.md +33 -0
- package/kit/.claude/agents/scalability-consultant.md +39 -0
- package/kit/.claude/agents/scout.md +25 -0
- package/kit/.claude/agents/security-auditor.md +42 -0
- package/kit/.claude/agents/seo-specialist.md +44 -0
- package/kit/.claude/agents/skill-creator.md +64 -0
- package/kit/.claude/agents/social-media-manager.md +35 -0
- package/kit/.claude/agents/systems-designer.md +35 -0
- package/kit/.claude/agents/technology-strategist.md +43 -0
- package/kit/.claude/agents/tester.md +40 -0
- package/kit/.claude/agents/ui-ux-designer.md +40 -0
- package/kit/.claude/commands/co/ask.md +29 -0
- package/kit/.claude/commands/co/bootstrap-auto-fast.md +28 -0
- package/kit/.claude/commands/co/bootstrap-auto-parallel.md +29 -0
- package/kit/.claude/commands/co/bootstrap-auto.md +30 -0
- package/kit/.claude/commands/co/bootstrap.md +31 -0
- package/kit/.claude/commands/co/brainstorm.md +27 -0
- package/kit/.claude/commands/co/campaign.md +28 -0
- package/kit/.claude/commands/co/changelog.md +25 -0
- package/kit/.claude/commands/co/checkpoint.md +25 -0
- package/kit/.claude/commands/co/ci.md +26 -0
- package/kit/.claude/commands/co/ck-help.md +24 -0
- package/kit/.claude/commands/co/coding-level.md +24 -0
- package/kit/.claude/commands/co/content-cro.md +26 -0
- package/kit/.claude/commands/co/content-enhance.md +26 -0
- package/kit/.claude/commands/co/content-fast.md +24 -0
- package/kit/.claude/commands/co/content-good.md +26 -0
- package/kit/.claude/commands/co/cook.md +33 -0
- package/kit/.claude/commands/co/debug.md +26 -0
- package/kit/.claude/commands/co/deploy.md +25 -0
- package/kit/.claude/commands/co/design-3d.md +27 -0
- package/kit/.claude/commands/co/design-describe.md +25 -0
- package/kit/.claude/commands/co/design-fast.md +25 -0
- package/kit/.claude/commands/co/design-good.md +28 -0
- package/kit/.claude/commands/co/design-screenshot.md +26 -0
- package/kit/.claude/commands/co/design-video.md +26 -0
- package/kit/.claude/commands/co/docker.md +24 -0
- package/kit/.claude/commands/co/docs-api.md +25 -0
- package/kit/.claude/commands/co/docs-init.md +26 -0
- package/kit/.claude/commands/co/docs-readme.md +24 -0
- package/kit/.claude/commands/co/docs-summarize.md +25 -0
- package/kit/.claude/commands/co/docs-update.md +25 -0
- package/kit/.claude/commands/co/env-check.md +25 -0
- package/kit/.claude/commands/co/fix-ci.md +29 -0
- package/kit/.claude/commands/co/fix-fast.md +28 -0
- package/kit/.claude/commands/co/fix-hard.md +33 -0
- package/kit/.claude/commands/co/fix-logs.md +28 -0
- package/kit/.claude/commands/co/fix-types.md +28 -0
- package/kit/.claude/commands/co/fix-ui.md +28 -0
- package/kit/.claude/commands/co/fix.md +27 -0
- package/kit/.claude/commands/co/git-cm.md +26 -0
- package/kit/.claude/commands/co/git-cp.md +26 -0
- package/kit/.claude/commands/co/git-pr.md +26 -0
- package/kit/.claude/commands/co/index.md +24 -0
- package/kit/.claude/commands/co/integrate-polar.md +29 -0
- package/kit/.claude/commands/co/integrate-sepay.md +29 -0
- package/kit/.claude/commands/co/journal.md +27 -0
- package/kit/.claude/commands/co/k8s.md +24 -0
- package/kit/.claude/commands/co/kanban.md +25 -0
- package/kit/.claude/commands/co/lint-fix.md +24 -0
- package/kit/.claude/commands/co/load.md +25 -0
- package/kit/.claude/commands/co/migrate.md +28 -0
- package/kit/.claude/commands/co/mock.md +26 -0
- package/kit/.claude/commands/co/mode.md +24 -0
- package/kit/.claude/commands/co/monitor.md +25 -0
- package/kit/.claude/commands/co/new-feature.md +27 -0
- package/kit/.claude/commands/co/optimize.md +26 -0
- package/kit/.claude/commands/co/plan-archive.md +24 -0
- package/kit/.claude/commands/co/plan-ci.md +28 -0
- package/kit/.claude/commands/co/plan-cro.md +27 -0
- package/kit/.claude/commands/co/plan-fast.md +24 -0
- package/kit/.claude/commands/co/plan-hard.md +27 -0
- package/kit/.claude/commands/co/plan-parallel.md +25 -0
- package/kit/.claude/commands/co/plan-two.md +29 -0
- package/kit/.claude/commands/co/plan-validate.md +27 -0
- package/kit/.claude/commands/co/plan.md +27 -0
- package/kit/.claude/commands/co/pr.md +25 -0
- package/kit/.claude/commands/co/preview.md +26 -0
- package/kit/.claude/commands/co/refactor.md +25 -0
- package/kit/.claude/commands/co/release.md +25 -0
- package/kit/.claude/commands/co/review-a11y.md +24 -0
- package/kit/.claude/commands/co/review-codebase-parallel.md +27 -0
- package/kit/.claude/commands/co/review-codebase.md +27 -0
- package/kit/.claude/commands/co/review-perf.md +24 -0
- package/kit/.claude/commands/co/review-security.md +25 -0
- package/kit/.claude/commands/co/scaffold.md +25 -0
- package/kit/.claude/commands/co/scout.md +26 -0
- package/kit/.claude/commands/co/secure.md +26 -0
- package/kit/.claude/commands/co/seed.md +25 -0
- package/kit/.claude/commands/co/seo-audit.md +24 -0
- package/kit/.claude/commands/co/seo-keywords.md +25 -0
- package/kit/.claude/commands/co/skill-create.md +29 -0
- package/kit/.claude/commands/co/skill-fix-logs.md +28 -0
- package/kit/.claude/commands/co/slide-create.md +24 -0
- package/kit/.claude/commands/co/spawn.md +24 -0
- package/kit/.claude/commands/co/terraform.md +24 -0
- package/kit/.claude/commands/co/test-gen.md +24 -0
- package/kit/.claude/commands/co/test-ui.md +27 -0
- package/kit/.claude/commands/co/test.md +26 -0
- package/kit/.claude/commands/co/use-mcp.md +25 -0
- package/kit/.claude/commands/co/video-script.md +25 -0
- package/kit/.claude/commands/co/watzup.md +25 -0
- package/kit/.claude/commands/co/worktree.md +25 -0
- package/kit/.claude/commands/co/write-blog.md +25 -0
- package/kit/.claude/commands/co/write-copy.md +24 -0
- package/kit/.claude/commands/co/write-email.md +25 -0
- package/kit/.claude/commands/content/content-cro.md +26 -0
- package/kit/.claude/commands/content/content-enhance.md +26 -0
- package/kit/.claude/commands/content/content-fast.md +24 -0
- package/kit/.claude/commands/content/content-good.md +26 -0
- package/kit/.claude/commands/content/enhance.md +26 -0
- package/kit/.claude/commands/content/good.md +26 -0
- package/kit/.claude/commands/core/ask.md +29 -0
- package/kit/.claude/commands/core/bootstrap-auto-fast.md +28 -0
- package/kit/.claude/commands/core/bootstrap-auto-parallel.md +29 -0
- package/kit/.claude/commands/core/bootstrap-auto.md +30 -0
- package/kit/.claude/commands/core/bootstrap.md +31 -0
- package/kit/.claude/commands/core/ck-help.md +24 -0
- package/kit/.claude/commands/core/coding-level.md +24 -0
- package/kit/.claude/commands/core/cook.md +33 -0
- package/kit/.claude/commands/core/debug.md +26 -0
- package/kit/.claude/commands/core/journal.md +27 -0
- package/kit/.claude/commands/core/kanban.md +25 -0
- package/kit/.claude/commands/core/preview.md +26 -0
- package/kit/.claude/commands/core/scout.md +26 -0
- package/kit/.claude/commands/core/test-ui.md +27 -0
- package/kit/.claude/commands/core/test.md +26 -0
- package/kit/.claude/commands/core/use-mcp.md +25 -0
- package/kit/.claude/commands/core/watzup.md +25 -0
- package/kit/.claude/commands/core/worktree.md +25 -0
- package/kit/.claude/commands/design/3d.md +27 -0
- package/kit/.claude/commands/design/design-3d.md +27 -0
- package/kit/.claude/commands/design/design-describe.md +25 -0
- package/kit/.claude/commands/design/design-fast.md +25 -0
- package/kit/.claude/commands/design/design-good.md +28 -0
- package/kit/.claude/commands/design/design-screenshot.md +26 -0
- package/kit/.claude/commands/design/design-video.md +26 -0
- package/kit/.claude/commands/design/good.md +28 -0
- package/kit/.claude/commands/design/video.md +26 -0
- package/kit/.claude/commands/docs/docs-init.md +26 -0
- package/kit/.claude/commands/docs/docs-summarize.md +25 -0
- package/kit/.claude/commands/docs/docs-update.md +25 -0
- package/kit/.claude/commands/docs/init.md +26 -0
- package/kit/.claude/commands/docs/summarize.md +25 -0
- package/kit/.claude/commands/fix/ci.md +29 -0
- package/kit/.claude/commands/fix/fast.md +28 -0
- package/kit/.claude/commands/fix/fix-ci.md +29 -0
- package/kit/.claude/commands/fix/fix-fast.md +28 -0
- package/kit/.claude/commands/fix/fix-hard.md +33 -0
- package/kit/.claude/commands/fix/fix-logs.md +28 -0
- package/kit/.claude/commands/fix/fix-types.md +28 -0
- package/kit/.claude/commands/fix/fix-ui.md +28 -0
- package/kit/.claude/commands/fix/hard.md +33 -0
- package/kit/.claude/commands/fix/logs.md +28 -0
- package/kit/.claude/commands/fix/types.md +28 -0
- package/kit/.claude/commands/fix/ui.md +28 -0
- package/kit/.claude/commands/git/cp.md +26 -0
- package/kit/.claude/commands/git/git-cm.md +26 -0
- package/kit/.claude/commands/git/git-cp.md +26 -0
- package/kit/.claude/commands/git/git-pr.md +26 -0
- package/kit/.claude/commands/integrate/integrate-polar.md +29 -0
- package/kit/.claude/commands/integrate/integrate-sepay.md +29 -0
- package/kit/.claude/commands/integrate/sepay.md +29 -0
- package/kit/.claude/commands/plan/ci.md +28 -0
- package/kit/.claude/commands/plan/cro.md +27 -0
- package/kit/.claude/commands/plan/hard.md +27 -0
- package/kit/.claude/commands/plan/plan-archive.md +24 -0
- package/kit/.claude/commands/plan/plan-ci.md +28 -0
- package/kit/.claude/commands/plan/plan-cro.md +27 -0
- package/kit/.claude/commands/plan/plan-fast.md +24 -0
- package/kit/.claude/commands/plan/plan-hard.md +27 -0
- package/kit/.claude/commands/plan/plan-parallel.md +25 -0
- package/kit/.claude/commands/plan/plan-two.md +29 -0
- package/kit/.claude/commands/plan/plan-validate.md +27 -0
- package/kit/.claude/commands/plan/plan.md +27 -0
- package/kit/.claude/commands/plan/validate.md +27 -0
- package/kit/.claude/commands/skill/fix-logs.md +28 -0
- package/kit/.claude/commands/skill/skill-create.md +29 -0
- package/kit/.claude/commands/skill/skill-fix-logs.md +28 -0
- package/kit/.claude/settings.json +16 -0
- package/kit/.claude/skills/ai-anthropic.md +100 -0
- package/kit/.claude/skills/ai-context-engineering.md +113 -0
- package/kit/.claude/skills/ai-gemini.md +152 -0
- package/kit/.claude/skills/ai-langchain.md +93 -0
- package/kit/.claude/skills/ai-llamaindex.md +179 -0
- package/kit/.claude/skills/ai-mcp-builder.md +101 -0
- package/kit/.claude/skills/ai-openai.md +250 -0
- package/kit/.claude/skills/ai-prompt-engineering.md +173 -0
- package/kit/.claude/skills/ai-rag.md +91 -0
- package/kit/.claude/skills/ai-vectordb.md +215 -0
- package/kit/.claude/skills/analytics-segment.md +161 -0
- package/kit/.claude/skills/api-caching.md +103 -0
- package/kit/.claude/skills/api-documentation.md +50 -0
- package/kit/.claude/skills/api-graphql.md +234 -0
- package/kit/.claude/skills/api-openapi.md +116 -0
- package/kit/.claude/skills/api-pagination-filtering.md +239 -0
- package/kit/.claude/skills/api-rate-limiting.md +179 -0
- package/kit/.claude/skills/api-rest-advanced.md +50 -0
- package/kit/.claude/skills/api-rest.md +217 -0
- package/kit/.claude/skills/api-trpc.md +173 -0
- package/kit/.claude/skills/api-versioning.md +70 -0
- package/kit/.claude/skills/api-webhooks.md +226 -0
- package/kit/.claude/skills/arch-clean-code.md +226 -0
- package/kit/.claude/skills/arch-clean.md +91 -0
- package/kit/.claude/skills/arch-cqrs.md +229 -0
- package/kit/.claude/skills/arch-ddd.md +85 -0
- package/kit/.claude/skills/arch-event-driven.md +189 -0
- package/kit/.claude/skills/arch-microservices.md +80 -0
- package/kit/.claude/skills/arch-monorepo.md +87 -0
- package/kit/.claude/skills/arch-multi-tenant.md +81 -0
- package/kit/.claude/skills/arch-serverless.md +86 -0
- package/kit/.claude/skills/auth-clerk.md +97 -0
- package/kit/.claude/skills/auth-jwt.md +143 -0
- package/kit/.claude/skills/auth-lucia.md +93 -0
- package/kit/.claude/skills/auth-nextauth.md +446 -0
- package/kit/.claude/skills/auth-oauth.md +208 -0
- package/kit/.claude/skills/auth-oauth2.md +110 -0
- package/kit/.claude/skills/auth-passkeys.md +109 -0
- package/kit/.claude/skills/auth-session.md +88 -0
- package/kit/.claude/skills/backend-dotnet.md +414 -0
- package/kit/.claude/skills/backend-express.md +129 -0
- package/kit/.claude/skills/backend-fastify.md +104 -0
- package/kit/.claude/skills/backend-go.md +205 -0
- package/kit/.claude/skills/backend-graphql.md +149 -0
- package/kit/.claude/skills/backend-grpc.md +382 -0
- package/kit/.claude/skills/backend-hono.md +95 -0
- package/kit/.claude/skills/backend-java-spring.md +198 -0
- package/kit/.claude/skills/backend-nodejs-express.md +165 -0
- package/kit/.claude/skills/backend-nodejs.md +143 -0
- package/kit/.claude/skills/backend-php-laravel.md +156 -0
- package/kit/.claude/skills/backend-python-django.md +200 -0
- package/kit/.claude/skills/backend-python-fastapi.md +169 -0
- package/kit/.claude/skills/backend-ruby-rails.md +190 -0
- package/kit/.claude/skills/backend-rust.md +182 -0
- package/kit/.claude/skills/backend-websockets.md +392 -0
- package/kit/.claude/skills/cache-redis.md +195 -0
- package/kit/.claude/skills/caching-strategies.md +100 -0
- package/kit/.claude/skills/cloud-aws.md +165 -0
- package/kit/.claude/skills/cloud-azure.md +187 -0
- package/kit/.claude/skills/cloud-cloudflare.md +74 -0
- package/kit/.claude/skills/cloud-fly.md +94 -0
- package/kit/.claude/skills/cloud-gcp.md +160 -0
- package/kit/.claude/skills/cloud-railway.md +92 -0
- package/kit/.claude/skills/cloud-render.md +70 -0
- package/kit/.claude/skills/cloud-serverless.md +68 -0
- package/kit/.claude/skills/cloud-vercel.md +76 -0
- package/kit/.claude/skills/component-patterns.md +50 -0
- package/kit/.claude/skills/content-management.md +197 -0
- package/kit/.claude/skills/cors-security.md +50 -0
- package/kit/.claude/skills/data-csv-excel.md +210 -0
- package/kit/.claude/skills/database-optimization.md +196 -0
- package/kit/.claude/skills/databases-transactions.md +68 -0
- package/kit/.claude/skills/db-cassandra.md +89 -0
- package/kit/.claude/skills/db-drizzle.md +363 -0
- package/kit/.claude/skills/db-dynamodb.md +83 -0
- package/kit/.claude/skills/db-elasticsearch.md +105 -0
- package/kit/.claude/skills/db-firebase-firestore.md +191 -0
- package/kit/.claude/skills/db-mongodb.md +198 -0
- package/kit/.claude/skills/db-mysql.md +50 -0
- package/kit/.claude/skills/db-neon.md +72 -0
- package/kit/.claude/skills/db-planetscale.md +76 -0
- package/kit/.claude/skills/db-postgresql.md +50 -0
- package/kit/.claude/skills/db-prisma.md +414 -0
- package/kit/.claude/skills/db-redis.md +50 -0
- package/kit/.claude/skills/db-sqlite.md +149 -0
- package/kit/.claude/skills/db-supabase.md +445 -0
- package/kit/.claude/skills/devops-ci-cd.md +271 -0
- package/kit/.claude/skills/devops-database-backup.md +77 -0
- package/kit/.claude/skills/devops-docker.md +93 -0
- package/kit/.claude/skills/devops-github-actions.md +82 -0
- package/kit/.claude/skills/devops-health-checks.md +50 -0
- package/kit/.claude/skills/devops-kubernetes.md +109 -0
- package/kit/.claude/skills/devops-logging.md +163 -0
- package/kit/.claude/skills/devops-monitoring.md +203 -0
- package/kit/.claude/skills/devops-pulumi.md +94 -0
- package/kit/.claude/skills/devops-secrets.md +166 -0
- package/kit/.claude/skills/devops-terraform.md +226 -0
- package/kit/.claude/skills/error-boundaries.md +84 -0
- package/kit/.claude/skills/file-storage.md +50 -0
- package/kit/.claude/skills/frontend-angular.md +104 -0
- package/kit/.claude/skills/frontend-astro.md +94 -0
- package/kit/.claude/skills/frontend-bundle-analysis.md +147 -0
- package/kit/.claude/skills/frontend-forms.md +134 -0
- package/kit/.claude/skills/frontend-htmx.md +86 -0
- package/kit/.claude/skills/frontend-nextjs.md +188 -0
- package/kit/.claude/skills/frontend-pwa.md +105 -0
- package/kit/.claude/skills/frontend-react-hooks.md +238 -0
- package/kit/.claude/skills/frontend-react.md +129 -0
- package/kit/.claude/skills/frontend-remix-advanced.md +106 -0
- package/kit/.claude/skills/frontend-remix.md +101 -0
- package/kit/.claude/skills/frontend-solid.md +99 -0
- package/kit/.claude/skills/frontend-state-management.md +134 -0
- package/kit/.claude/skills/frontend-state.md +106 -0
- package/kit/.claude/skills/frontend-svelte.md +121 -0
- package/kit/.claude/skills/frontend-testing.md +100 -0
- package/kit/.claude/skills/frontend-vite.md +94 -0
- package/kit/.claude/skills/frontend-vue.md +133 -0
- package/kit/.claude/skills/frontend-webpack.md +93 -0
- package/kit/.claude/skills/functional-programming.md +50 -0
- package/kit/.claude/skills/hooks-custom.md +50 -0
- package/kit/.claude/skills/http-server.md +50 -0
- package/kit/.claude/skills/i18n-general.md +89 -0
- package/kit/.claude/skills/i18n-localization.md +191 -0
- package/kit/.claude/skills/i18n-nextjs.md +127 -0
- package/kit/.claude/skills/infrastructure-docker-compose.md +77 -0
- package/kit/.claude/skills/infrastructure-serverless.md +177 -0
- package/kit/.claude/skills/jwt-tokens.md +50 -0
- package/kit/.claude/skills/logging-winston.md +106 -0
- package/kit/.claude/skills/messaging-kafka.md +102 -0
- package/kit/.claude/skills/messaging-rabbitmq.md +50 -0
- package/kit/.claude/skills/mobile-capacitor.md +109 -0
- package/kit/.claude/skills/mobile-expo.md +101 -0
- package/kit/.claude/skills/mobile-flutter.md +259 -0
- package/kit/.claude/skills/mobile-react-native.md +238 -0
- package/kit/.claude/skills/monitoring-apm.md +50 -0
- package/kit/.claude/skills/monitoring-error-tracking.md +217 -0
- package/kit/.claude/skills/nodejs-streams.md +168 -0
- package/kit/.claude/skills/oauth-integration.md +50 -0
- package/kit/.claude/skills/patterns-dependency-injection.md +218 -0
- package/kit/.claude/skills/patterns-factory-singleton.md +209 -0
- package/kit/.claude/skills/patterns-observer-pubsub.md +210 -0
- package/kit/.claude/skills/payment-lemonsqueezy.md +101 -0
- package/kit/.claude/skills/payment-square.md +178 -0
- package/kit/.claude/skills/payment-stripe.md +206 -0
- package/kit/.claude/skills/perf-bundle.md +100 -0
- package/kit/.claude/skills/perf-web-vitals.md +102 -0
- package/kit/.claude/skills/performance-database-connection-pooling.md +67 -0
- package/kit/.claude/skills/performance-metrics.md +73 -0
- package/kit/.claude/skills/performance-optimization.md +208 -0
- package/kit/.claude/skills/performance-web-vitals.md +169 -0
- package/kit/.claude/skills/rate-limiting.md +77 -0
- package/kit/.claude/skills/reactive-programming.md +50 -0
- package/kit/.claude/skills/realtime-database.md +50 -0
- package/kit/.claude/skills/realtime-subscriptions.md +218 -0
- package/kit/.claude/skills/saas-ab-testing.md +90 -0
- package/kit/.claude/skills/saas-analytics.md +113 -0
- package/kit/.claude/skills/saas-billing.md +106 -0
- package/kit/.claude/skills/saas-email.md +88 -0
- package/kit/.claude/skills/saas-feature-flags.md +83 -0
- package/kit/.claude/skills/saas-onboarding.md +96 -0
- package/kit/.claude/skills/saas-user-onboarding.md +207 -0
- package/kit/.claude/skills/security-encryption.md +216 -0
- package/kit/.claude/skills/security-owasp.md +212 -0
- package/kit/.claude/skills/security-secrets-rotation.md +64 -0
- package/kit/.claude/skills/seo-content.md +94 -0
- package/kit/.claude/skills/seo-technical.md +101 -0
- package/kit/.claude/skills/serverless-framework.md +151 -0
- package/kit/.claude/skills/sharding-scaling.md +50 -0
- package/kit/.claude/skills/styling-css-modules.md +219 -0
- package/kit/.claude/skills/styling-styled-components.md +206 -0
- package/kit/.claude/skills/styling-tailwind.md +206 -0
- package/kit/.claude/skills/test-e2e.md +86 -0
- package/kit/.claude/skills/test-integration.md +216 -0
- package/kit/.claude/skills/test-performance.md +162 -0
- package/kit/.claude/skills/test-tdd.md +170 -0
- package/kit/.claude/skills/test-unit.md +301 -0
- package/kit/.claude/skills/testing-accessibility.md +117 -0
- package/kit/.claude/skills/testing-contract.md +75 -0
- package/kit/.claude/skills/testing-e2e-advanced.md +50 -0
- package/kit/.claude/skills/testing-load-stress.md +79 -0
- package/kit/.claude/skills/testing-mutation.md +92 -0
- package/kit/.claude/skills/testing-snapshot.md +50 -0
- package/kit/.claude/skills/testing-vitest.md +172 -0
- package/kit/.claude/skills/tooling-biome.md +91 -0
- package/kit/.claude/skills/tooling-build-tools.md +166 -0
- package/kit/.claude/skills/tooling-bun.md +94 -0
- package/kit/.claude/skills/tooling-eslint.md +103 -0
- package/kit/.claude/skills/tooling-git.md +79 -0
- package/kit/.claude/skills/tooling-monorepo.md +162 -0
- package/kit/.claude/skills/tooling-testing-frameworks.md +207 -0
- package/kit/.claude/skills/tooling-typescript.md +156 -0
- package/kit/.claude/skills/ui-a11y.md +106 -0
- package/kit/.claude/skills/ui-framer.md +106 -0
- package/kit/.claude/skills/ui-gsap.md +102 -0
- package/kit/.claude/skills/ui-radix.md +82 -0
- package/kit/.claude/skills/ui-shadcn.md +463 -0
- package/kit/.claude/skills/ui-tailwind.md +98 -0
- package/kit/.claude/skills/ui-threejs.md +110 -0
- package/kit/.claude/skills/ui-tokens.md +97 -0
- package/kit/.claude/skills/utilities-date-time.md +170 -0
- package/kit/.claude/skills/validation-schemas.md +110 -0
- package/kit/.claude/skills/version-control-git.md +144 -0
- package/kit/.claude/skills/web-accessibility-wcag.md +102 -0
- package/kit/.claude/skills/web-astro.md +197 -0
- package/kit/.claude/skills/web-html-css.md +224 -0
- package/kit/.claude/skills/web-htmx.md +99 -0
- package/kit/.claude/skills/web-nextjs-advanced.md +202 -0
- package/kit/.claude/skills/web-remix.md +194 -0
- package/kit/.claude/skills/web-seo.md +99 -0
- package/kit/.claude/skills/web-svelte.md +234 -0
- package/kit/.claude/skills/websocket-server.md +50 -0
- package/kit/.claude/skills/writing-marketing.md +89 -0
- package/kit/.claude/skills/writing-technical.md +119 -0
- package/kit/CLAUDE.md +206 -0
- package/kit/README.md +150 -0
- package/kit/SKILLS_INDEX.md +188 -0
- package/kit/docs/README.md +3 -0
- package/kit/journals/README.md +3 -0
- package/kit/plans/README.md +3 -0
- package/package.json +3 -1
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# Design Patterns
|
|
2
|
+
|
|
3
|
+
Common patterns for software architecture.
|
|
4
|
+
|
|
5
|
+
## Singleton Pattern
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Ensure only one instance exists
|
|
9
|
+
class Logger {
|
|
10
|
+
private static instance: Logger;
|
|
11
|
+
|
|
12
|
+
private constructor() {}
|
|
13
|
+
|
|
14
|
+
static getInstance(): Logger {
|
|
15
|
+
if (!Logger.instance) {
|
|
16
|
+
Logger.instance = new Logger();
|
|
17
|
+
}
|
|
18
|
+
return Logger.instance;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
log(message: string) {
|
|
22
|
+
console.log(`[LOG] ${message}`);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Usage
|
|
27
|
+
const logger1 = Logger.getInstance();
|
|
28
|
+
const logger2 = Logger.getInstance();
|
|
29
|
+
|
|
30
|
+
console.log(logger1 === logger2); // true
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Factory Pattern
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
// Create objects without exposing creation logic
|
|
37
|
+
interface Shape {
|
|
38
|
+
draw(): void;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
class Circle implements Shape {
|
|
42
|
+
draw() { console.log('Drawing circle'); }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
class Square implements Shape {
|
|
46
|
+
draw() { console.log('Drawing square'); }
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
class ShapeFactory {
|
|
50
|
+
static createShape(type: string): Shape {
|
|
51
|
+
switch (type) {
|
|
52
|
+
case 'circle':
|
|
53
|
+
return new Circle();
|
|
54
|
+
case 'square':
|
|
55
|
+
return new Square();
|
|
56
|
+
default:
|
|
57
|
+
throw new Error(`Unknown shape: ${type}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Usage
|
|
63
|
+
const circle = ShapeFactory.createShape('circle');
|
|
64
|
+
circle.draw();
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Observer Pattern
|
|
68
|
+
|
|
69
|
+
```typescript
|
|
70
|
+
// Notify multiple objects about state changes
|
|
71
|
+
interface Observer {
|
|
72
|
+
update(data: any): void;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
class Subject {
|
|
76
|
+
private observers: Observer[] = [];
|
|
77
|
+
|
|
78
|
+
attach(observer: Observer) {
|
|
79
|
+
this.observers.push(observer);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
detach(observer: Observer) {
|
|
83
|
+
const index = this.observers.indexOf(observer);
|
|
84
|
+
if (index > -1) {
|
|
85
|
+
this.observers.splice(index, 1);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
notify(data: any) {
|
|
90
|
+
this.observers.forEach(observer => observer.update(data));
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
class UserCreatedListener implements Observer {
|
|
95
|
+
update(data: any) {
|
|
96
|
+
console.log('User created:', data);
|
|
97
|
+
// Send welcome email
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// Usage
|
|
102
|
+
const subject = new Subject();
|
|
103
|
+
const listener = new UserCreatedListener();
|
|
104
|
+
|
|
105
|
+
subject.attach(listener);
|
|
106
|
+
subject.notify({ userId: '123', email: 'user@example.com' });
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Decorator Pattern
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
// Attach additional responsibilities dynamically
|
|
113
|
+
interface Component {
|
|
114
|
+
operation(): string;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
class ConcreteComponent implements Component {
|
|
118
|
+
operation(): string {
|
|
119
|
+
return 'ConcreteComponent';
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
abstract class Decorator implements Component {
|
|
124
|
+
constructor(protected component: Component) {}
|
|
125
|
+
|
|
126
|
+
operation(): string {
|
|
127
|
+
return this.component.operation();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
class ConcreteDecoratorA extends Decorator {
|
|
132
|
+
operation(): string {
|
|
133
|
+
return `ConcreteDecoratorA(${super.operation()})`;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
class ConcreteDecoratorB extends Decorator {
|
|
138
|
+
operation(): string {
|
|
139
|
+
return `ConcreteDecoratorB(${super.operation()})`;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// Usage
|
|
144
|
+
const component = new ConcreteComponent();
|
|
145
|
+
const decorated = new ConcreteDecoratorA(
|
|
146
|
+
new ConcreteDecoratorB(component)
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
console.log(decorated.operation()); // ConcreteDecoratorA(ConcreteDecoratorB(ConcreteComponent))
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Strategy Pattern
|
|
153
|
+
|
|
154
|
+
```typescript
|
|
155
|
+
// Define family of interchangeable algorithms
|
|
156
|
+
interface SortStrategy {
|
|
157
|
+
sort(items: number[]): number[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
class BubbleSort implements SortStrategy {
|
|
161
|
+
sort(items: number[]): number[] {
|
|
162
|
+
const arr = [...items];
|
|
163
|
+
for (let i = 0; i < arr.length; i++) {
|
|
164
|
+
for (let j = 0; j < arr.length - i - 1; j++) {
|
|
165
|
+
if (arr[j] > arr[j + 1]) {
|
|
166
|
+
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return arr;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
class QuickSort implements SortStrategy {
|
|
175
|
+
sort(items: number[]): number[] {
|
|
176
|
+
if (items.length <= 1) return items;
|
|
177
|
+
const pivot = items[0];
|
|
178
|
+
const less = items.slice(1).filter(x => x <= pivot);
|
|
179
|
+
const greater = items.slice(1).filter(x => x > pivot);
|
|
180
|
+
return [...this.sort(less), pivot, ...this.sort(greater)];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
class Sorter {
|
|
185
|
+
constructor(private strategy: SortStrategy) {}
|
|
186
|
+
|
|
187
|
+
sort(items: number[]): number[] {
|
|
188
|
+
return this.strategy.sort(items);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Usage
|
|
193
|
+
const items = [3, 1, 4, 1, 5];
|
|
194
|
+
const sorter = new Sorter(new QuickSort());
|
|
195
|
+
console.log(sorter.sort(items)); // [1, 1, 3, 4, 5]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
## Best Practices
|
|
199
|
+
|
|
200
|
+
✅ **Use appropriate patterns** - Don't over-engineer
|
|
201
|
+
✅ **Combine patterns** - Real apps use multiple patterns
|
|
202
|
+
✅ **Document patterns** - Make intent clear
|
|
203
|
+
✅ **Refactor to patterns** - Emerge naturally from code
|
|
204
|
+
✅ **Know the tradeoffs** - Patterns have pros and cons
|
|
205
|
+
|
|
206
|
+
## Resources
|
|
207
|
+
|
|
208
|
+
- [Gang of Four Design Patterns](https://en.wikipedia.org/wiki/Design_Patterns)
|
|
209
|
+
- [Refactoring Guru Patterns](https://refactoring.guru/design-patterns)
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# Observer & Pub/Sub Patterns
|
|
2
|
+
|
|
3
|
+
Decoupled event-driven communication.
|
|
4
|
+
|
|
5
|
+
## Observer Pattern Implementation
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
type Observer<T> = (data: T) => void;
|
|
9
|
+
|
|
10
|
+
class Subject<T> {
|
|
11
|
+
private observers: Set<Observer<T>> = new Set();
|
|
12
|
+
|
|
13
|
+
subscribe(observer: Observer<T>): () => void {
|
|
14
|
+
this.observers.add(observer);
|
|
15
|
+
// Return unsubscribe function
|
|
16
|
+
return () => this.observers.delete(observer);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
notify(data: T) {
|
|
20
|
+
this.observers.forEach(observer => observer(data));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Usage
|
|
25
|
+
const userSubject = new Subject<{ userId: string; action: string }>();
|
|
26
|
+
|
|
27
|
+
const unsubscribe1 = userSubject.subscribe(data => {
|
|
28
|
+
console.log('Email service:', data);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
const unsubscribe2 = userSubject.subscribe(data => {
|
|
32
|
+
console.log('Analytics:', data);
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
userSubject.notify({ userId: '123', action: 'login' });
|
|
36
|
+
|
|
37
|
+
// Unsubscribe
|
|
38
|
+
unsubscribe1();
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Pub/Sub with Channels
|
|
42
|
+
|
|
43
|
+
```typescript
|
|
44
|
+
class PubSub {
|
|
45
|
+
private channels = new Map<string, Set<Function>>();
|
|
46
|
+
|
|
47
|
+
subscribe(channel: string, callback: Function): () => void {
|
|
48
|
+
if (!this.channels.has(channel)) {
|
|
49
|
+
this.channels.set(channel, new Set());
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
this.channels.get(channel)!.add(callback);
|
|
53
|
+
|
|
54
|
+
return () => {
|
|
55
|
+
this.channels.get(channel)!.delete(callback);
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
publish(channel: string, data: any) {
|
|
60
|
+
const subscribers = this.channels.get(channel);
|
|
61
|
+
if (subscribers) {
|
|
62
|
+
subscribers.forEach(callback => callback(data));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Usage
|
|
68
|
+
const pubsub = new PubSub();
|
|
69
|
+
|
|
70
|
+
pubsub.subscribe('user:created', (user) => {
|
|
71
|
+
console.log('User created:', user);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
pubsub.subscribe('user:created', (user) => {
|
|
75
|
+
console.log('Send welcome email to:', user.email);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
pubsub.publish('user:created', {
|
|
79
|
+
id: '123',
|
|
80
|
+
email: 'user@example.com'
|
|
81
|
+
});
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## EventEmitter Pattern
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { EventEmitter } from 'events';
|
|
88
|
+
|
|
89
|
+
class UserService extends EventEmitter {
|
|
90
|
+
async createUser(userData: any) {
|
|
91
|
+
const user = await db.users.create(userData);
|
|
92
|
+
|
|
93
|
+
// Emit event
|
|
94
|
+
this.emit('user:created', user);
|
|
95
|
+
this.emit('user:modified', user);
|
|
96
|
+
|
|
97
|
+
return user;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async deleteUser(userId: string) {
|
|
101
|
+
await db.users.delete(userId);
|
|
102
|
+
this.emit('user:deleted', userId);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Usage
|
|
107
|
+
const userService = new UserService();
|
|
108
|
+
|
|
109
|
+
userService.on('user:created', (user) => {
|
|
110
|
+
console.log('New user:', user.email);
|
|
111
|
+
sendWelcomeEmail(user);
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
userService.on('user:deleted', (userId) => {
|
|
115
|
+
console.log('User deleted:', userId);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
userService.once('user:modified', (user) => {
|
|
119
|
+
console.log('User first modified:', user);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
await userService.createUser({ email: 'user@example.com' });
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Message Queue Pattern
|
|
126
|
+
|
|
127
|
+
```typescript
|
|
128
|
+
interface Message {
|
|
129
|
+
id: string;
|
|
130
|
+
type: string;
|
|
131
|
+
payload: any;
|
|
132
|
+
timestamp: Date;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
class MessageQueue {
|
|
136
|
+
private queue: Message[] = [];
|
|
137
|
+
private subscribers = new Map<string, Function[]>();
|
|
138
|
+
private processing = false;
|
|
139
|
+
|
|
140
|
+
async enqueue(type: string, payload: any) {
|
|
141
|
+
this.queue.push({
|
|
142
|
+
id: crypto.randomUUID(),
|
|
143
|
+
type,
|
|
144
|
+
payload,
|
|
145
|
+
timestamp: new Date()
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
this.process();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
subscribe(type: string, handler: Function) {
|
|
152
|
+
if (!this.subscribers.has(type)) {
|
|
153
|
+
this.subscribers.set(type, []);
|
|
154
|
+
}
|
|
155
|
+
this.subscribers.get(type)!.push(handler);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
private async process() {
|
|
159
|
+
if (this.processing) return;
|
|
160
|
+
|
|
161
|
+
this.processing = true;
|
|
162
|
+
|
|
163
|
+
while (this.queue.length > 0) {
|
|
164
|
+
const message = this.queue.shift()!;
|
|
165
|
+
const handlers = this.subscribers.get(message.type) || [];
|
|
166
|
+
|
|
167
|
+
for (const handler of handlers) {
|
|
168
|
+
try {
|
|
169
|
+
await handler(message.payload);
|
|
170
|
+
} catch (error) {
|
|
171
|
+
console.error(`Error processing message ${message.id}:`, error);
|
|
172
|
+
// Re-queue failed messages
|
|
173
|
+
this.queue.push(message);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
this.processing = false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Usage
|
|
183
|
+
const queue = new MessageQueue();
|
|
184
|
+
|
|
185
|
+
queue.subscribe('email:send', async (payload) => {
|
|
186
|
+
await emailService.send(payload.to, payload.subject);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
queue.subscribe('analytics:track', async (payload) => {
|
|
190
|
+
await analytics.track(payload);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
await queue.enqueue('email:send', {
|
|
194
|
+
to: 'user@example.com',
|
|
195
|
+
subject: 'Welcome'
|
|
196
|
+
});
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Best Practices
|
|
200
|
+
|
|
201
|
+
✅ **Decouple components** - Reduce dependencies
|
|
202
|
+
✅ **Error handling** - Handle failed subscriptions
|
|
203
|
+
✅ **Memory leaks** - Unsubscribe when done
|
|
204
|
+
✅ **Type safety** - Use generics for typed events
|
|
205
|
+
✅ **Debugging** - Log event emissions
|
|
206
|
+
|
|
207
|
+
## Resources
|
|
208
|
+
|
|
209
|
+
- [Node.js EventEmitter](https://nodejs.org/api/events.html)
|
|
210
|
+
- [PubSub Pattern](https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern)
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# Lemon Squeezy Payments
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
Lemon Squeezy is a merchant of record payment platform with built-in tax handling, subscriptions, and a simple API.
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
npm install @lemonsqueezy/lemonsqueezy.js
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
```env
|
|
13
|
+
LEMONSQUEEZY_API_KEY=eyJ0...
|
|
14
|
+
LEMONSQUEEZY_STORE_ID=12345
|
|
15
|
+
LEMONSQUEEZY_WEBHOOK_SECRET=whsec_...
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Create Checkout
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
import { lemonSqueezySetup, createCheckout } from '@lemonsqueezy/lemonsqueezy.js';
|
|
22
|
+
|
|
23
|
+
lemonSqueezySetup({ apiKey: process.env.LEMONSQUEEZY_API_KEY! });
|
|
24
|
+
|
|
25
|
+
// app/api/checkout/route.ts
|
|
26
|
+
export async function POST(req: Request) {
|
|
27
|
+
const { userId, email, variantId } = await req.json();
|
|
28
|
+
|
|
29
|
+
const { data, error } = await createCheckout(
|
|
30
|
+
process.env.LEMONSQUEEZY_STORE_ID!,
|
|
31
|
+
variantId,
|
|
32
|
+
{
|
|
33
|
+
checkoutData: {
|
|
34
|
+
email,
|
|
35
|
+
custom: { userId },
|
|
36
|
+
},
|
|
37
|
+
checkoutOptions: {
|
|
38
|
+
embed: false,
|
|
39
|
+
media: true,
|
|
40
|
+
logo: true,
|
|
41
|
+
},
|
|
42
|
+
productOptions: {
|
|
43
|
+
redirectUrl: `${process.env.NEXT_PUBLIC_URL}/dashboard?success=true`,
|
|
44
|
+
receiptThankYouNote: 'Thank you for subscribing!',
|
|
45
|
+
},
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
if (error) return Response.json({ error }, { status: 500 });
|
|
50
|
+
return Response.json({ url: data?.data.attributes.url });
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Webhook Handler
|
|
55
|
+
|
|
56
|
+
```typescript
|
|
57
|
+
// app/api/webhooks/lemonsqueezy/route.ts
|
|
58
|
+
import crypto from 'crypto';
|
|
59
|
+
|
|
60
|
+
export async function POST(req: Request) {
|
|
61
|
+
const rawBody = await req.text();
|
|
62
|
+
const signature = req.headers.get('x-signature') ?? '';
|
|
63
|
+
|
|
64
|
+
const hmac = crypto
|
|
65
|
+
.createHmac('sha256', process.env.LEMONSQUEEZY_WEBHOOK_SECRET!)
|
|
66
|
+
.update(rawBody)
|
|
67
|
+
.digest('hex');
|
|
68
|
+
|
|
69
|
+
if (hmac !== signature) {
|
|
70
|
+
return Response.json({ error: 'Invalid signature' }, { status: 401 });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const event = JSON.parse(rawBody);
|
|
74
|
+
const eventName = event.meta.event_name;
|
|
75
|
+
const userId = event.meta.custom_data?.userId;
|
|
76
|
+
|
|
77
|
+
switch (eventName) {
|
|
78
|
+
case 'order_created':
|
|
79
|
+
await prisma.user.update({
|
|
80
|
+
where: { id: userId },
|
|
81
|
+
data: { plan: 'pro', planExpiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) }
|
|
82
|
+
});
|
|
83
|
+
break;
|
|
84
|
+
case 'subscription_cancelled':
|
|
85
|
+
await prisma.user.update({ where: { id: userId }, data: { plan: 'free' } });
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return Response.json({ received: true });
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Best Practices
|
|
94
|
+
- Always verify webhook signatures before processing
|
|
95
|
+
- Store `userId` in checkout `custom_data` to link purchases to users
|
|
96
|
+
- Use Lemon Squeezy's test mode during development
|
|
97
|
+
- Handle `subscription_renewed`, `subscription_expired`, and `subscription_cancelled` events
|
|
98
|
+
|
|
99
|
+
## Resources
|
|
100
|
+
- [Lemon Squeezy docs](https://docs.lemonsqueezy.com)
|
|
101
|
+
- [@lemonsqueezy/lemonsqueezy.js](https://github.com/lemonSqueezy/lemonsqueezy-js)
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
# Square Payments
|
|
2
|
+
|
|
3
|
+
Payment processing platform with in-store and online capabilities.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install square
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Web Payments
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Client, Environment } from 'square';
|
|
15
|
+
|
|
16
|
+
const client = new Client({
|
|
17
|
+
environment: Environment.Production,
|
|
18
|
+
accessToken: process.env.SQUARE_ACCESS_TOKEN
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const paymentsApi = client.paymentsApi;
|
|
22
|
+
|
|
23
|
+
async function processPayment(sourceId: string, amountInCents: number) {
|
|
24
|
+
const response = await paymentsApi.createPayment({
|
|
25
|
+
sourceId,
|
|
26
|
+
amountMoney: {
|
|
27
|
+
amount: BigInt(amountInCents),
|
|
28
|
+
currency: 'USD'
|
|
29
|
+
},
|
|
30
|
+
idempotencyKey: crypto.randomUUID()
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return response.result;
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Web Payments Form
|
|
38
|
+
|
|
39
|
+
```typescript
|
|
40
|
+
import { SquareWebPaymentUI } from '@square/web-payments-sdk-js';
|
|
41
|
+
|
|
42
|
+
async function initializeSquare() {
|
|
43
|
+
const web = window.Square?.web;
|
|
44
|
+
|
|
45
|
+
if (!web) {
|
|
46
|
+
throw new Error('Square SDK not loaded');
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const payments = await web.payments({
|
|
50
|
+
applicationId: process.env.REACT_APP_SQUARE_APP_ID,
|
|
51
|
+
locationId: process.env.REACT_APP_SQUARE_LOCATION_ID
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const card = await payments.card();
|
|
55
|
+
await card.attach('#card-container');
|
|
56
|
+
|
|
57
|
+
return { payments, card };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function CheckoutForm() {
|
|
61
|
+
const { payments, card } = useSquarePayments();
|
|
62
|
+
|
|
63
|
+
async function handlePayment() {
|
|
64
|
+
try {
|
|
65
|
+
const result = await card.tokenize();
|
|
66
|
+
|
|
67
|
+
if (result.status === 'OK') {
|
|
68
|
+
const payment = await fetch('/api/square-payment', {
|
|
69
|
+
method: 'POST',
|
|
70
|
+
body: JSON.stringify({
|
|
71
|
+
sourceId: result.token,
|
|
72
|
+
amount: 9999
|
|
73
|
+
})
|
|
74
|
+
}).then(r => r.json());
|
|
75
|
+
|
|
76
|
+
alert('Payment successful!');
|
|
77
|
+
}
|
|
78
|
+
} catch (error) {
|
|
79
|
+
console.error('Payment failed:', error);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<div>
|
|
85
|
+
<div id="card-container"></div>
|
|
86
|
+
<button onClick={handlePayment}>Pay</button>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Customers & Cards
|
|
93
|
+
|
|
94
|
+
```typescript
|
|
95
|
+
const customersApi = client.customersApi;
|
|
96
|
+
const cardsApi = client.cardsApi;
|
|
97
|
+
|
|
98
|
+
async function createCustomer(email: string, name: string) {
|
|
99
|
+
const response = await customersApi.createCustomer({
|
|
100
|
+
email,
|
|
101
|
+
givenName: name
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
return response.result?.customer;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function storeCard(customerId: string, sourceId: string) {
|
|
108
|
+
const response = await cardsApi.createCard({
|
|
109
|
+
sourceId,
|
|
110
|
+
customerId
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
return response.result?.card;
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Subscriptions
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
const subscriptionApi = client.subscriptionsApi;
|
|
121
|
+
|
|
122
|
+
async function createSubscription(customerId: string, planId: string) {
|
|
123
|
+
const response = await subscriptionApi.createSubscription({
|
|
124
|
+
customerId,
|
|
125
|
+
locationId: process.env.SQUARE_LOCATION_ID,
|
|
126
|
+
planVariationId: planId,
|
|
127
|
+
startDate: new Date().toISOString().split('T')[0]
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
return response.result?.subscription;
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## Webhooks
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import crypto from 'crypto';
|
|
138
|
+
|
|
139
|
+
app.post('/webhooks/square', express.json(), (req, res) => {
|
|
140
|
+
const signature = req.header('x-square-hmac-sha256');
|
|
141
|
+
const body = req.body;
|
|
142
|
+
|
|
143
|
+
const hash = crypto
|
|
144
|
+
.createHmac('sha256', process.env.SQUARE_WEBHOOK_SIGNATURE_KEY)
|
|
145
|
+
.update(JSON.stringify(body))
|
|
146
|
+
.digest('base64');
|
|
147
|
+
|
|
148
|
+
if (hash !== signature) {
|
|
149
|
+
return res.status(401).json({ error: 'Invalid signature' });
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const event = body.data.object;
|
|
153
|
+
|
|
154
|
+
switch (body.type) {
|
|
155
|
+
case 'payment.created':
|
|
156
|
+
console.log('Payment created:', event);
|
|
157
|
+
break;
|
|
158
|
+
case 'payment.updated':
|
|
159
|
+
console.log('Payment updated:', event);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
res.json({ success: true });
|
|
164
|
+
});
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Best Practices
|
|
168
|
+
|
|
169
|
+
✅ **Tokenization** - Use Square's secure token generation
|
|
170
|
+
✅ **3D Secure** - Support for additional verification
|
|
171
|
+
✅ **Idempotency** - Generate unique keys for retry safety
|
|
172
|
+
✅ **Webhooks** - Handle payment state changes
|
|
173
|
+
✅ **Testing** - Use Square's test cards
|
|
174
|
+
|
|
175
|
+
## Resources
|
|
176
|
+
|
|
177
|
+
- [Square Developer Docs](https://developer.squareup.com/)
|
|
178
|
+
- [Web Payments SDK](https://developer.squareup.com/docs/web-payments/overview)
|