@kensaurus/skills 0.0.0-stage → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +53 -0
- package/.claude-plugin/plugin.json +40 -0
- package/.cursor-plugin/plugin.json +38 -0
- package/.mcp.json +28 -0
- package/CHANGELOG.md +1790 -0
- package/LICENSE +21 -0
- package/LICENSE-APACHE +62 -0
- package/NOTICE +13 -0
- package/README.md +821 -2
- package/SECURITY.md +55 -0
- package/agents/code-reviewer.md +60 -0
- package/agents/completion-judge.md +89 -0
- package/agents/db-migrator.md +125 -0
- package/agents/debugger.md +47 -0
- package/agents/deploy-checker.md +100 -0
- package/agents/perf-monitor.md +74 -0
- package/assets/favicon.png +0 -0
- package/assets/logo-light.png +0 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +6 -0
- package/assets/og.png +0 -0
- package/bin/install.mjs +1127 -0
- package/bin/kenji.js +2 -0
- package/commands/adr.md +17 -0
- package/commands/aeo-plan.md +18 -0
- package/commands/arch-boundaries.md +17 -0
- package/commands/aso-plan.md +18 -0
- package/commands/auth-flows.md +19 -0
- package/commands/backup-plan.md +17 -0
- package/commands/burndown-full.md +25 -0
- package/commands/capacitor-plan.md +18 -0
- package/commands/codemod-safety.md +22 -0
- package/commands/commit.md +18 -0
- package/commands/complete-everything.md +40 -0
- package/commands/cost-plan.md +19 -0
- package/commands/deadcode-plan.md +26 -0
- package/commands/deadcode.md +32 -0
- package/commands/debug-issue.md +17 -0
- package/commands/deps-plan.md +18 -0
- package/commands/docs-plan.md +17 -0
- package/commands/doctrine.md +19 -0
- package/commands/error-plan.md +19 -0
- package/commands/feedback-to-closure.md +36 -0
- package/commands/fix-issue.md +76 -0
- package/commands/gate-logic.md +26 -0
- package/commands/green-repo.md +36 -0
- package/commands/grill-me.md +19 -0
- package/commands/gtm-plan.md +21 -0
- package/commands/gtm-weekly.md +17 -0
- package/commands/gtm.md +22 -0
- package/commands/handoff.md +15 -0
- package/commands/housekeep-backlog.md +18 -0
- package/commands/housekeep-files.md +22 -0
- package/commands/housekeep-gates.md +18 -0
- package/commands/instant-nav.md +11 -0
- package/commands/integrity-plan.md +19 -0
- package/commands/launch-kit.md +16 -0
- package/commands/mcp-guide.md +40 -0
- package/commands/mobile-plan.md +19 -0
- package/commands/native-rn-monorepo/README.md +78 -0
- package/commands/native-rn-monorepo/android-build.md +26 -0
- package/commands/native-rn-monorepo/android-install.md +32 -0
- package/commands/native-rn-monorepo/android-logcat.md +37 -0
- package/commands/native-rn-monorepo/ios-ci-logs.md +56 -0
- package/commands/native-rn-monorepo/ios-ci-status.md +52 -0
- package/commands/native-rn-monorepo/ios-ci-trigger.md +59 -0
- package/commands/native-rn-monorepo/rn-reset.md +50 -0
- package/commands/native-rn-monorepo/rn-ship-ios.md +67 -0
- package/commands/native-rn-monorepo/rn-verify.md +53 -0
- package/commands/perf-plan.md +18 -0
- package/commands/plan-mode.md +74 -0
- package/commands/pr.md +16 -0
- package/commands/pricing-plan.md +20 -0
- package/commands/privacy-plan.md +18 -0
- package/commands/readability.md +12 -0
- package/commands/readme.md +15 -0
- package/commands/refactor.md +15 -0
- package/commands/release-prep.md +17 -0
- package/commands/research.md +25 -0
- package/commands/responsive-audit.md +21 -0
- package/commands/review-code.md +18 -0
- package/commands/rls-plan.md +18 -0
- package/commands/secrets-plan.md +18 -0
- package/commands/security-plan.md +19 -0
- package/commands/ship-and-observe.md +36 -0
- package/commands/skill-conflicts.md +19 -0
- package/commands/slop-plan.md +18 -0
- package/commands/stub-plan.md +18 -0
- package/commands/test-mutation.md +16 -0
- package/commands/test-plan.md +17 -0
- package/commands/test.md +29 -0
- package/commands/thirdparty-web-interface-guidelines.md +185 -0
- package/commands/uiux-plan.md +18 -0
- package/commands/uiux.md +45 -0
- package/commands/update-deps.md +21 -0
- package/commands/validation-plan.md +19 -0
- package/commands-portable/fix-issue.md +72 -0
- package/commands-portable/plan-mode.md +92 -0
- package/commands-portable/research.md +91 -0
- package/docs/screenshots/README.md +5 -0
- package/docs/screenshots/audit-dark.png +0 -0
- package/docs/screenshots/build-dark.png +0 -0
- package/docs/screenshots/grill-dark.png +0 -0
- package/docs/screenshots/hero-dark.png +0 -0
- package/docs/screenshots/hero-light.png +0 -0
- package/docs/screenshots/ship-dark.png +0 -0
- package/docs/screenshots/src/showcase.html +320 -0
- package/hooks/completion-gate.mjs +258 -0
- package/hooks/cursor-hooks.json +13 -0
- package/hooks/hooks.json +15 -0
- package/install.sh +21 -0
- package/llms.txt +40 -0
- package/mcp/README.md +266 -0
- package/mcp/VERSIONS.md +41 -0
- package/mcp/mcp-full.json.template +124 -0
- package/mcp/mcp.json.template +29 -0
- package/mcp/pinned-versions.json +27 -0
- package/package.json +94 -4
- package/rules/approved-plan-execution.mdc +65 -0
- package/rules/full-stack-ship-discipline.mdc +37 -0
- package/rules/native-rn-monorepo/README.md +63 -0
- package/rules/native-rn-monorepo/_project.mdc +69 -0
- package/rules/native-rn-monorepo/native-android.mdc +72 -0
- package/rules/native-rn-monorepo/native-ios.mdc +61 -0
- package/rules/native-rn-monorepo/react-native-js.mdc +78 -0
- package/rules/native-rn-monorepo/web.mdc +60 -0
- package/rules/project-starter/components.mdc +54 -0
- package/rules/project-starter/data-fetching.mdc +77 -0
- package/rules/project-starter/git.mdc +41 -0
- package/rules/project-starter/supabase.mdc +37 -0
- package/rules/project-starter/tailwind.mdc +48 -0
- package/rules/project-starter/typescript.mdc +36 -0
- package/rules/project-starter/web-performance.mdc +42 -0
- package/rules/senior-engineer.mdc +30 -0
- package/rules/shell-first-search.mdc +19 -0
- package/rules/skill-workflows.mdc +35 -0
- package/rules/verification-before-completion.mdc +57 -0
- package/skills/audit-accessibility/SKILL.md +441 -0
- package/skills/audit-agent-speed/SKILL.md +181 -0
- package/skills/audit-agent-speed/scripts/stop-typecheck.mjs +151 -0
- package/skills/audit-analytics/SKILL.md +138 -0
- package/skills/audit-auth-flows/SKILL.md +267 -0
- package/skills/audit-backend-architecture/SKILL.md +266 -0
- package/skills/audit-backend-architecture/references/patterns.md +386 -0
- package/skills/audit-bundle-size/SKILL.md +295 -0
- package/skills/audit-cicd/SKILL.md +218 -0
- package/skills/audit-code-quality/SKILL.md +314 -0
- package/skills/audit-code-review/SKILL.md +289 -0
- package/skills/audit-codemod-safety/SKILL.md +159 -0
- package/skills/audit-db-schema/SKILL.md +465 -0
- package/skills/audit-db-schema/references/details.md +110 -0
- package/skills/audit-doctrine/SKILL.md +189 -0
- package/skills/audit-env-parity/SKILL.md +133 -0
- package/skills/audit-fe-api/SKILL.md +458 -0
- package/skills/audit-gate-logic/SKILL.md +219 -0
- package/skills/audit-i18n/SKILL.md +339 -0
- package/skills/audit-infra-cost/SKILL.md +142 -0
- package/skills/audit-langfuse-llm/SKILL.md +468 -0
- package/skills/audit-langfuse-llm/references/details.md +226 -0
- package/skills/audit-llm-security/SKILL.md +147 -0
- package/skills/audit-monetization-iap/SKILL.md +137 -0
- package/skills/audit-payment-system/SKILL.md +268 -0
- package/skills/audit-payment-system/references/checklist.md +283 -0
- package/skills/audit-performance/SKILL.md +383 -0
- package/skills/audit-performance/references/loading-priority-2026.md +81 -0
- package/skills/audit-realworld/SKILL.md +287 -0
- package/skills/audit-registry-listing/SKILL.md +122 -0
- package/skills/audit-resilience/SKILL.md +153 -0
- package/skills/audit-responsive/SKILL.md +221 -0
- package/skills/audit-responsive/references/checklist.md +166 -0
- package/skills/audit-security/SKILL.md +289 -0
- package/skills/audit-skill-conflicts/SKILL.md +178 -0
- package/skills/audit-ui-states/SKILL.md +146 -0
- package/skills/audit-uiux-design-system/SKILL.md +475 -0
- package/skills/audit-uiux-design-system/references/details.md +71 -0
- package/skills/audit-ux/SKILL.md +381 -0
- package/skills/audit-ux/references/details.md +245 -0
- package/skills/audit-ux-journeys/SKILL.md +215 -0
- package/skills/audit-ux-journeys/references/checklist.md +179 -0
- package/skills/backend-db-performance/SKILL.md +441 -0
- package/skills/backend-error-handling/SKILL.md +489 -0
- package/skills/backend-error-handling/references/details.md +58 -0
- package/skills/backend-observability/SKILL.md +88 -0
- package/skills/backend-patterns/SKILL.md +499 -0
- package/skills/backend-patterns/references/architecture-patterns.md +298 -0
- package/skills/backend-realtime/SKILL.md +403 -0
- package/skills/backend-realtime/references/patterns.md +74 -0
- package/skills/burndown-full/SKILL.md +174 -0
- package/skills/complete-everything/SKILL.md +295 -0
- package/skills/data-pipeline/SKILL.md +109 -0
- package/skills/data-visualization/SKILL.md +488 -0
- package/skills/debug-error/SKILL.md +322 -0
- package/skills/debug-fe-be-integration/SKILL.md +459 -0
- package/skills/debug-sentry-monitor/SKILL.md +497 -0
- package/skills/debug-sentry-monitor/references/details.md +165 -0
- package/skills/deploy-npm/SKILL.md +394 -0
- package/skills/deploy-npm/references/example-mushi-mushi.md +52 -0
- package/skills/deploy-verify/SKILL.md +489 -0
- package/skills/design-api/SKILL.md +379 -0
- package/skills/design-canvas/SKILL.md +155 -0
- package/skills/design-email/SKILL.md +370 -0
- package/skills/design-frontend/SKILL.md +143 -0
- package/skills/design-generative-art/SKILL.md +474 -0
- package/skills/design-mobile-first/SKILL.md +506 -0
- package/skills/design-motion/SKILL.md +333 -0
- package/skills/design-motion/references/delight-interactions.md +191 -0
- package/skills/design-prd/SKILL.md +443 -0
- package/skills/design-system/SKILL.md +457 -0
- package/skills/design-theme/SKILL.md +226 -0
- package/skills/design-theme/themes/tsumagoi-ranch.md +150 -0
- package/skills/docs-adr/SKILL.md +168 -0
- package/skills/docs-coauthor/SKILL.md +368 -0
- package/skills/docs-comparison-pages/SKILL.md +117 -0
- package/skills/docs-domain-modeling/SKILL.md +97 -0
- package/skills/docs-launch-kit/SKILL.md +139 -0
- package/skills/docs-writer/SKILL.md +469 -0
- package/skills/enhance-agent-guardrails/SKILL.md +164 -0
- package/skills/enhance-arch-boundaries/SKILL.md +154 -0
- package/skills/enhance-capacitor-ui/SKILL.md +463 -0
- package/skills/enhance-capacitor-ui/references/details.md +750 -0
- package/skills/enhance-email-deliverability/SKILL.md +143 -0
- package/skills/enhance-growth-loops/SKILL.md +122 -0
- package/skills/enhance-lifecycle-email/SKILL.md +130 -0
- package/skills/enhance-motion/SKILL.md +193 -0
- package/skills/enhance-onboarding/SKILL.md +148 -0
- package/skills/enhance-pwa/SKILL.md +303 -0
- package/skills/enhance-readability/SKILL.md +146 -0
- package/skills/enhance-readme/SKILL.md +496 -0
- package/skills/enhance-readme/package-lock.json +187 -0
- package/skills/enhance-readme/package.json +17 -0
- package/skills/enhance-readme/scripts/generate-readme-blocks.mjs +199 -0
- package/skills/enhance-readme/scripts/record-readme-tour.mjs +442 -0
- package/skills/enhance-skill-prompts/SKILL.md +167 -0
- package/skills/enhance-skill-prompts/references/exemplar-audit-auth-flows.md +311 -0
- package/skills/enhance-ux-laws/SKILL.md +409 -0
- package/skills/enhance-web-conversion/SKILL.md +155 -0
- package/skills/enhance-web-forms/SKILL.md +154 -0
- package/skills/enhance-web-instant-nav/SKILL.md +138 -0
- package/skills/enhance-web-instant-nav/references/bfcache-blockers.md +23 -0
- package/skills/enhance-web-instant-nav/references/early-hints.md +33 -0
- package/skills/enhance-web-instant-nav/references/speculation-rules.md +44 -0
- package/skills/enhance-web-landing/SKILL.md +459 -0
- package/skills/enhance-web-landing/references/details.md +773 -0
- package/skills/enhance-web-redesign/SKILL.md +228 -0
- package/skills/enhance-web-seo/SKILL.md +276 -0
- package/skills/enhance-web-ui/SKILL.md +473 -0
- package/skills/enhance-web-ui/references/details.md +674 -0
- package/skills/enhance-web-ux/HEURISTICS.md +248 -0
- package/skills/enhance-web-ux/PATTERNS.md +375 -0
- package/skills/enhance-web-ux/SKILL.md +464 -0
- package/skills/enhance-web-ux/examples.md +222 -0
- package/skills/enhance-web-ux/references/details.md +406 -0
- package/skills/enhance-web-web3d/SKILL.md +397 -0
- package/skills/enhance-web-web3d/references/css-canvas-effects.md +180 -0
- package/skills/handoff/SKILL.md +66 -0
- package/skills/housekeep-backlog/SKILL.md +149 -0
- package/skills/housekeep-dead-code/SKILL.md +387 -0
- package/skills/housekeep-dead-code/references/ratchet-ci.md +205 -0
- package/skills/housekeep-dead-code/references/supabase-hygiene.md +152 -0
- package/skills/housekeep-design/SKILL.md +207 -0
- package/skills/housekeep-files/SKILL.md +220 -0
- package/skills/housekeep-files/references/naming-and-catalog.md +86 -0
- package/skills/housekeep-files/scripts/housekeep-files.ps1 +360 -0
- package/skills/housekeep-files/scripts/housekeep-files.sh +238 -0
- package/skills/housekeep-gates/SKILL.md +174 -0
- package/skills/iterate-agent-harness/SKILL.md +137 -0
- package/skills/iterate-gtm-weekly/SKILL.md +103 -0
- package/skills/iterate-post-launch/SKILL.md +292 -0
- package/skills/meta-mcp-builder/SKILL.md +313 -0
- package/skills/meta-skill-creator/SKILL.md +304 -0
- package/skills/mobile-capacitor-platform/SKILL.md +103 -0
- package/skills/mobile-emulator-start/SKILL.md +296 -0
- package/skills/mobile-emulator-test/SKILL.md +491 -0
- package/skills/mobile-emulator-test/references/details.md +478 -0
- package/skills/mobile-rn-performance/SKILL.md +107 -0
- package/skills/mobile-rn-screen/SKILL.md +476 -0
- package/skills/mobile-rn-screen/references/details.md +785 -0
- package/skills/mushi-health/SKILL.md +206 -0
- package/skills/mushi-integration/SKILL.md +257 -0
- package/skills/plan-aeo-readiness/SKILL.md +166 -0
- package/skills/plan-antislop/SKILL.md +281 -0
- package/skills/plan-aso/SKILL.md +149 -0
- package/skills/plan-backup-dr/SKILL.md +131 -0
- package/skills/plan-capacitor-hardening/SKILL.md +217 -0
- package/skills/plan-data-integrity/SKILL.md +187 -0
- package/skills/plan-dead-code/SKILL.md +386 -0
- package/skills/plan-dead-code/references/knip-config.md +214 -0
- package/skills/plan-dead-code/references/output-templates.md +133 -0
- package/skills/plan-dead-code/references/preservation-contract.md +50 -0
- package/skills/plan-dead-code/references/residue-greps.md +84 -0
- package/skills/plan-dependency-provenance/SKILL.md +200 -0
- package/skills/plan-docs-sync/SKILL.md +143 -0
- package/skills/plan-docs-sync/references/drift-taxonomy.md +43 -0
- package/skills/plan-docs-sync/references/output-templates.md +33 -0
- package/skills/plan-docs-sync/references/preservation-contract.md +17 -0
- package/skills/plan-error-handling/SKILL.md +205 -0
- package/skills/plan-gtm/SKILL.md +276 -0
- package/skills/plan-gtm/references/benchmarks-2026.md +183 -0
- package/skills/plan-input-validation/SKILL.md +179 -0
- package/skills/plan-llm-cost-guardrails/SKILL.md +176 -0
- package/skills/plan-mobile-readiness/SKILL.md +171 -0
- package/skills/plan-perf-audit/SKILL.md +145 -0
- package/skills/plan-perf-audit/references/audit-scope.md +51 -0
- package/skills/plan-perf-audit/references/output-templates.md +33 -0
- package/skills/plan-perf-audit/references/preservation-contract.md +13 -0
- package/skills/plan-pricing/SKILL.md +173 -0
- package/skills/plan-privacy-compliance/SKILL.md +148 -0
- package/skills/plan-rls-audit/SKILL.md +231 -0
- package/skills/plan-secrets-audit/SKILL.md +181 -0
- package/skills/plan-security-audit/SKILL.md +168 -0
- package/skills/plan-security-audit/references/output-templates.md +36 -0
- package/skills/plan-security-audit/references/owasp-supabase-scope.md +55 -0
- package/skills/plan-security-audit/references/preservation-contract.md +18 -0
- package/skills/plan-stub-checker/SKILL.md +216 -0
- package/skills/plan-stub-checker/references/detection-methodology.md +75 -0
- package/skills/plan-stub-checker/references/detection-taxonomy.md +34 -0
- package/skills/plan-stub-checker/references/output-templates.md +63 -0
- package/skills/plan-stub-checker/references/preservation-contract.md +24 -0
- package/skills/plan-test-coverage/SKILL.md +170 -0
- package/skills/plan-test-coverage/references/methodology.md +54 -0
- package/skills/plan-test-coverage/references/output-templates.md +34 -0
- package/skills/plan-test-coverage/references/preservation-contract.md +15 -0
- package/skills/plan-uiux-unification/SKILL.md +230 -0
- package/skills/plan-uiux-unification/references/output-templates.md +67 -0
- package/skills/plan-uiux-unification/references/phase-workbook.md +85 -0
- package/skills/plan-uiux-unification/references/preservation-contract.md +24 -0
- package/skills/protocol-browser-anti-stall/SKILL.md +211 -0
- package/skills/protocol-browser-anti-stall/references/mcp-to-cli-map.md +113 -0
- package/skills/protocol-browser-anti-stall/references/playwright-session-coordination.md +170 -0
- package/skills/research/SKILL.md +422 -0
- package/skills/test-exploratory/SKILL.md +165 -0
- package/skills/test-exploratory/references/charter-template.md +29 -0
- package/skills/test-load/SKILL.md +126 -0
- package/skills/test-mutation/SKILL.md +160 -0
- package/skills/test-playwright/SKILL.md +354 -0
- package/skills/test-qa/SKILL.md +364 -0
- package/skills/test-qa/references/details.md +268 -0
- package/skills/test-red-team/SKILL.md +386 -0
- package/skills/test-red-team/references/owasp-attack-checklist.md +193 -0
- package/skills/test-unit/SKILL.md +259 -0
- package/skills/test-unit/references/details.md +267 -0
- package/skills/test-visual-regression/SKILL.md +132 -0
- package/skills/thirdparty-emil-design-eng/ATTRIBUTION.md +20 -0
- package/skills/thirdparty-emil-design-eng/SKILL.md +21 -0
- package/skills/thirdparty-emil-design-eng/references/emil-design-eng.md +676 -0
- package/skills/thirdparty-ui-ux-pro-max/ATTRIBUTION.md +22 -0
- package/skills/thirdparty-ui-ux-pro-max/SKILL.md +304 -0
- package/skills/thirdparty-ui-ux-pro-max/data/charts.csv +26 -0
- package/skills/thirdparty-ui-ux-pro-max/data/colors.csv +97 -0
- package/skills/thirdparty-ui-ux-pro-max/data/icons.csv +101 -0
- package/skills/thirdparty-ui-ux-pro-max/data/landing.csv +31 -0
- package/skills/thirdparty-ui-ux-pro-max/data/products.csv +97 -0
- package/skills/thirdparty-ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills/thirdparty-ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills/thirdparty-ui-ux-pro-max/data/styles.csv +68 -0
- package/skills/thirdparty-ui-ux-pro-max/data/typography.csv +58 -0
- package/skills/thirdparty-ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills/thirdparty-ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills/thirdparty-ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/core.py +253 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/design_system.py +1067 -0
- package/skills/thirdparty-ui-ux-pro-max/scripts/search.py +114 -0
- package/skills/thirdparty-web-interface-guidelines/ATTRIBUTION.md +23 -0
- package/skills/thirdparty-web-interface-guidelines/SKILL.md +190 -0
- package/skills/workflow-build-feature/SKILL.md +118 -0
- package/skills/workflow-coding-discipline/SKILL.md +140 -0
- package/skills/workflow-environment-ready/SKILL.md +128 -0
- package/skills/workflow-feature-flag/SKILL.md +262 -0
- package/skills/workflow-feedback-to-closure/SKILL.md +165 -0
- package/skills/workflow-fix-and-ship/SKILL.md +136 -0
- package/skills/workflow-git-commit/SKILL.md +200 -0
- package/skills/workflow-green-repo/SKILL.md +166 -0
- package/skills/workflow-grilling/SKILL.md +73 -0
- package/skills/workflow-gtm/SKILL.md +153 -0
- package/skills/workflow-housekeep/SKILL.md +453 -0
- package/skills/workflow-housekeep/references/templates.md +109 -0
- package/skills/workflow-launch-ready/SKILL.md +145 -0
- package/skills/workflow-merge-conflicts/SKILL.md +62 -0
- package/skills/workflow-onboard/SKILL.md +99 -0
- package/skills/workflow-parallel-agents/SKILL.md +164 -0
- package/skills/workflow-pr/SKILL.md +197 -0
- package/skills/workflow-quality-gate/SKILL.md +147 -0
- package/skills/workflow-refactor/SKILL.md +274 -0
- package/skills/workflow-release-prep/SKILL.md +207 -0
- package/skills/workflow-ship-and-observe/SKILL.md +164 -0
- package/skills/workflow-spec-tdd/SKILL.md +141 -0
- package/skills/workflow-spec-tdd/references/spec-template.md +126 -0
- package/skills/workflow-spec-tdd/references/tdd-patterns.md +167 -0
- package/skills-cursor/babysit/SKILL.md +17 -0
- package/skills-cursor/canvas/SKILL.md +142 -0
- package/skills-cursor/canvas/sdk/canvas-tokens.d.ts +235 -0
- package/skills-cursor/canvas/sdk/chart-primitives.d.ts +200 -0
- package/skills-cursor/canvas/sdk/dag-layout.d.ts +102 -0
- package/skills-cursor/canvas/sdk/diff-view.d.ts +130 -0
- package/skills-cursor/canvas/sdk/form-primitives.d.ts +194 -0
- package/skills-cursor/canvas/sdk/hooks.d.ts +117 -0
- package/skills-cursor/canvas/sdk/index.d.ts +47 -0
- package/skills-cursor/canvas/sdk/theme.d.ts +61 -0
- package/skills-cursor/canvas/sdk/todo-list.d.ts +49 -0
- package/skills-cursor/canvas/sdk/ui-primitives.d.ts +549 -0
- package/skills-cursor/canvas/sdk/ui-primitives.test.d.ts +2 -0
- package/skills-cursor/create-hook/SKILL.md +238 -0
- package/skills-cursor/create-rule/SKILL.md +185 -0
- package/skills-cursor/create-skill/SKILL.md +269 -0
- package/skills-cursor/create-skill/references/authoring-guide.md +182 -0
- package/skills-cursor/create-subagent/SKILL.md +228 -0
- package/skills-cursor/migrate-to-skills/SKILL.md +121 -0
- package/skills-cursor/shell/SKILL.md +22 -0
- package/skills-cursor/split-to-prs/SKILL.md +47 -0
- package/skills-cursor/statusline/SKILL.md +193 -0
- package/skills-cursor/update-cli-config/SKILL.md +85 -0
- package/skills-cursor/update-cursor-settings/SKILL.md +137 -0
- package/skills.sh.json +297 -0
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: design-mobile-first
|
|
3
|
+
description: >
|
|
4
|
+
Design mobile-first UIs: touch targets, safe areas, gestures, then enhance up.
|
|
5
|
+
Use when building for small screens, touch, swipe, PWA, or tablet. Linearized
|
|
6
|
+
desktop / responsive audit → audit-responsive.
|
|
7
|
+
license: MIT
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Mobile-First Design Skill
|
|
11
|
+
|
|
12
|
+
**Degree of freedom: MIXED.** Pattern choice `[HIGH freedom]`; breakpoint,
|
|
13
|
+
viewport, and existing-hook inventory `[LOW freedom — run exactly]`.
|
|
14
|
+
|
|
15
|
+
Build interfaces that work on mobile first, then enhance for larger screens.
|
|
16
|
+
|
|
17
|
+
**Not this skill:** a desktop that is a linearized phone (no max-width, stacked
|
|
18
|
+
at 1440, stretched buttons). That is `audit-responsive`.
|
|
19
|
+
|
|
20
|
+
## How to reason
|
|
21
|
+
|
|
22
|
+
1. **Survey** — breakpoints, viewport, existing mobile hooks
|
|
23
|
+
2. **Base** — mobile styles first (44px, safe-area)
|
|
24
|
+
3. **Enhance** — `sm:`/`md:`/`lg:` add up; they do not replace the base
|
|
25
|
+
4. **Device-check** — real phone, not only a resized desktop window
|
|
26
|
+
|
|
27
|
+
## Worked example
|
|
28
|
+
|
|
29
|
+
> **Survey:** Tailwind `sm/md/lg` exist; checkout CTA is `h-8`; no `safe-area-inset-bottom`.
|
|
30
|
+
> **Base:** `min-h-[44px]`, `pb-[env(safe-area-inset-bottom)]`, stacked fields, 16px inputs.
|
|
31
|
+
> **Enhance:** two-column names at `sm:`; table replaces cards at `md:`.
|
|
32
|
+
> **Device-check:** thumb reaches the CTA; iOS does not zoom on focus.
|
|
33
|
+
|
|
34
|
+
## Self-critique before reporting
|
|
35
|
+
|
|
36
|
+
- **Base is mobile** — primary layout is not `lg:`-only
|
|
37
|
+
- **44px + safe-area** — tap targets and notches were measured
|
|
38
|
+
- **Real device** — not emulator-or-resize only
|
|
39
|
+
- **Right owner** — linearized 1440 desktop → `audit-responsive`; hybrid native chrome → `enhance-capacitor-ui`
|
|
40
|
+
|
|
41
|
+
## Check existing first [LOW freedom — run exactly]
|
|
42
|
+
|
|
43
|
+
**Before ANY mobile optimization, verify:**
|
|
44
|
+
|
|
45
|
+
1. **Check existing breakpoints:**
|
|
46
|
+
```bash
|
|
47
|
+
cat tailwind.config.* | grep -A10 "screens\|breakpoints"
|
|
48
|
+
rg "sm:|md:|lg:|xl:" --type tsx | head -20
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
2. **Check for existing mobile patterns:**
|
|
52
|
+
```bash
|
|
53
|
+
rg "useMediaQuery|useBreakpoint|isMobile" --type ts --type tsx
|
|
54
|
+
ls -la src/hooks/use*Mobile* src/hooks/use*Responsive* 2>/dev/null
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
3. **Check viewport meta:**
|
|
58
|
+
```bash
|
|
59
|
+
rg "viewport" src/app/layout.tsx index.html
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
**Why:** Maintain consistent responsive patterns across the app.
|
|
63
|
+
|
|
64
|
+
## Mobile-First Principles [HIGH freedom]
|
|
65
|
+
|
|
66
|
+
### 1. Design for Mobile First
|
|
67
|
+
```css
|
|
68
|
+
/* Base styles = mobile */
|
|
69
|
+
.card {
|
|
70
|
+
padding: 1rem;
|
|
71
|
+
font-size: 0.875rem;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Then enhance for larger screens */
|
|
75
|
+
@media (min-width: 640px) {
|
|
76
|
+
.card {
|
|
77
|
+
padding: 1.5rem;
|
|
78
|
+
font-size: 1rem;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/* Tailwind design-mobile-first */
|
|
83
|
+
<div className="p-4 sm:p-6 md:p-8">
|
|
84
|
+
<div className="text-sm sm:text-base lg:text-lg">
|
|
85
|
+
<div className="grid-cols-1 sm:grid-cols-2 lg:grid-cols-3">
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### 2. Touch Targets (44px minimum)
|
|
89
|
+
```tsx
|
|
90
|
+
// Touch-friendly button
|
|
91
|
+
<button className="min-h-[44px] min-w-[44px] px-4 py-3">
|
|
92
|
+
Tap me
|
|
93
|
+
</button>
|
|
94
|
+
|
|
95
|
+
// Touch-friendly list items
|
|
96
|
+
<li className="py-3 px-4 min-h-[44px] active:bg-muted">
|
|
97
|
+
List item
|
|
98
|
+
</li>
|
|
99
|
+
|
|
100
|
+
// Icon buttons with proper touch area
|
|
101
|
+
<button
|
|
102
|
+
className="p-3 -m-3" // Negative margin extends touch area
|
|
103
|
+
aria-label="Menu"
|
|
104
|
+
>
|
|
105
|
+
<MenuIcon className="h-5 w-5" />
|
|
106
|
+
</button>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### 3. Thumb-Friendly Zones
|
|
110
|
+
```tsx
|
|
111
|
+
// Bottom navigation for primary actions
|
|
112
|
+
<nav className="fixed bottom-0 left-0 right-0 border-t bg-background safe-area-pb">
|
|
113
|
+
<div className="flex justify-around py-2">
|
|
114
|
+
<NavItem icon={HomeIcon} label="Home" />
|
|
115
|
+
<NavItem icon={SearchIcon} label="Search" />
|
|
116
|
+
<NavItem icon={PlusIcon} label="Create" />
|
|
117
|
+
<NavItem icon={BellIcon} label="Alerts" />
|
|
118
|
+
<NavItem icon={UserIcon} label="Profile" />
|
|
119
|
+
</div>
|
|
120
|
+
</nav>
|
|
121
|
+
|
|
122
|
+
// Safe area padding for notched devices
|
|
123
|
+
.safe-area-pb {
|
|
124
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
125
|
+
}
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
## Responsive Patterns
|
|
129
|
+
|
|
130
|
+
### Mobile Navigation
|
|
131
|
+
```tsx
|
|
132
|
+
'use client'
|
|
133
|
+
import { useState } from 'react'
|
|
134
|
+
import { motion, AnimatePresence } from 'framer-motion'
|
|
135
|
+
|
|
136
|
+
export function MobileNav() {
|
|
137
|
+
const [isOpen, setIsOpen] = useState(false)
|
|
138
|
+
|
|
139
|
+
return (
|
|
140
|
+
<>
|
|
141
|
+
<button
|
|
142
|
+
className="lg:hidden p-2"
|
|
143
|
+
onClick={() => setIsOpen(true)}
|
|
144
|
+
aria-label="Open menu"
|
|
145
|
+
>
|
|
146
|
+
<MenuIcon className="h-6 w-6" />
|
|
147
|
+
</button>
|
|
148
|
+
|
|
149
|
+
<AnimatePresence>
|
|
150
|
+
{isOpen && (
|
|
151
|
+
<>
|
|
152
|
+
{/* Backdrop */}
|
|
153
|
+
<motion.div
|
|
154
|
+
initial={{ opacity: 0 }}
|
|
155
|
+
animate={{ opacity: 1 }}
|
|
156
|
+
exit={{ opacity: 0 }}
|
|
157
|
+
className="fixed inset-0 bg-black/50 z-40 lg:hidden"
|
|
158
|
+
onClick={() => setIsOpen(false)}
|
|
159
|
+
/>
|
|
160
|
+
|
|
161
|
+
{/* Drawer */}
|
|
162
|
+
<motion.div
|
|
163
|
+
initial={{ x: '-100%' }}
|
|
164
|
+
animate={{ x: 0 }}
|
|
165
|
+
exit={{ x: '-100%' }}
|
|
166
|
+
transition={{ type: 'spring', damping: 25, stiffness: 200 }}
|
|
167
|
+
className="fixed inset-y-0 left-0 w-[280px] bg-background z-50 lg:hidden"
|
|
168
|
+
>
|
|
169
|
+
<div className="p-4">
|
|
170
|
+
<button
|
|
171
|
+
className="absolute top-4 right-4 p-2"
|
|
172
|
+
onClick={() => setIsOpen(false)}
|
|
173
|
+
>
|
|
174
|
+
<XIcon className="h-6 w-6" />
|
|
175
|
+
</button>
|
|
176
|
+
<nav className="mt-8 space-y-2">
|
|
177
|
+
{navItems.map((item) => (
|
|
178
|
+
<a
|
|
179
|
+
key={item.href}
|
|
180
|
+
href={item.href}
|
|
181
|
+
className="block py-3 px-4 rounded-lg hover:bg-muted"
|
|
182
|
+
>
|
|
183
|
+
{item.label}
|
|
184
|
+
</a>
|
|
185
|
+
))}
|
|
186
|
+
</nav>
|
|
187
|
+
</div>
|
|
188
|
+
</motion.div>
|
|
189
|
+
</>
|
|
190
|
+
)}
|
|
191
|
+
</AnimatePresence>
|
|
192
|
+
</>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Responsive Tables
|
|
198
|
+
```tsx
|
|
199
|
+
// Card-based layout on mobile, table on desktop
|
|
200
|
+
export function ResponsiveTable({ data }: { data: Item[] }) {
|
|
201
|
+
return (
|
|
202
|
+
<>
|
|
203
|
+
{/* Mobile: Card layout */}
|
|
204
|
+
<div className="space-y-4 md:hidden">
|
|
205
|
+
{data.map((item) => (
|
|
206
|
+
<div key={item.id} className="rounded-lg border p-4">
|
|
207
|
+
<div className="flex justify-between">
|
|
208
|
+
<span className="font-medium">{item.name}</span>
|
|
209
|
+
<span className="text-muted-foreground">{item.date}</span>
|
|
210
|
+
</div>
|
|
211
|
+
<div className="mt-2 text-sm text-muted-foreground">
|
|
212
|
+
{item.description}
|
|
213
|
+
</div>
|
|
214
|
+
<div className="mt-3 flex justify-between items-center">
|
|
215
|
+
<span className="font-semibold">{item.amount}</span>
|
|
216
|
+
<Badge>{item.status}</Badge>
|
|
217
|
+
</div>
|
|
218
|
+
</div>
|
|
219
|
+
))}
|
|
220
|
+
</div>
|
|
221
|
+
|
|
222
|
+
{/* Desktop: Traditional table */}
|
|
223
|
+
<table className="hidden md:table w-full">
|
|
224
|
+
<thead>
|
|
225
|
+
<tr className="border-b">
|
|
226
|
+
<th className="text-left py-3">Name</th>
|
|
227
|
+
<th className="text-left py-3">Date</th>
|
|
228
|
+
<th className="text-left py-3">Amount</th>
|
|
229
|
+
<th className="text-left py-3">Status</th>
|
|
230
|
+
</tr>
|
|
231
|
+
</thead>
|
|
232
|
+
<tbody>
|
|
233
|
+
{data.map((item) => (
|
|
234
|
+
<tr key={item.id} className="border-b">
|
|
235
|
+
<td className="py-3">{item.name}</td>
|
|
236
|
+
<td className="py-3">{item.date}</td>
|
|
237
|
+
<td className="py-3">{item.amount}</td>
|
|
238
|
+
<td className="py-3"><Badge>{item.status}</Badge></td>
|
|
239
|
+
</tr>
|
|
240
|
+
))}
|
|
241
|
+
</tbody>
|
|
242
|
+
</table>
|
|
243
|
+
</>
|
|
244
|
+
)
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### Responsive Grid
|
|
249
|
+
```tsx
|
|
250
|
+
// Fluid grid that adapts to screen size
|
|
251
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
|
|
252
|
+
{items.map((item) => (
|
|
253
|
+
<Card key={item.id}>{item.content}</Card>
|
|
254
|
+
))}
|
|
255
|
+
</div>
|
|
256
|
+
|
|
257
|
+
// Auto-fit grid (items wrap naturally)
|
|
258
|
+
<div className="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-4">
|
|
259
|
+
{items.map((item) => (
|
|
260
|
+
<Card key={item.id}>{item.content}</Card>
|
|
261
|
+
))}
|
|
262
|
+
</div>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
## Touch Gestures
|
|
266
|
+
|
|
267
|
+
### Swipe to Delete
|
|
268
|
+
```tsx
|
|
269
|
+
'use client'
|
|
270
|
+
import { motion, useMotionValue, useTransform, PanInfo } from 'framer-motion'
|
|
271
|
+
|
|
272
|
+
export function SwipeableItem({ onDelete, children }: SwipeableItemProps) {
|
|
273
|
+
const x = useMotionValue(0)
|
|
274
|
+
const background = useTransform(
|
|
275
|
+
x,
|
|
276
|
+
[-100, 0],
|
|
277
|
+
['rgb(239 68 68)', 'rgb(255 255 255)']
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
const handleDragEnd = (_: any, info: PanInfo) => {
|
|
281
|
+
if (info.offset.x < -100) {
|
|
282
|
+
onDelete()
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
return (
|
|
287
|
+
<motion.div style={{ background }} className="relative overflow-hidden rounded-lg">
|
|
288
|
+
<motion.div
|
|
289
|
+
drag="x"
|
|
290
|
+
dragConstraints={{ left: -100, right: 0 }}
|
|
291
|
+
onDragEnd={handleDragEnd}
|
|
292
|
+
style={{ x }}
|
|
293
|
+
className="bg-background p-4"
|
|
294
|
+
>
|
|
295
|
+
{children}
|
|
296
|
+
</motion.div>
|
|
297
|
+
<div className="absolute right-4 top-1/2 -translate-y-1/2 text-white">
|
|
298
|
+
<TrashIcon className="h-5 w-5" />
|
|
299
|
+
</div>
|
|
300
|
+
</motion.div>
|
|
301
|
+
)
|
|
302
|
+
}
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### Pull to Refresh
|
|
306
|
+
```tsx
|
|
307
|
+
'use client'
|
|
308
|
+
import { useState, useRef } from 'react'
|
|
309
|
+
import { motion, useMotionValue, useTransform } from 'framer-motion'
|
|
310
|
+
|
|
311
|
+
export function PullToRefresh({ onRefresh, children }: PullToRefreshProps) {
|
|
312
|
+
const [isRefreshing, setIsRefreshing] = useState(false)
|
|
313
|
+
const y = useMotionValue(0)
|
|
314
|
+
const opacity = useTransform(y, [0, 60], [0, 1])
|
|
315
|
+
const scale = useTransform(y, [0, 60], [0.5, 1])
|
|
316
|
+
|
|
317
|
+
const handleDragEnd = async () => {
|
|
318
|
+
if (y.get() > 60) {
|
|
319
|
+
setIsRefreshing(true)
|
|
320
|
+
await onRefresh()
|
|
321
|
+
setIsRefreshing(false)
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div className="overflow-hidden">
|
|
327
|
+
<motion.div
|
|
328
|
+
style={{ opacity, scale }}
|
|
329
|
+
className="flex justify-center py-4"
|
|
330
|
+
>
|
|
331
|
+
<RefreshIcon className={cn('h-6 w-6', isRefreshing && 'animate-spin')} />
|
|
332
|
+
</motion.div>
|
|
333
|
+
<motion.div
|
|
334
|
+
drag="y"
|
|
335
|
+
dragConstraints={{ top: 0, bottom: 0 }}
|
|
336
|
+
dragElastic={0.5}
|
|
337
|
+
onDragEnd={handleDragEnd}
|
|
338
|
+
style={{ y }}
|
|
339
|
+
>
|
|
340
|
+
{children}
|
|
341
|
+
</motion.div>
|
|
342
|
+
</div>
|
|
343
|
+
)
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
## Mobile-Specific Components
|
|
348
|
+
|
|
349
|
+
### Bottom Sheet
|
|
350
|
+
```tsx
|
|
351
|
+
'use client'
|
|
352
|
+
import { motion, useDragControls, PanInfo } from 'framer-motion'
|
|
353
|
+
|
|
354
|
+
export function BottomSheet({ isOpen, onClose, children }: BottomSheetProps) {
|
|
355
|
+
const controls = useDragControls()
|
|
356
|
+
|
|
357
|
+
const handleDragEnd = (_: any, info: PanInfo) => {
|
|
358
|
+
if (info.velocity.y > 500 || info.offset.y > 200) {
|
|
359
|
+
onClose()
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
if (!isOpen) return null
|
|
364
|
+
|
|
365
|
+
return (
|
|
366
|
+
<>
|
|
367
|
+
<motion.div
|
|
368
|
+
initial={{ opacity: 0 }}
|
|
369
|
+
animate={{ opacity: 1 }}
|
|
370
|
+
exit={{ opacity: 0 }}
|
|
371
|
+
className="fixed inset-0 bg-black/50 z-40"
|
|
372
|
+
onClick={onClose}
|
|
373
|
+
/>
|
|
374
|
+
<motion.div
|
|
375
|
+
initial={{ y: '100%' }}
|
|
376
|
+
animate={{ y: 0 }}
|
|
377
|
+
exit={{ y: '100%' }}
|
|
378
|
+
drag="y"
|
|
379
|
+
dragControls={controls}
|
|
380
|
+
dragConstraints={{ top: 0 }}
|
|
381
|
+
dragElastic={0.2}
|
|
382
|
+
onDragEnd={handleDragEnd}
|
|
383
|
+
className="fixed bottom-0 left-0 right-0 bg-background rounded-t-xl z-50 max-h-[90vh] overflow-hidden"
|
|
384
|
+
>
|
|
385
|
+
{/* Drag handle */}
|
|
386
|
+
<div
|
|
387
|
+
className="flex justify-center py-3 cursor-grab active:cursor-grabbing"
|
|
388
|
+
onPointerDown={(e) => controls.start(e)}
|
|
389
|
+
>
|
|
390
|
+
<div className="w-12 h-1.5 bg-muted-foreground/30 rounded-full" />
|
|
391
|
+
</div>
|
|
392
|
+
<div className="px-4 pb-safe overflow-y-auto max-h-[calc(90vh-40px)]">
|
|
393
|
+
{children}
|
|
394
|
+
</div>
|
|
395
|
+
</motion.div>
|
|
396
|
+
</>
|
|
397
|
+
)
|
|
398
|
+
}
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
### Mobile-Optimized Forms
|
|
402
|
+
```tsx
|
|
403
|
+
// Stack form fields vertically on mobile
|
|
404
|
+
<form className="space-y-4">
|
|
405
|
+
<div className="grid gap-4 sm:grid-cols-2">
|
|
406
|
+
<div className="space-y-2">
|
|
407
|
+
<Label htmlFor="firstName">First Name</Label>
|
|
408
|
+
<Input
|
|
409
|
+
id="firstName"
|
|
410
|
+
// Larger touch targets
|
|
411
|
+
className="h-12 text-base"
|
|
412
|
+
// Prevent iOS zoom on focus
|
|
413
|
+
style={{ fontSize: '16px' }}
|
|
414
|
+
/>
|
|
415
|
+
</div>
|
|
416
|
+
<div className="space-y-2">
|
|
417
|
+
<Label htmlFor="lastName">Last Name</Label>
|
|
418
|
+
<Input
|
|
419
|
+
id="lastName"
|
|
420
|
+
className="h-12 text-base"
|
|
421
|
+
style={{ fontSize: '16px' }}
|
|
422
|
+
/>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
|
|
426
|
+
{/* Full-width button on mobile */}
|
|
427
|
+
<Button className="w-full sm:w-auto h-12">
|
|
428
|
+
Submit
|
|
429
|
+
</Button>
|
|
430
|
+
</form>
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## PWA Features
|
|
434
|
+
|
|
435
|
+
### Viewport & Meta Tags
|
|
436
|
+
```tsx
|
|
437
|
+
// app/layout.tsx
|
|
438
|
+
export const metadata = {
|
|
439
|
+
viewport: {
|
|
440
|
+
width: 'device-width',
|
|
441
|
+
initialScale: 1,
|
|
442
|
+
// No maximumScale / userScalable: false — the 16px inputs above already stop iOS focus-zoom,
|
|
443
|
+
// and disabling pinch-zoom fails WCAG 1.4.4
|
|
444
|
+
viewportFit: 'cover', // For notched devices
|
|
445
|
+
},
|
|
446
|
+
appleWebApp: {
|
|
447
|
+
capable: true,
|
|
448
|
+
statusBarStyle: 'default',
|
|
449
|
+
title: 'My App',
|
|
450
|
+
},
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Install Prompt
|
|
455
|
+
```tsx
|
|
456
|
+
'use client'
|
|
457
|
+
import { useEffect, useState } from 'react'
|
|
458
|
+
|
|
459
|
+
export function InstallPrompt() {
|
|
460
|
+
const [deferredPrompt, setDeferredPrompt] = useState<any>(null)
|
|
461
|
+
|
|
462
|
+
useEffect(() => {
|
|
463
|
+
const handler = (e: Event) => {
|
|
464
|
+
e.preventDefault()
|
|
465
|
+
setDeferredPrompt(e)
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
window.addEventListener('beforeinstallprompt', handler)
|
|
469
|
+
return () => window.removeEventListener('beforeinstallprompt', handler)
|
|
470
|
+
}, [])
|
|
471
|
+
|
|
472
|
+
if (!deferredPrompt) return null
|
|
473
|
+
|
|
474
|
+
const handleInstall = async () => {
|
|
475
|
+
deferredPrompt.prompt()
|
|
476
|
+
const { outcome } = await deferredPrompt.userChoice
|
|
477
|
+
if (outcome === 'accepted') {
|
|
478
|
+
setDeferredPrompt(null)
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
return (
|
|
483
|
+
<div className="fixed bottom-20 left-4 right-4 p-4 bg-card border rounded-lg shadow-lg">
|
|
484
|
+
<p className="font-medium">Install our app</p>
|
|
485
|
+
<p className="text-sm text-muted-foreground">Get quick access from your home screen</p>
|
|
486
|
+
<div className="mt-3 flex gap-2">
|
|
487
|
+
<Button onClick={handleInstall}>Install</Button>
|
|
488
|
+
<Button variant="ghost" onClick={() => setDeferredPrompt(null)}>
|
|
489
|
+
Not now
|
|
490
|
+
</Button>
|
|
491
|
+
</div>
|
|
492
|
+
</div>
|
|
493
|
+
)
|
|
494
|
+
}
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
## Validation [LOW freedom — do not skip]
|
|
498
|
+
|
|
499
|
+
Touch ≥44px · thumb-zone CTAs · gestures with feedback · 60fps · no focus-zoom · safe-area · offline-graceful · real device (not emulator-only).
|
|
500
|
+
|
|
501
|
+
## Related
|
|
502
|
+
|
|
503
|
+
- `audit-responsive` — unstack desktop; layout/IA at 375 / 768 / 1440
|
|
504
|
+
- `enhance-capacitor-ui` — hybrid web + native form-factor axes
|
|
505
|
+
- `design-frontend` — new visual surfaces
|
|
506
|
+
- `audit-performance` — mobile perf budgets
|