claude-code-superkit 0.0.0-stage → 1.5.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/LICENSE +21 -0
- package/README.md +374 -2
- package/bin/cli.js +153 -0
- package/bin/inject-tokens.js +224 -0
- package/bin/measure-tokens.js +17 -0
- package/bin/superkit-counts-verify.sh +30 -0
- package/lib/codex.js +246 -0
- package/lib/docs-scaffold.js +147 -0
- package/lib/installer.js +499 -0
- package/lib/prompts.js +51 -0
- package/lib/settings-builder.js +51 -0
- package/lib/superpowers.js +99 -0
- package/lib/utils.js +117 -0
- package/lib/validator.js +84 -0
- package/package.json +49 -4
- package/packages/codex/AGENTS.md +396 -0
- package/packages/codex/INSTALL.md +342 -0
- package/packages/codex/config.toml +22 -0
- package/packages/codex/hooks/superkit.mjs +203 -0
- package/packages/codex/hooks.json +30 -0
- package/packages/codex/legacy-baseline.json +88 -0
- package/packages/codex/native-skills.txt +65 -0
- package/packages/codex/rules/default.rules +565 -0
- package/packages/codex/skills/ai-slop-cleaner/SKILL.md +44 -0
- package/packages/codex/skills/api-contract-sync/SKILL.md +96 -0
- package/packages/codex/skills/architect/SKILL.md +49 -0
- package/packages/codex/skills/audit-backend/SKILL.md +80 -0
- package/packages/codex/skills/audit-frontend/SKILL.md +82 -0
- package/packages/codex/skills/audit-infra/SKILL.md +87 -0
- package/packages/codex/skills/audit-orchestrator/SKILL.md +114 -0
- package/packages/codex/skills/behavioral-nudge-engine/SKILL.md +110 -0
- package/packages/codex/skills/benchmark/SKILL.md +49 -0
- package/packages/codex/skills/bot-reviewer/SKILL.md +94 -0
- package/packages/codex/skills/code-reviewer/SKILL.md +67 -0
- package/packages/codex/skills/codebase-onboarding-engineer/SKILL.md +46 -0
- package/packages/codex/skills/comment-rot-analyzer/SKILL.md +75 -0
- package/packages/codex/skills/commit-helper/SKILL.md +101 -0
- package/packages/codex/skills/critic/SKILL.md +56 -0
- package/packages/codex/skills/database-reviewer/SKILL.md +79 -0
- package/packages/codex/skills/debug-observer/SKILL.md +107 -0
- package/packages/codex/skills/dependency-checker/SKILL.md +69 -0
- package/packages/codex/skills/design-system-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/dev-orchestrator/SKILL.md +304 -0
- package/packages/codex/skills/docs-reviewer/SKILL.md +86 -0
- package/packages/codex/skills/drizzle-orm-expert/SKILL.md +246 -0
- package/packages/codex/skills/e2e-test-generator/SKILL.md +95 -0
- package/packages/codex/skills/evaluator/SKILL.md +63 -0
- package/packages/codex/skills/frontend-perf-reviewer/SKILL.md +95 -0
- package/packages/codex/skills/frontend-ui-color-reviewer/SKILL.md +68 -0
- package/packages/codex/skills/frontend-ui-design-critic/SKILL.md +99 -0
- package/packages/codex/skills/frontend-ui-interaction-reviewer/SKILL.md +102 -0
- package/packages/codex/skills/frontend-ui-motion-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/frontend-ui-reviewer/SKILL.md +81 -0
- package/packages/codex/skills/frontend-ui-typography-reviewer/SKILL.md +62 -0
- package/packages/codex/skills/gltf-debugging/SKILL.md +128 -0
- package/packages/codex/skills/go-benchmark/SKILL.md +217 -0
- package/packages/codex/skills/go-concurrency-reviewer/SKILL.md +113 -0
- package/packages/codex/skills/go-error-reviewer/SKILL.md +107 -0
- package/packages/codex/skills/go-grpc-patterns/SKILL.md +285 -0
- package/packages/codex/skills/go-modernizer/SKILL.md +111 -0
- package/packages/codex/skills/go-observability-reviewer/SKILL.md +121 -0
- package/packages/codex/skills/go-performance-reviewer/SKILL.md +112 -0
- package/packages/codex/skills/go-reviewer/SKILL.md +109 -0
- package/packages/codex/skills/go-samber-do/SKILL.md +158 -0
- package/packages/codex/skills/go-samber-lo/SKILL.md +178 -0
- package/packages/codex/skills/go-samber-oops/SKILL.md +174 -0
- package/packages/codex/skills/goal-verifier/SKILL.md +53 -0
- package/packages/codex/skills/health-checker/SKILL.md +109 -0
- package/packages/codex/skills/html-to-3d-texture/SKILL.md +153 -0
- package/packages/codex/skills/impeccable-craft/SKILL.md +101 -0
- package/packages/codex/skills/lint-runner/SKILL.md +85 -0
- package/packages/codex/skills/migrate/SKILL.md +60 -0
- package/packages/codex/skills/migration-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/minimal-change-engineer/SKILL.md +44 -0
- package/packages/codex/skills/new-migration/SKILL.md +59 -0
- package/packages/codex/skills/nextjs-supabase-auth/SKILL.md +227 -0
- package/packages/codex/skills/output-enforcement/SKILL.md +71 -0
- package/packages/codex/skills/plan-checker/SKILL.md +53 -0
- package/packages/codex/skills/postgresql-optimization/SKILL.md +159 -0
- package/packages/codex/skills/pre-deploy-validator/SKILL.md +111 -0
- package/packages/codex/skills/presentation-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/product-3d-lighting/SKILL.md +137 -0
- package/packages/codex/skills/project-architecture/SKILL.md +52 -0
- package/packages/codex/skills/py-reviewer/SKILL.md +100 -0
- package/packages/codex/skills/r3f-scene-reviewer/SKILL.md +88 -0
- package/packages/codex/skills/r3f-scroll-driven-3d/SKILL.md +162 -0
- package/packages/codex/skills/reality-checker/SKILL.md +61 -0
- package/packages/codex/skills/redis-patterns/SKILL.md +260 -0
- package/packages/codex/skills/review-orchestrator/SKILL.md +151 -0
- package/packages/codex/skills/rs-reviewer/SKILL.md +98 -0
- package/packages/codex/skills/ru-text/SKILL.md +132 -0
- package/packages/codex/skills/scaffold-endpoint/SKILL.md +44 -0
- package/packages/codex/skills/security-scanner/SKILL.md +94 -0
- package/packages/codex/skills/silent-failure-hunter/SKILL.md +176 -0
- package/packages/codex/skills/telegram-bot-builder/SKILL.md +120 -0
- package/packages/codex/skills/test-generator/SKILL.md +79 -0
- package/packages/codex/skills/test-runner/SKILL.md +101 -0
- package/packages/codex/skills/threejs-color-management/SKILL.md +97 -0
- package/packages/codex/skills/tree-generator/SKILL.md +63 -0
- package/packages/codex/skills/ts-reviewer/SKILL.md +90 -0
- package/packages/codex/skills/ui-design-reviewer/SKILL.md +89 -0
- package/packages/codex/skills/ui-reviewer/SKILL.md +103 -0
- package/packages/codex/skills/visual-reviewer/SKILL.md +85 -0
- package/packages/codex/skills/writing-agents/SKILL.md +165 -0
- package/packages/codex/skills/writing-commands/SKILL.md +173 -0
- package/packages/core/CLAUDE.md +118 -0
- package/packages/core/INTERNAL-FILES +16 -0
- package/packages/core/agents/ai-slop-cleaner.md +187 -0
- package/packages/core/agents/api-contract-sync.md +127 -0
- package/packages/core/agents/architect.md +205 -0
- package/packages/core/agents/audit-backend.md +137 -0
- package/packages/core/agents/audit-frontend.md +129 -0
- package/packages/core/agents/audit-infra.md +182 -0
- package/packages/core/agents/behavioral-nudge-engine.md +170 -0
- package/packages/core/agents/code-reviewer.md +195 -0
- package/packages/core/agents/codebase-onboarding-engineer.md +172 -0
- package/packages/core/agents/comment-rot-analyzer.md +115 -0
- package/packages/core/agents/critic.md +172 -0
- package/packages/core/agents/database-reviewer.md +201 -0
- package/packages/core/agents/debug-observer.md +261 -0
- package/packages/core/agents/dependency-checker.md +199 -0
- package/packages/core/agents/docs-reviewer.md +206 -0
- package/packages/core/agents/e2e-test-generator.md +261 -0
- package/packages/core/agents/evaluator.md +141 -0
- package/packages/core/agents/goal-verifier.md +130 -0
- package/packages/core/agents/health-checker.md +194 -0
- package/packages/core/agents/migration-reviewer.md +161 -0
- package/packages/core/agents/minimal-change-engineer.md +219 -0
- package/packages/core/agents/plan-checker.md +139 -0
- package/packages/core/agents/pre-deploy-validator.md +189 -0
- package/packages/core/agents/reality-checker.md +175 -0
- package/packages/core/agents/scaffold-endpoint.md +162 -0
- package/packages/core/agents/security-scanner.md +236 -0
- package/packages/core/agents/silent-failure-hunter.md +276 -0
- package/packages/core/agents/test-generator.md +146 -0
- package/packages/core/agents/tree-generator.md +141 -0
- package/packages/core/agents/ui-reviewer.md +172 -0
- package/packages/core/agents/visual-reviewer.md +211 -0
- package/packages/core/commands/audit.md +166 -0
- package/packages/core/commands/benchmark.md +130 -0
- package/packages/core/commands/commit.md +148 -0
- package/packages/core/commands/dev.md +302 -0
- package/packages/core/commands/docs-init.md +75 -0
- package/packages/core/commands/lint.md +137 -0
- package/packages/core/commands/migrate.md +146 -0
- package/packages/core/commands/new-migration.md +182 -0
- package/packages/core/commands/pair.md +209 -0
- package/packages/core/commands/review.md +195 -0
- package/packages/core/commands/security-scan.md +142 -0
- package/packages/core/commands/superkit-evolve.md +231 -0
- package/packages/core/commands/superkit-init.md +274 -0
- package/packages/core/commands/test.md +108 -0
- package/packages/core/commands/workflow.md +150 -0
- package/packages/core/docs/guide/01-getting-started.md +41 -0
- package/packages/core/docs-templates/README.md +33 -0
- package/packages/core/docs-templates/adr-template.md +62 -0
- package/packages/core/docs-templates/architecture/api-contracts.md +26 -0
- package/packages/core/docs-templates/architecture/api-reference.md +48 -0
- package/packages/core/docs-templates/architecture/auth-and-sessions.md +38 -0
- package/packages/core/docs-templates/architecture/backend-layers.md +42 -0
- package/packages/core/docs-templates/architecture/data-flow.md +26 -0
- package/packages/core/docs-templates/architecture/database-schema.md +51 -0
- package/packages/core/docs-templates/architecture/deployment.md +41 -0
- package/packages/core/docs-templates/architecture/frontend-state.md +46 -0
- package/packages/core/helpers/statusline.cjs +370 -0
- package/packages/core/hooks/CHAIN-SEMANTICS.md +84 -0
- package/packages/core/hooks/audit-settings-source.sh +98 -0
- package/packages/core/hooks/audit-trail.sh +120 -0
- package/packages/core/hooks/block-dangerous-git.sh +189 -0
- package/packages/core/hooks/bundle-import-check.sh +64 -0
- package/packages/core/hooks/compact-state-inject.sh +84 -0
- package/packages/core/hooks/config-protection.sh +68 -0
- package/packages/core/hooks/console-log-warning.sh +28 -0
- package/packages/core/hooks/context-monitor.sh +35 -0
- package/packages/core/hooks/dev-edit-counter.sh +59 -0
- package/packages/core/hooks/dev-marker-set.sh +55 -0
- package/packages/core/hooks/dev-required-on-commit.sh +426 -0
- package/packages/core/hooks/doc-check-on-commit.sh +396 -0
- package/packages/core/hooks/edit-streak-check.sh +63 -0
- package/packages/core/hooks/evolve-check.sh +78 -0
- package/packages/core/hooks/gateguard-pre-edit.sh +154 -0
- package/packages/core/hooks/gateguard-record-facts.sh +37 -0
- package/packages/core/hooks/intake-classifier.py +449 -0
- package/packages/core/hooks/lib/profile.sh +141 -0
- package/packages/core/hooks/loop-guard.sh +75 -0
- package/packages/core/hooks/migration-safety.sh +56 -0
- package/packages/core/hooks/plan-completion-gate.sh +61 -0
- package/packages/core/hooks/pre-compact-save.sh +89 -0
- package/packages/core/hooks/security-patterns.sh +119 -0
- package/packages/core/hooks/session-context-restore.sh +76 -0
- package/packages/core/hooks/subagent-stop-validate.sh +73 -0
- package/packages/core/hooks/superkit-counts-verify.sh +346 -0
- package/packages/core/hooks/superkit-update.sh +367 -0
- package/packages/core/hooks/tests/README.md +42 -0
- package/packages/core/hooks/tests/audit-trail-chain_test.sh +62 -0
- package/packages/core/hooks/tests/block-dangerous-git_test.sh +144 -0
- package/packages/core/hooks/tests/chain-semantics/h1.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/h2.sh +9 -0
- package/packages/core/hooks/tests/chain-semantics/h3.sh +11 -0
- package/packages/core/hooks/tests/chain-semantics/run-experiment.sh +65 -0
- package/packages/core/hooks/tests/chain-semantics/settings-experiment.json +15 -0
- package/packages/core/hooks/tests/counts-verify_test.sh +118 -0
- package/packages/core/hooks/tests/dev-required-on-commit_test.sh +207 -0
- package/packages/core/hooks/tests/dev-required-wip-on-main_test.sh +20 -0
- package/packages/core/hooks/tests/doc-check-on-commit_test.sh +122 -0
- package/packages/core/hooks/tests/edit-streak-check_test.sh +106 -0
- package/packages/core/hooks/tests/internal-manifest_test.sh +130 -0
- package/packages/core/hooks/tests/json-path_test.sh +108 -0
- package/packages/core/hooks/tests/mirror-invariants_test.sh +139 -0
- package/packages/core/hooks/tests/nudge-throttle_test.sh +95 -0
- package/packages/core/hooks/tests/profile-helper_test.sh +21 -0
- package/packages/core/hooks/tests/run-all.sh +47 -0
- package/packages/core/hooks/tests/session-key-helper_test.sh +17 -0
- package/packages/core/hooks/tests/superkit-update_test.sh +311 -0
- package/packages/core/hooks/tests/warn-visibility_test.sh +59 -0
- package/packages/core/hooks/user-intent-detect.sh +44 -0
- package/packages/core/hooks/verify-hooks.sh +69 -0
- package/packages/core/rules/auto-commands.md +124 -0
- package/packages/core/rules/coding-style.md +68 -0
- package/packages/core/rules/dev-workflow.md +77 -0
- package/packages/core/rules/documentation.md +106 -0
- package/packages/core/rules/frontend-aesthetics.md +53 -0
- package/packages/core/rules/git-workflow.md +14 -0
- package/packages/core/rules/security.md +29 -0
- package/packages/core/rules/superkit-integrity.md +114 -0
- package/packages/core/settings.json +229 -0
- package/packages/core/skills/drizzle-orm-expert/SKILL.md +260 -0
- package/packages/core/skills/nextjs-supabase-auth/SKILL.md +259 -0
- package/packages/core/skills/postgresql-optimization/SKILL.md +150 -0
- package/packages/core/skills/project-architecture/SKILL.md +31 -0
- package/packages/core/skills/project-scanner/SKILL.md +132 -0
- package/packages/core/skills/redis-patterns/SKILL.md +261 -0
- package/packages/core/skills/ru-text/SKILL.md +156 -0
- package/packages/core/skills/telegram-bot-builder/SKILL.md +145 -0
- package/packages/core/skills/writing-agents/SKILL.md +220 -0
- package/packages/core/skills/writing-commands/SKILL.md +176 -0
- package/packages/core/skills/writing-hooks/SKILL.md +335 -0
- package/packages/extras/bot-reviewer.md +279 -0
- package/packages/extras/design-system-reviewer.md +234 -0
- package/packages/extras/red-blue-auditor/README.md +117 -0
- package/packages/extras/red-blue-auditor/agent.md +128 -0
- package/packages/extras/red-blue-auditor/patterns/agent-config.txt +4 -0
- package/packages/extras/red-blue-auditor/patterns/hook-injection.txt +8 -0
- package/packages/extras/red-blue-auditor/patterns/mcp-risk.txt +5 -0
- package/packages/extras/red-blue-auditor/patterns/permission-abuse.txt +6 -0
- package/packages/extras/red-blue-auditor/patterns/secrets.txt +17 -0
- package/packages/extras/red-blue-auditor/scan.sh +88 -0
- package/packages/extras/skillsmp-search/SKILL.md +134 -0
- package/packages/frontend-3d/README.md +62 -0
- package/packages/frontend-3d/agents/frontend-perf-reviewer.md +164 -0
- package/packages/frontend-3d/agents/presentation-reviewer.md +146 -0
- package/packages/frontend-3d/agents/r3f-scene-reviewer.md +128 -0
- package/packages/frontend-3d/agents/ui-design-reviewer.md +169 -0
- package/packages/frontend-3d/commands/capture-screen.md +166 -0
- package/packages/frontend-3d/hooks/bundle-size-warn.sh +93 -0
- package/packages/frontend-3d/hooks/gsap-pattern-check.sh +74 -0
- package/packages/frontend-3d/hooks/r3f-color-check.sh +76 -0
- package/packages/frontend-3d/hooks/tailwind-version-guard.sh +98 -0
- package/packages/frontend-3d/rules/frontend-aesthetics-3d.md +81 -0
- package/packages/frontend-3d/rules/gsap-conventions.md +129 -0
- package/packages/frontend-3d/rules/threejs-conventions.md +116 -0
- package/packages/frontend-3d/skills/gltf-debugging/SKILL.md +145 -0
- package/packages/frontend-3d/skills/html-to-3d-texture/SKILL.md +183 -0
- package/packages/frontend-3d/skills/output-enforcement/SKILL.md +79 -0
- package/packages/frontend-3d/skills/product-3d-lighting/SKILL.md +166 -0
- package/packages/frontend-3d/skills/r3f-scroll-driven-3d/SKILL.md +209 -0
- package/packages/frontend-3d/skills/threejs-color-management/SKILL.md +111 -0
- package/packages/frontend-ui/NOTICE.md +99 -0
- package/packages/frontend-ui/README.md +59 -0
- package/packages/frontend-ui/agents/ui-color-reviewer.md +174 -0
- package/packages/frontend-ui/agents/ui-design-critic.md +198 -0
- package/packages/frontend-ui/agents/ui-interaction-reviewer.md +259 -0
- package/packages/frontend-ui/agents/ui-motion-reviewer.md +266 -0
- package/packages/frontend-ui/agents/ui-reviewer.md +251 -0
- package/packages/frontend-ui/agents/ui-typography-reviewer.md +222 -0
- package/packages/frontend-ui/hooks/tests/ui-animation-easing-check_test.sh +78 -0
- package/packages/frontend-ui/hooks/tests/ui-banned-fonts-check_test.sh +77 -0
- package/packages/frontend-ui/hooks/tests/ui-color-check_test.sh +75 -0
- package/packages/frontend-ui/hooks/ui-animation-easing-check.sh +86 -0
- package/packages/frontend-ui/hooks/ui-banned-fonts-check.sh +90 -0
- package/packages/frontend-ui/hooks/ui-color-check.sh +102 -0
- package/packages/frontend-ui/rules/color-and-contrast.md +230 -0
- package/packages/frontend-ui/rules/frontend-design-aesthetics.md +124 -0
- package/packages/frontend-ui/rules/interaction-polish.md +335 -0
- package/packages/frontend-ui/rules/motion-and-animation.md +283 -0
- package/packages/frontend-ui/rules/spatial-and-layout.md +212 -0
- package/packages/frontend-ui/rules/typography-guidelines.md +185 -0
- package/packages/frontend-ui/rules/ui-anti-patterns.md +309 -0
- package/packages/frontend-ui/settings.json +24 -0
- package/packages/frontend-ui/skills/impeccable-craft/SKILL.md +187 -0
- package/packages/gan/README.md +232 -0
- package/packages/gan/agents/gan-evaluator.md +214 -0
- package/packages/gan/agents/gan-generator.md +171 -0
- package/packages/gan/agents/gan-planner.md +206 -0
- package/packages/gan/rubrics/functionality.md +66 -0
- package/packages/gan/rubrics/ui-quality.md +77 -0
- package/packages/gan/skills/gan-evaluator/SKILL.md +91 -0
- package/packages/gan/skills/gan-generator/SKILL.md +72 -0
- package/packages/gan/skills/gan-planner/SKILL.md +93 -0
- package/packages/stack-agents/go/go-concurrency-reviewer.md +210 -0
- package/packages/stack-agents/go/go-error-reviewer.md +187 -0
- package/packages/stack-agents/go/go-modernizer.md +160 -0
- package/packages/stack-agents/go/go-observability-reviewer.md +185 -0
- package/packages/stack-agents/go/go-performance-reviewer.md +160 -0
- package/packages/stack-agents/go/go-reviewer.md +277 -0
- package/packages/stack-agents/go/references/benchmark-methodology.md +280 -0
- package/packages/stack-agents/go/references/channel-patterns.md +384 -0
- package/packages/stack-agents/go/references/cli-cobra-viper.md +190 -0
- package/packages/stack-agents/go/references/code-style.md +262 -0
- package/packages/stack-agents/go/references/context-propagation.md +317 -0
- package/packages/stack-agents/go/references/data-structures.md +315 -0
- package/packages/stack-agents/go/references/database-patterns.md +334 -0
- package/packages/stack-agents/go/references/design-patterns.md +411 -0
- package/packages/stack-agents/go/references/di-frameworks.md +146 -0
- package/packages/stack-agents/go/references/error-creation.md +251 -0
- package/packages/stack-agents/go/references/error-inspection.md +348 -0
- package/packages/stack-agents/go/references/error-wrapping.md +230 -0
- package/packages/stack-agents/go/references/gopls-driving.md +62 -0
- package/packages/stack-agents/go/references/goroutine-lifecycle.md +351 -0
- package/packages/stack-agents/go/references/graphql-patterns.md +221 -0
- package/packages/stack-agents/go/references/grpc-patterns.md +373 -0
- package/packages/stack-agents/go/references/modernize-guide.md +522 -0
- package/packages/stack-agents/go/references/module-management.md +191 -0
- package/packages/stack-agents/go/references/naming-conventions.md +176 -0
- package/packages/stack-agents/go/references/observability-pipeline.md +352 -0
- package/packages/stack-agents/go/references/performance-profiling.md +250 -0
- package/packages/stack-agents/go/references/refactoring-mechanics.md +127 -0
- package/packages/stack-agents/go/references/rest-openapi-patterns.md +160 -0
- package/packages/stack-agents/go/references/samber-do.md +201 -0
- package/packages/stack-agents/go/references/samber-libraries.md +363 -0
- package/packages/stack-agents/go/references/samber-lo.md +260 -0
- package/packages/stack-agents/go/references/samber-oops.md +200 -0
- package/packages/stack-agents/go/references/security-checklist.md +441 -0
- package/packages/stack-agents/go/references/standard-stdlib-now.md +181 -0
- package/packages/stack-agents/go/references/stay-updated.md +147 -0
- package/packages/stack-agents/go/references/structs-interfaces.md +312 -0
- package/packages/stack-agents/go/references/sync-primitives.md +395 -0
- package/packages/stack-agents/go/references/testing-patterns.md +483 -0
- package/packages/stack-agents/go/references/troubleshooting.md +98 -0
- package/packages/stack-agents/python/py-reviewer.md +194 -0
- package/packages/stack-agents/rust/rs-reviewer.md +188 -0
- package/packages/stack-agents/typescript/ts-reviewer.md +135 -0
- package/packages/stack-hooks/go/go-context-check-on-edit.sh +56 -0
- package/packages/stack-hooks/go/go-error-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-format-on-edit.sh +32 -0
- package/packages/stack-hooks/go/go-safety-check-on-edit.sh +54 -0
- package/packages/stack-hooks/go/go-vet-on-edit.sh +61 -0
- package/packages/stack-hooks/go/golangci-lint-on-edit.sh +54 -0
- package/packages/stack-hooks/python/ruff-on-edit.sh +67 -0
- package/packages/stack-hooks/rust/cargo-check-on-edit.sh +64 -0
- package/packages/stack-hooks/typescript/typecheck-on-edit.sh +76 -0
- package/packages/stack-rules/go/go-conventions.md +44 -0
- package/packages/stack-rules/go/go-safety.md +35 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
applyWhenPaths:
|
|
4
|
+
- "**/presentation/**/*.tsx"
|
|
5
|
+
- "**/presentation/**/*.jsx"
|
|
6
|
+
- "**/landing/**/*.tsx"
|
|
7
|
+
- "**/landing/**/*.jsx"
|
|
8
|
+
tokens: 685
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Frontend Aesthetics — 3D & Presentation
|
|
12
|
+
|
|
13
|
+
Aesthetics rules for 3D-enhanced presentation/landing pages. If the core `frontend-aesthetics` rule is installed, this extends it with animation and 3D-specific patterns; every rule below also stands on its own.
|
|
14
|
+
|
|
15
|
+
## 1. Anti-Center Bias
|
|
16
|
+
|
|
17
|
+
When a section contains more than 4 visual elements (cards, CTAs, images, 3D objects), do not center everything — pick one of:
|
|
18
|
+
- Split screen: content left, 3D right (or vice versa)
|
|
19
|
+
- Asymmetric layout with intentional negative space
|
|
20
|
+
- 3D element offset from center for visual interest
|
|
21
|
+
|
|
22
|
+
## 2. Cards Only When Earned
|
|
23
|
+
|
|
24
|
+
Use a card only when elevation communicates hierarchy — never as the default container. If every section is a card, nothing has emphasis.
|
|
25
|
+
|
|
26
|
+
## 3. Viewport Units
|
|
27
|
+
|
|
28
|
+
```tsx
|
|
29
|
+
// WRONG — iOS Safari address bar causes jumping
|
|
30
|
+
h-screen
|
|
31
|
+
|
|
32
|
+
// RIGHT — dynamic viewport height
|
|
33
|
+
min-h-[100dvh]
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 4. Grid Over Flex Math
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
// WRONG — fragile percentage calculations
|
|
40
|
+
<div className="flex">
|
|
41
|
+
<div className="w-[calc(50%-12px)]">
|
|
42
|
+
|
|
43
|
+
// RIGHT — explicit grid
|
|
44
|
+
<div className="grid grid-cols-2 gap-6">
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## 5. Staggered Reveals
|
|
48
|
+
|
|
49
|
+
List/grid items MUST use staggered entrance — batch pop-in (all items appearing simultaneously) looks cheap.
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
// 0.05-0.1s delay between items (GSAP)
|
|
53
|
+
stagger: { each: 0.08, from: 'start' }
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 6. Spring Physics for Interactions
|
|
57
|
+
|
|
58
|
+
For interactive presentation elements (hover cards, draggable 3D, mouse-tracking) on Framer Motion stacks (`framer-motion` / `motion`):
|
|
59
|
+
|
|
60
|
+
```tsx
|
|
61
|
+
// WRONG — robotic
|
|
62
|
+
transition={{ duration: 0.3, ease: 'linear' }}
|
|
63
|
+
|
|
64
|
+
// RIGHT — natural feel
|
|
65
|
+
transition={{ type: 'spring', stiffness: 300, damping: 20 }}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
GSAP has no `type: 'spring'` — never paste these props into a GSAP tween. On GSAP-only stacks use an ease instead (`ease: 'back.out(1.7)'` for interactive pops; for scroll/3D ease choices see the Ease Standards table in `gsap-conventions.md`). Simple open/close state transitions in plain 2D UI follow the frontend-ui `motion-and-animation.md` rule when installed: duration-based ease-out, not springs.
|
|
69
|
+
|
|
70
|
+
## 7. 3D Scene Atmosphere
|
|
71
|
+
|
|
72
|
+
- Dark backgrounds: ambient < 0.3, dramatic key light
|
|
73
|
+
- Light backgrounds: ambient 0.7–0.8, soft even lighting
|
|
74
|
+
- Add `<Float>` for idle animation (static 3D looks dead) — EXCEPT when `window.matchMedia('(prefers-reduced-motion: reduce)')` matches: render the scene without idle motion
|
|
75
|
+
- `ContactShadows` for grounding — floating objects feel disconnected
|
|
76
|
+
|
|
77
|
+
## 8. Scroll-Driven 3D
|
|
78
|
+
|
|
79
|
+
- The 3D model MUST respond to scroll — rotation, scale, material changes
|
|
80
|
+
- Use phase-based animation (entry → showcase → transition → exit); each phase has a clear visual purpose — no random motion
|
|
81
|
+
- Timeline and scrub mechanics follow `gsap-conventions.md`
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
applyWhenPaths:
|
|
4
|
+
- "**/presentation/**"
|
|
5
|
+
- "**/src/**/*.tsx"
|
|
6
|
+
- "**/src/**/*.jsx"
|
|
7
|
+
tokens: 827
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# GSAP ScrollTrigger Conventions
|
|
11
|
+
|
|
12
|
+
Mandatory rules for GSAP scroll-driven animation code. Violations cause visual bugs.
|
|
13
|
+
|
|
14
|
+
**Scope:** this rule governs scroll-scrubbed presentation timelines and 3D scene motion. Interactive 2D UI element transitions (buttons, dropdowns, modals, hovers) follow `motion-and-animation.md` (frontend-ui package) instead — including its ease rules.
|
|
15
|
+
|
|
16
|
+
## 1. Timeline Extension — normalized scrub timelines ONLY
|
|
17
|
+
|
|
18
|
+
Precondition — apply this rule only when BOTH hold:
|
|
19
|
+
|
|
20
|
+
- the timeline is driven by ScrollTrigger `scrub`, AND
|
|
21
|
+
- its positions are normalized to the 0–1 range (the Phase Object pattern, rule 6).
|
|
22
|
+
|
|
23
|
+
Then, immediately after creating the timeline, add:
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
tl.set({}, {}, 1.0); // no-op keyframe at position 1.0 — forces timeline to span the full 0–1 range
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
**Why:** without it, animations compress into the first ~10% of the scroll range.
|
|
30
|
+
|
|
31
|
+
Duration-based (non-scrub) timelines: do NOT add this line — position `1.0` is meaningless there and inserts a stray keyframe.
|
|
32
|
+
|
|
33
|
+
## 2. Scrub Must Be a Number
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
// WRONG
|
|
37
|
+
scrub: true
|
|
38
|
+
|
|
39
|
+
// RIGHT
|
|
40
|
+
scrub: 1 // standard smoothness
|
|
41
|
+
scrub: 0.5 // snappier
|
|
42
|
+
scrub: 0.3 // very responsive
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Why:** `scrub: true` (boolean) causes jerky, non-smooth scrolling behavior.
|
|
46
|
+
|
|
47
|
+
## 3. invalidateOnRefresh
|
|
48
|
+
|
|
49
|
+
Every ScrollTrigger config MUST include:
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
scrollTrigger: {
|
|
53
|
+
invalidateOnRefresh: true,
|
|
54
|
+
// ... other config
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Why:** without it, calculated positions break on window resize.
|
|
59
|
+
|
|
60
|
+
## 4. Context Cleanup
|
|
61
|
+
|
|
62
|
+
All animations MUST be inside `gsap.context()` with cleanup:
|
|
63
|
+
|
|
64
|
+
```tsx
|
|
65
|
+
useEffect(() => {
|
|
66
|
+
const ctx = gsap.context(() => {
|
|
67
|
+
// all animations here
|
|
68
|
+
}, containerRef);
|
|
69
|
+
|
|
70
|
+
return () => ctx.revert();
|
|
71
|
+
}, []);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**Why:** without context, animations leak memory and break on React re-renders.
|
|
75
|
+
|
|
76
|
+
## 5. Centralized GSAP Import
|
|
77
|
+
|
|
78
|
+
Import GSAP from the project's setup module, never directly:
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// WRONG
|
|
82
|
+
import gsap from 'gsap';
|
|
83
|
+
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
84
|
+
|
|
85
|
+
// RIGHT
|
|
86
|
+
import { gsap, ScrollTrigger } from '@/lib/gsap-setup';
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
If no setup module exists yet, create one first (adjust the path to the project's alias):
|
|
90
|
+
|
|
91
|
+
```tsx
|
|
92
|
+
// lib/gsap-setup.ts
|
|
93
|
+
import gsap from 'gsap';
|
|
94
|
+
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
95
|
+
|
|
96
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
97
|
+
|
|
98
|
+
export { gsap, ScrollTrigger };
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Why:** ensures plugins are registered exactly once, consistently.
|
|
102
|
+
|
|
103
|
+
## 6. Phase Object for Timeline Positions
|
|
104
|
+
|
|
105
|
+
Use named constants, not magic numbers:
|
|
106
|
+
|
|
107
|
+
```tsx
|
|
108
|
+
const P = {
|
|
109
|
+
entryStart: 0,
|
|
110
|
+
entryEnd: 0.25,
|
|
111
|
+
showcaseStart: 0.25,
|
|
112
|
+
showcaseEnd: 0.7,
|
|
113
|
+
exitStart: 0.7,
|
|
114
|
+
exitEnd: 1.0,
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
tl.fromTo(element, { opacity: 0 }, { opacity: 1, duration: P.entryEnd - P.entryStart }, P.entryStart);
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
## 7. Ease Standards — scroll/3D contexts only
|
|
121
|
+
|
|
122
|
+
This table applies to scroll-scrubbed timelines and 3D scene motion. For 2D UI element transitions, use the ease rules in `motion-and-animation.md` (frontend-ui package): ease-out there, never ease-in.
|
|
123
|
+
|
|
124
|
+
| Use Case | Ease | Why |
|
|
125
|
+
|----------|------|-----|
|
|
126
|
+
| Entrances | `power3.out` | Fast start, gentle stop |
|
|
127
|
+
| Crossfades | `power2.inOut` | Smooth both directions |
|
|
128
|
+
| Subtle motion | `sine.in` / `sine.out` | Barely perceptible |
|
|
129
|
+
| Viewport exits | `power2.in` | Gentle start, fast finish — allowed for scroll/3D exits only |
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
alwaysApply: false
|
|
3
|
+
applyWhenPaths:
|
|
4
|
+
- "**/components/3d/**"
|
|
5
|
+
- "**/three/**"
|
|
6
|
+
- "**/scene/**"
|
|
7
|
+
- "**/r3f/**"
|
|
8
|
+
tokens: 870
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Three.js / R3F Conventions
|
|
12
|
+
|
|
13
|
+
Mandatory rules for React Three Fiber and Three.js code. For debugging wrong-looking colors (washed out, oversaturated, too dark), load the `threejs-color-management` skill — the settings below match its pipeline.
|
|
14
|
+
|
|
15
|
+
## 1. UI Screen Textures
|
|
16
|
+
|
|
17
|
+
Textures representing UI (screenshots, app screens) on 3D models:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
<meshBasicMaterial
|
|
21
|
+
map={screenTexture}
|
|
22
|
+
toneMapped={false}
|
|
23
|
+
/>
|
|
24
|
+
// + screenTexture.colorSpace = THREE.SRGBColorSpace
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**Rules:**
|
|
28
|
+
- Use `meshBasicMaterial` — screens emit light, they don't reflect it
|
|
29
|
+
- NEVER `MeshStandardMaterial` for display screens
|
|
30
|
+
- Set `toneMapped={false}` — prevents ACES tone mapping from distorting UI colors
|
|
31
|
+
- Set `texture.colorSpace = THREE.SRGBColorSpace` for any photo/UI texture; data textures (normal, roughness) stay `THREE.LinearSRGBColorSpace`
|
|
32
|
+
- Never `sRGBEncoding` / `texture.encoding` — deprecated since r152; use `colorSpace`
|
|
33
|
+
- Set Canvas `gl={{ toneMapping: THREE.NoToneMapping }}` when a UI/screen texture occupies the majority of the frame or is the hero object; otherwise keep the R3F default (`THREE.ACESFilmicToneMapping`) for realistic scenes. Always write the named constant, never bare `0`.
|
|
34
|
+
|
|
35
|
+
## 2. UV Settings on Texture Replacement
|
|
36
|
+
|
|
37
|
+
When replacing a material's texture map, MUST copy ALL UV settings:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
newTexture.flipY = oldTexture.flipY;
|
|
41
|
+
newTexture.wrapS = oldTexture.wrapS;
|
|
42
|
+
newTexture.wrapT = oldTexture.wrapT;
|
|
43
|
+
newTexture.offset.copy(oldTexture.offset);
|
|
44
|
+
newTexture.repeat.copy(oldTexture.repeat);
|
|
45
|
+
newTexture.rotation = oldTexture.rotation;
|
|
46
|
+
newTexture.center.copy(oldTexture.center);
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
**Why:** Forgetting any of these causes texture misalignment, stretching, or mirroring.
|
|
50
|
+
|
|
51
|
+
Also set `newTexture.colorSpace` per Section 1 — the seven lines above do not copy it.
|
|
52
|
+
|
|
53
|
+
## 3. GLB Preloading
|
|
54
|
+
|
|
55
|
+
Always preload at module level (outside the component):
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
useGLTF.preload('/models/phone.glb');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
**Why:** Without preload, model loads on mount causing visible pop-in.
|
|
62
|
+
|
|
63
|
+
## 4. useFrame Performance
|
|
64
|
+
|
|
65
|
+
```tsx
|
|
66
|
+
// WRONG — allocates on every frame (60fps = 60 allocations/sec)
|
|
67
|
+
useFrame(() => {
|
|
68
|
+
const pos = new THREE.Vector3(1, 2, 3);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// RIGHT — pre-allocate in ref
|
|
72
|
+
const tempVec = useRef(new THREE.Vector3());
|
|
73
|
+
useFrame(() => {
|
|
74
|
+
tempVec.current.set(1, 2, 3);
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
## 5. Zustand in useFrame
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
// WRONG — hook subscription triggers re-renders
|
|
82
|
+
const progress = useStore((s) => s.progress);
|
|
83
|
+
useFrame(() => { /* use progress */ });
|
|
84
|
+
|
|
85
|
+
// RIGHT — direct read, no re-renders
|
|
86
|
+
useFrame(() => {
|
|
87
|
+
const { progress } = useStore.getState();
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 6. DPR Settings
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
<Canvas dpr={[1, 2]}>
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Higher values degrade mobile performance with minimal visual benefit.
|
|
98
|
+
|
|
99
|
+
## 7. Disposal
|
|
100
|
+
|
|
101
|
+
Pick the branch by how the asset is used:
|
|
102
|
+
|
|
103
|
+
| Asset | Rule |
|
|
104
|
+
|-------|------|
|
|
105
|
+
| Shared/preloaded GLTF (`useGLTF`, rendered in more than one place or preloaded via `useGLTF.preload`) | Wrap in `<group dispose={null}>` — the loader cache owns the asset; auto-disposal on unmount would break every other consumer |
|
|
106
|
+
| One-off geometry/material/texture declared in JSX, used by a single component | No `dispose={null}` — R3F disposes it automatically on unmount |
|
|
107
|
+
| Objects created imperatively (`new THREE.CanvasTexture(...)`, render targets) | Call `.dispose()` yourself in the `useEffect` cleanup |
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
// Shared/preloaded model — protect the cached asset:
|
|
111
|
+
<group dispose={null}>
|
|
112
|
+
<Model />
|
|
113
|
+
</group>
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Do NOT put `dispose={null}` on one-off scenes — that leaks GPU memory on unmount.
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: gltf-debugging
|
|
3
|
+
description: Runtime GLB/GLTF inspection — traverse nodes, identify screen meshes, inspect UV coordinates, material property dumping, fixing exported materials at runtime. Use when textures don't map correctly to 3D models.
|
|
4
|
+
tokens: 1419
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# GLTF/GLB Debugging
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Runtime inspection recipes for when textures don't map correctly onto a loaded GLB/GLTF model: traverse meshes, check UV coordinates, dump material properties, replace textures without breaking UV mapping.
|
|
12
|
+
|
|
13
|
+
## Use when / Do not use
|
|
14
|
+
|
|
15
|
+
**Use when:** a texture renders wrong on a GLB/GLTF (stretched, black, mirrored, on the wrong mesh), or you need to find which mesh is the "screen"/target surface in a model.
|
|
16
|
+
**Do not use for:** general color-space pipeline setup (see `threejs-color-management`) or scroll/animation issues (see `r3f-scroll-driven-3d`).
|
|
17
|
+
|
|
18
|
+
## Hard Rules
|
|
19
|
+
|
|
20
|
+
1. Run Steps 1→4 in order. Inspect before fixing — never guess at a fix without traversal + UV + material data.
|
|
21
|
+
2. NEVER modify a mesh's material in place. Clone first (`mesh.material = mat.clone()`) — exported materials are often shared across meshes.
|
|
22
|
+
3. When replacing a texture, copy ALL 7 UV settings from the old map: `flipY`, `wrapS`, `wrapT`, `offset`, `repeat`, `rotation`, `center`. Missing even one causes flipped/offset textures.
|
|
23
|
+
4. After any texture or material change, set both `texture.needsUpdate = true` AND `material.needsUpdate = true`.
|
|
24
|
+
5. `colorSpace = THREE.SRGBColorSpace` + `toneMapped = false` applies to color/UI/photo maps (`.map`) ONLY. Data textures (`normalMap`, `roughnessMap`, `metalnessMap`, `aoMap`) use `THREE.LinearSRGBColorSpace` and keep `toneMapped` as exported.
|
|
25
|
+
|
|
26
|
+
## Workflow
|
|
27
|
+
|
|
28
|
+
Optional pre-check (offline, before touching runtime code) — list scenes, meshes, materials, and textures of the file:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
npx @gltf-transform/cli inspect model.glb
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Step 1 — Traverse All Meshes
|
|
35
|
+
|
|
36
|
+
See what's in the model; find the target mesh by name.
|
|
37
|
+
|
|
38
|
+
```tsx
|
|
39
|
+
useEffect(() => {
|
|
40
|
+
scene.traverse((child) => {
|
|
41
|
+
if ((child as THREE.Mesh).isMesh) {
|
|
42
|
+
const mesh = child as THREE.Mesh;
|
|
43
|
+
console.log(`Mesh: ${mesh.name}`, {
|
|
44
|
+
geometry: mesh.geometry.attributes,
|
|
45
|
+
material: (mesh.material as THREE.Material).type,
|
|
46
|
+
visible: mesh.visible,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}, [scene]);
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 2 — Inspect UV Coordinates
|
|
54
|
+
|
|
55
|
+
UV coordinates map 2D textures onto 3D geometry. Range 0–1 = good.
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
const geo = mesh.geometry;
|
|
59
|
+
const uvAttr = geo.attributes.uv;
|
|
60
|
+
|
|
61
|
+
if (!uvAttr) {
|
|
62
|
+
console.error(`${mesh.name}: NO UV coordinates!`);
|
|
63
|
+
// Fix: re-export from Blender with UV map
|
|
64
|
+
} else {
|
|
65
|
+
// Check UV range
|
|
66
|
+
let minU = Infinity, maxU = -Infinity;
|
|
67
|
+
let minV = Infinity, maxV = -Infinity;
|
|
68
|
+
for (let i = 0; i < uvAttr.count; i++) {
|
|
69
|
+
const u = uvAttr.getX(i), v = uvAttr.getY(i);
|
|
70
|
+
minU = Math.min(minU, u); maxU = Math.max(maxU, u);
|
|
71
|
+
minV = Math.min(minV, v); maxV = Math.max(maxV, v);
|
|
72
|
+
}
|
|
73
|
+
console.log(`${mesh.name} UV range: U[${minU},${maxU}] V[${minV},${maxV}]`);
|
|
74
|
+
// [0,1] = single texture fill. [0,0.5] = uses half the texture (atlas)
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Step 3 — Dump Material Properties
|
|
79
|
+
|
|
80
|
+
```tsx
|
|
81
|
+
const mat = mesh.material as THREE.MeshStandardMaterial;
|
|
82
|
+
console.log(`${mesh.name} material:`, {
|
|
83
|
+
type: mat.type,
|
|
84
|
+
map: mat.map ? 'yes' : 'no',
|
|
85
|
+
emissiveMap: mat.emissiveMap ? 'yes' : 'no',
|
|
86
|
+
normalMap: mat.normalMap ? 'yes' : 'no',
|
|
87
|
+
roughness: mat.roughness,
|
|
88
|
+
metalness: mat.metalness,
|
|
89
|
+
color: mat.color?.getHexString(),
|
|
90
|
+
toneMapped: mat.toneMapped,
|
|
91
|
+
});
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Step 4 — Replace Texture Safely
|
|
95
|
+
|
|
96
|
+
Apply Hard Rules 2–5: clone the material, copy all 7 UV settings, flag updates.
|
|
97
|
+
|
|
98
|
+
```tsx
|
|
99
|
+
function replaceTexture(mesh: THREE.Mesh, newTexture: THREE.Texture) {
|
|
100
|
+
const mat = mesh.material as THREE.MeshBasicMaterial;
|
|
101
|
+
const oldMap = mat.map;
|
|
102
|
+
|
|
103
|
+
// Clone material to not affect other meshes sharing it
|
|
104
|
+
mesh.material = mat.clone();
|
|
105
|
+
const newMat = mesh.material as THREE.MeshBasicMaterial;
|
|
106
|
+
|
|
107
|
+
// Copy ALL UV settings from original texture
|
|
108
|
+
if (oldMap) {
|
|
109
|
+
newTexture.flipY = oldMap.flipY;
|
|
110
|
+
newTexture.wrapS = oldMap.wrapS;
|
|
111
|
+
newTexture.wrapT = oldMap.wrapT;
|
|
112
|
+
newTexture.offset.copy(oldMap.offset);
|
|
113
|
+
newTexture.repeat.copy(oldMap.repeat);
|
|
114
|
+
newTexture.rotation = oldMap.rotation;
|
|
115
|
+
newTexture.center.copy(oldMap.center);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Color/UI/photo texture tail. For data textures (normalMap, roughnessMap,
|
|
119
|
+
// metalnessMap, aoMap): use THREE.LinearSRGBColorSpace and keep toneMapped.
|
|
120
|
+
newTexture.colorSpace = THREE.SRGBColorSpace;
|
|
121
|
+
newTexture.needsUpdate = true;
|
|
122
|
+
|
|
123
|
+
newMat.map = newTexture;
|
|
124
|
+
newMat.toneMapped = false;
|
|
125
|
+
newMat.needsUpdate = true;
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Common Issues
|
|
130
|
+
|
|
131
|
+
| Issue | Cause | Fix |
|
|
132
|
+
|-------|-------|-----|
|
|
133
|
+
| Texture stretched/squished | UV coordinates don't match texture aspect ratio | Check UV range (Step 2). If model uses a UV atlas, you may need custom UV mapping |
|
|
134
|
+
| Texture appears on wrong mesh | Multiple meshes share a material | Clone material before modifying: `mesh.material = mat.clone()` |
|
|
135
|
+
| Texture flipped/mirrored | `flipY` mismatch between old and new texture | Copy `flipY` from original texture, or try toggling it |
|
|
136
|
+
| Black/invisible texture | `needsUpdate` not called, or wrong `colorSpace` | Set `texture.needsUpdate = true` and `material.needsUpdate = true`; check Hard Rule 5 |
|
|
137
|
+
| Sketchfab model with baked textures | Texture atlas — UVs map to specific regions of a combined image | Use the original atlas texture, or re-UV the screen mesh in Blender |
|
|
138
|
+
| Glass mesh hiding screen content | Front glass mesh occludes screen texture | Set glass mesh `visible={false}`, or `material.transparent = true` with low opacity |
|
|
139
|
+
|
|
140
|
+
## Recap — non-negotiables
|
|
141
|
+
|
|
142
|
+
- Inspect in order (traverse → UV → material dump) before applying any fix.
|
|
143
|
+
- Clone shared materials; never mutate in place.
|
|
144
|
+
- Copy all 7 UV settings when swapping a texture; then `needsUpdate = true` on both texture and material.
|
|
145
|
+
- `SRGBColorSpace`/`toneMapped = false` for color maps only — data maps stay linear.
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: html-to-3d-texture
|
|
3
|
+
description: Capture HTML/React components as PNG or canvas textures for 3D model screens — Playwright, html2canvas, live CanvasTexture, resolution guide, rounded-corner masking.
|
|
4
|
+
tokens: 1514
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# HTML to 3D Texture Pipeline
|
|
8
|
+
|
|
9
|
+
## Purpose
|
|
10
|
+
|
|
11
|
+
Display web UI on a 3D surface: render a React component, capture it as a PNG or canvas, apply it as a Three.js texture on the model's screen mesh.
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
React Component → Capture (Playwright/html2canvas) → PNG/Canvas → Three.js Texture → 3D Mesh
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Use when / Do not use
|
|
18
|
+
|
|
19
|
+
- **Use when**: a 3D model (phone, laptop, tablet) must show real web UI on its screen.
|
|
20
|
+
- **Do not use when**: the UI must stay clickable/scrollable on the 3D surface — a texture is a flat image. Use `@react-three/drei` `<Html>` instead.
|
|
21
|
+
|
|
22
|
+
## Hard Rules
|
|
23
|
+
|
|
24
|
+
- Set `texture.colorSpace = THREE.SRGBColorSpace` on every texture built from a capture — otherwise colors wash out.
|
|
25
|
+
- Capture at 2x (`deviceScaleFactor: 2` / `scale: 2`) — 1x textures look blurry on retina screens.
|
|
26
|
+
- html2canvas re-parses the entire DOM subtree on every call — this cost applies to Method 2 AND Method 3. In any repeated-capture loop, cap refresh at 1–2 fps for production; higher rates (e.g. 10 fps) are local-dev demos only.
|
|
27
|
+
|
|
28
|
+
## Workflow
|
|
29
|
+
|
|
30
|
+
1. Pick the capture method from the decision table below.
|
|
31
|
+
2. Capture at 2x using that method's code.
|
|
32
|
+
3. Post-process if the screen needs rounded corners (sharp recipe below).
|
|
33
|
+
4. Apply as texture with `SRGBColorSpace` set (PNG → `THREE.TextureLoader`; canvas → `THREE.CanvasTexture`).
|
|
34
|
+
|
|
35
|
+
## Decision table — which method
|
|
36
|
+
|
|
37
|
+
| Content on the 3D screen | Method |
|
|
38
|
+
|--------------------------|--------|
|
|
39
|
+
| Static — never changes at runtime | **Method 1** — Playwright PNG (build-time) |
|
|
40
|
+
| Changes on discrete events (user action, data loaded) | **Method 2** — one-shot html2canvas per event |
|
|
41
|
+
| Changes continuously (timers, animations, live data) | **Method 3** — throttled html2canvas loop |
|
|
42
|
+
| Must remain interactive (clicks, scroll, inputs) | Not a texture — drei `<Html>` |
|
|
43
|
+
|
|
44
|
+
Default when unsure: **Method 1** — best quality, zero runtime cost.
|
|
45
|
+
|
|
46
|
+
## Method 1: Playwright Capture (build-time, best quality)
|
|
47
|
+
|
|
48
|
+
Best for: production screenshots, pixel-perfect captures.
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
// scripts/capture-screen.mjs
|
|
52
|
+
import { chromium } from 'playwright';
|
|
53
|
+
|
|
54
|
+
const PORT = process.argv[2] || 3000;
|
|
55
|
+
const WIDTH = 440; // Native screen width
|
|
56
|
+
const HEIGHT = 956; // Native screen height
|
|
57
|
+
const SCALE = 2; // Retina (output: 880x1912)
|
|
58
|
+
|
|
59
|
+
async function capture() {
|
|
60
|
+
const browser = await chromium.launch();
|
|
61
|
+
const page = await browser.newPage({
|
|
62
|
+
viewport: { width: WIDTH, height: HEIGHT },
|
|
63
|
+
deviceScaleFactor: SCALE,
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
await page.goto(`http://localhost:${PORT}/capture`);
|
|
67
|
+
await page.waitForLoadState('networkidle');
|
|
68
|
+
|
|
69
|
+
// Find target element
|
|
70
|
+
const el = await page.locator('[data-screen-id="main"]');
|
|
71
|
+
await el.screenshot({
|
|
72
|
+
path: 'public/textures/screen.png',
|
|
73
|
+
type: 'png',
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
await browser.close();
|
|
77
|
+
console.log(`Captured: ${WIDTH * SCALE}x${HEIGHT * SCALE}px`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
capture();
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Method 2: One-shot html2canvas (event-driven runtime capture)
|
|
84
|
+
|
|
85
|
+
Best for: content that changes on discrete events. Call once per change event (button click, data arrival) — do NOT wrap this in an interval; that is Method 3.
|
|
86
|
+
|
|
87
|
+
```tsx
|
|
88
|
+
import html2canvas from 'html2canvas';
|
|
89
|
+
import * as THREE from 'three';
|
|
90
|
+
|
|
91
|
+
async function captureToTexture(element: HTMLElement): Promise<THREE.CanvasTexture> {
|
|
92
|
+
const canvas = await html2canvas(element, {
|
|
93
|
+
scale: 2,
|
|
94
|
+
useCORS: true,
|
|
95
|
+
backgroundColor: null, // transparent
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
const texture = new THREE.CanvasTexture(canvas);
|
|
99
|
+
texture.colorSpace = THREE.SRGBColorSpace;
|
|
100
|
+
texture.needsUpdate = true;
|
|
101
|
+
|
|
102
|
+
return texture;
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Method 3: Throttled html2canvas loop (continuous updates)
|
|
107
|
+
|
|
108
|
+
Best for: UI that changes continuously while displayed on the 3D surface. Same capture as Method 2, driven by a timer — so the html2canvas cost from Hard Rules repeats every tick. Keep `FPS` at 1–2 in production.
|
|
109
|
+
|
|
110
|
+
```tsx
|
|
111
|
+
const FPS = 2; // production-safe (1-2 fps). 10 fps = local-dev demo only — CPU-heavy.
|
|
112
|
+
|
|
113
|
+
function useHTMLTexture(ref: React.RefObject<HTMLDivElement>) {
|
|
114
|
+
const textureRef = useRef<THREE.CanvasTexture | null>(null);
|
|
115
|
+
|
|
116
|
+
useEffect(() => {
|
|
117
|
+
const interval = setInterval(async () => {
|
|
118
|
+
if (!ref.current) return;
|
|
119
|
+
const canvas = await html2canvas(ref.current, { scale: 2 });
|
|
120
|
+
if (textureRef.current) {
|
|
121
|
+
textureRef.current.image = canvas;
|
|
122
|
+
textureRef.current.needsUpdate = true;
|
|
123
|
+
} else {
|
|
124
|
+
textureRef.current = new THREE.CanvasTexture(canvas);
|
|
125
|
+
textureRef.current.colorSpace = THREE.SRGBColorSpace;
|
|
126
|
+
}
|
|
127
|
+
}, 1000 / FPS);
|
|
128
|
+
|
|
129
|
+
return () => clearInterval(interval);
|
|
130
|
+
}, [ref]);
|
|
131
|
+
|
|
132
|
+
return textureRef;
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Resolution Guide
|
|
137
|
+
|
|
138
|
+
| Device | Native (pts) | @2x (px) | Use for |
|
|
139
|
+
|--------|-------------|----------|---------|
|
|
140
|
+
| iPhone 15 Pro | 393x852 | 786x1704 | Phone model screen |
|
|
141
|
+
| iPhone 16 Pro Max | 440x956 | 880x1912 | Large phone model |
|
|
142
|
+
| iPad Pro 11" | 834x1194 | 1668x2388 | Tablet model |
|
|
143
|
+
| MacBook Pro 14" | 1512x982 | 3024x1964 | Laptop model |
|
|
144
|
+
|
|
145
|
+
## Applying Rounded Corners
|
|
146
|
+
|
|
147
|
+
PNG with transparent rounded corners for phone screens:
|
|
148
|
+
|
|
149
|
+
```javascript
|
|
150
|
+
// Using sharp (Node.js)
|
|
151
|
+
import sharp from 'sharp';
|
|
152
|
+
|
|
153
|
+
const RADIUS = 124; // 62pt * 2x scale
|
|
154
|
+
const { width, height } = await sharp('screen.png').metadata();
|
|
155
|
+
|
|
156
|
+
const mask = Buffer.from(
|
|
157
|
+
`<svg width="${width}" height="${height}">
|
|
158
|
+
<rect x="0" y="0" width="${width}" height="${height}"
|
|
159
|
+
rx="${RADIUS}" ry="${RADIUS}" fill="white"/>
|
|
160
|
+
</svg>`
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
await sharp('screen.png')
|
|
164
|
+
.ensureAlpha()
|
|
165
|
+
.composite([{ input: mask, blend: 'dest-in' }])
|
|
166
|
+
.png()
|
|
167
|
+
.toFile('screen-rounded.png');
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
## Tips
|
|
171
|
+
|
|
172
|
+
- Always capture at 2x for retina quality
|
|
173
|
+
- Use `data-screen-id` attribute to find elements reliably
|
|
174
|
+
- Remove debug borders/outlines before capture
|
|
175
|
+
- Test with `sips -g pixelWidth -g pixelHeight` (macOS) to verify dimensions
|
|
176
|
+
- Set `backgroundColor: null` for transparent backgrounds when needed
|
|
177
|
+
|
|
178
|
+
## Recap — non-negotiables
|
|
179
|
+
|
|
180
|
+
- `SRGBColorSpace` on every capture-derived texture.
|
|
181
|
+
- Capture at 2x, always.
|
|
182
|
+
- Repeated html2canvas capture: 1–2 fps in production; 10 fps only as a labeled local-dev demo value.
|
|
183
|
+
- Unsure which method: Method 1 (Playwright PNG).
|