opencode-skills-collection 3.1.12 → 3.1.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled-skills/.antigravity-install-manifest.json +192 -1
- package/bundled-skills/ab-testing/SKILL.md +368 -0
- package/bundled-skills/ab-testing/evals/evals.json +105 -0
- package/bundled-skills/ab-testing/references/sample-size-guide.md +263 -0
- package/bundled-skills/ab-testing/references/test-templates.md +277 -0
- package/bundled-skills/accint-commitments/SKILL.md +32 -0
- package/bundled-skills/accint-frames/SKILL.md +35 -0
- package/bundled-skills/accint-solve/SKILL.md +22 -192
- package/bundled-skills/add-app-clip/SKILL.md +297 -0
- package/bundled-skills/add-app-clip/agents/openai.yaml +4 -0
- package/bundled-skills/add-app-clip/references/native-module.md +96 -0
- package/bundled-skills/agent-memory/SKILL.md +84 -0
- package/bundled-skills/alternatives-pages/README.md +46 -0
- package/bundled-skills/alternatives-pages/SKILL.md +376 -0
- package/bundled-skills/analytics/SKILL.md +324 -0
- package/bundled-skills/analytics/evals/evals.json +90 -0
- package/bundled-skills/analytics/references/event-library.md +260 -0
- package/bundled-skills/analytics/references/ga4-implementation.md +300 -0
- package/bundled-skills/analytics/references/gtm-implementation.md +390 -0
- package/bundled-skills/anti-deception/SKILL.md +50 -0
- package/bundled-skills/api-analyzer/SKILL.md +101 -0
- package/bundled-skills/api-and-interface-design/SKILL.md +307 -0
- package/bundled-skills/api-designer/SKILL.md +167 -0
- package/bundled-skills/api-integration/SKILL.md +175 -0
- package/bundled-skills/api-onboarding/README.md +47 -0
- package/bundled-skills/api-onboarding/SKILL.md +473 -0
- package/bundled-skills/api-sdk-generator/SKILL.md +223 -0
- package/bundled-skills/appium-skill/SKILL.md +317 -0
- package/bundled-skills/applicationinsights-web-ts/SKILL.md +477 -0
- package/bundled-skills/automated-triage/SKILL.md +189 -0
- package/bundled-skills/aws-agentic-ai/SKILL.md +141 -0
- package/bundled-skills/aws-cdk-development/SKILL.md +275 -0
- package/bundled-skills/aws-cost-operations/SKILL.md +273 -0
- package/bundled-skills/aws-mcp-setup/SKILL.md +192 -0
- package/bundled-skills/aws-serverless-eda/SKILL.md +394 -0
- package/bundled-skills/aws-sst-development/SKILL.md +175 -0
- package/bundled-skills/azure-ai-language-conversations-py/SKILL.md +112 -0
- package/bundled-skills/azure-servicebus-rust/SKILL.md +182 -0
- package/bundled-skills/azure-storage-queue-rust/SKILL.md +178 -0
- package/bundled-skills/baseline-ui/SKILL.md +15 -10
- package/bundled-skills/brooks-audit/SKILL.md +49 -0
- package/bundled-skills/brooks-audit/architecture-guide.md +195 -0
- package/bundled-skills/brooks-audit/onboarding-guide.md +89 -0
- package/bundled-skills/brooks-debt/SKILL.md +42 -0
- package/bundled-skills/brooks-debt/debt-guide.md +125 -0
- package/bundled-skills/brooks-harness/SKILL.md +139 -0
- package/bundled-skills/brooks-review/SKILL.md +42 -0
- package/bundled-skills/brooks-review/pr-review-guide.md +163 -0
- package/bundled-skills/brooks-sweep/SKILL.md +44 -0
- package/bundled-skills/brooks-sweep/sweep-guide.md +264 -0
- package/bundled-skills/brooks-test/SKILL.md +41 -0
- package/bundled-skills/brooks-test/test-guide.md +147 -0
- package/bundled-skills/bug-hunt-swarm/SKILL.md +189 -0
- package/bundled-skills/bug-hunt-swarm/agents/openai.yaml +4 -0
- package/bundled-skills/building-native-ui/SKILL.md +77 -18
- package/bundled-skills/building-native-ui/agents/openai.yaml +4 -0
- package/bundled-skills/building-native-ui/references/animations.md +220 -0
- package/bundled-skills/building-native-ui/references/controls.md +270 -0
- package/bundled-skills/building-native-ui/references/form-sheet.md +253 -0
- package/bundled-skills/building-native-ui/references/gradients.md +106 -0
- package/bundled-skills/building-native-ui/references/icons.md +213 -0
- package/bundled-skills/building-native-ui/references/media.md +198 -0
- package/bundled-skills/building-native-ui/references/route-structure.md +229 -0
- package/bundled-skills/building-native-ui/references/search.md +248 -0
- package/bundled-skills/building-native-ui/references/storage.md +121 -0
- package/bundled-skills/building-native-ui/references/tabs.md +433 -0
- package/bundled-skills/building-native-ui/references/toolbar-and-headers.md +284 -0
- package/bundled-skills/building-native-ui/references/visual-effects.md +197 -0
- package/bundled-skills/building-native-ui/references/webgpu-three.md +605 -0
- package/bundled-skills/building-native-ui/references/zoom-transitions.md +158 -0
- package/bundled-skills/changelog-updates/README.md +53 -0
- package/bundled-skills/changelog-updates/SKILL.md +552 -0
- package/bundled-skills/ci-cd-and-automation/SKILL.md +403 -0
- package/bundled-skills/claimable-postgres/SKILL.md +91 -59
- package/bundled-skills/co-marketing/SKILL.md +301 -0
- package/bundled-skills/co-marketing/evals/evals.json +84 -0
- package/bundled-skills/code-review-and-quality/SKILL.md +394 -0
- package/bundled-skills/code-showcase-core-components/SKILL.md +281 -0
- package/bundled-skills/code-showcase-react-ui-patterns/SKILL.md +306 -0
- package/bundled-skills/code-showcase-systematic-debugging/SKILL.md +167 -0
- package/bundled-skills/code-showcase-testing-patterns/SKILL.md +276 -0
- package/bundled-skills/code-simplification/SKILL.md +344 -0
- package/bundled-skills/community-building/README.md +102 -0
- package/bundled-skills/community-building/SKILL.md +415 -0
- package/bundled-skills/competitor-profiling/SKILL.md +427 -0
- package/bundled-skills/competitor-profiling/evals/evals.json +85 -0
- package/bundled-skills/competitor-profiling/references/templates.md +167 -0
- package/bundled-skills/competitor-profiling/references/tool-reference.md +179 -0
- package/bundled-skills/competitor-tracking/README.md +40 -0
- package/bundled-skills/competitor-tracking/SKILL.md +322 -0
- package/bundled-skills/context-engineering/SKILL.md +302 -0
- package/bundled-skills/cro/SKILL.md +202 -0
- package/bundled-skills/cro/evals/evals.json +111 -0
- package/bundled-skills/cro/references/experiments.md +248 -0
- package/bundled-skills/cro/references/form.md +422 -0
- package/bundled-skills/cucumber-skill/SKILL.md +235 -0
- package/bundled-skills/customer-research/SKILL.md +287 -0
- package/bundled-skills/customer-research/evals/evals.json +162 -0
- package/bundled-skills/customer-research/references/source-guides.md +401 -0
- package/bundled-skills/cypress-skill/SKILL.md +235 -0
- package/bundled-skills/debugging-and-error-recovery/SKILL.md +313 -0
- package/bundled-skills/debugging-code/SKILL.md +284 -0
- package/bundled-skills/debugging-code/references/advanced-techniques.md +50 -0
- package/bundled-skills/debugging-code/references/installing-debuggers.md +67 -0
- package/bundled-skills/debugging-code/scripts/install-dap.sh +87 -0
- package/bundled-skills/deprecation-and-migration/SKILL.md +219 -0
- package/bundled-skills/design-philosophy/SKILL.md +40 -0
- package/bundled-skills/design-philosophy/reference.md +19 -0
- package/bundled-skills/design-spatial/SKILL.md +271 -0
- package/bundled-skills/design-spatial/scripts/layout-audit.js +138 -0
- package/bundled-skills/design-system/SKILL.md +140 -0
- package/bundled-skills/design-system/references/motion-choreography.md +111 -0
- package/bundled-skills/design-thinking/SKILL.md +109 -0
- package/bundled-skills/design-ux/SKILL.md +75 -0
- package/bundled-skills/dev-to-hashnode/README.md +62 -0
- package/bundled-skills/dev-to-hashnode/SKILL.md +399 -0
- package/bundled-skills/developer-advocacy/README.md +102 -0
- package/bundled-skills/developer-advocacy/SKILL.md +423 -0
- package/bundled-skills/developer-audience-context/README.md +61 -0
- package/bundled-skills/developer-audience-context/SKILL.md +271 -0
- package/bundled-skills/developer-audience-context/references/example-apitest.md +175 -0
- package/bundled-skills/developer-audience-context/references/template.md +152 -0
- package/bundled-skills/developer-churn/README.md +80 -0
- package/bundled-skills/developer-churn/SKILL.md +652 -0
- package/bundled-skills/developer-listening/README.md +30 -0
- package/bundled-skills/developer-listening/SKILL.md +232 -0
- package/bundled-skills/developer-newsletter/README.md +84 -0
- package/bundled-skills/developer-newsletter/SKILL.md +376 -0
- package/bundled-skills/developer-onboarding/README.md +35 -0
- package/bundled-skills/developer-onboarding/SKILL.md +530 -0
- package/bundled-skills/developer-sandbox/README.md +47 -0
- package/bundled-skills/developer-sandbox/SKILL.md +504 -0
- package/bundled-skills/developer-seo/README.md +36 -0
- package/bundled-skills/developer-seo/SKILL.md +296 -0
- package/bundled-skills/developer-signup-flow/README.md +36 -0
- package/bundled-skills/developer-signup-flow/SKILL.md +397 -0
- package/bundled-skills/devrel-content/README.md +81 -0
- package/bundled-skills/devrel-content/SKILL.md +428 -0
- package/bundled-skills/docs/integrations/jetski-cortex.md +3 -3
- package/bundled-skills/docs/integrations/jetski-gemini-loader/README.md +1 -1
- package/bundled-skills/docs/maintainers/repo-growth-seo.md +3 -3
- package/bundled-skills/docs/maintainers/skills-update-guide.md +1 -1
- package/bundled-skills/docs/users/bundles.md +1 -1
- package/bundled-skills/docs/users/claude-code-skills.md +1 -1
- package/bundled-skills/docs/users/faq.md +1 -1
- package/bundled-skills/docs/users/gemini-cli-skills.md +1 -1
- package/bundled-skills/docs/users/getting-started.md +1 -1
- package/bundled-skills/docs/users/kiro-integration.md +1 -1
- package/bundled-skills/docs/users/usage.md +8 -8
- package/bundled-skills/docs/users/visual-guide.md +8 -8
- package/bundled-skills/docs-as-marketing/README.md +37 -0
- package/bundled-skills/docs-as-marketing/SKILL.md +398 -0
- package/bundled-skills/documentation-and-adrs/SKILL.md +291 -0
- package/bundled-skills/doubt-driven-development/SKILL.md +256 -0
- package/bundled-skills/eas-update-insights/SKILL.md +232 -0
- package/bundled-skills/eas-update-insights/agents/openai.yaml +4 -0
- package/bundled-skills/eas-update-insights/references/channel-insights-schema.md +47 -0
- package/bundled-skills/eas-update-insights/references/update-insights-schema.md +69 -0
- package/bundled-skills/expo-api-routes/SKILL.md +9 -5
- package/bundled-skills/expo-api-routes/agents/openai.yaml +4 -0
- package/bundled-skills/expo-brownfield/SKILL.md +71 -0
- package/bundled-skills/expo-brownfield/agents/openai.yaml +4 -0
- package/bundled-skills/expo-brownfield/references/brownfield-integrated.md +526 -0
- package/bundled-skills/expo-brownfield/references/brownfield-isolated.md +402 -0
- package/bundled-skills/expo-brownfield/references/comparison.md +63 -0
- package/bundled-skills/expo-brownfield/references/troubleshooting.md +88 -0
- package/bundled-skills/expo-cicd-workflows/SKILL.md +18 -16
- package/bundled-skills/expo-cicd-workflows/agents/openai.yaml +4 -0
- package/bundled-skills/expo-cicd-workflows/scripts/fetch.js +109 -0
- package/bundled-skills/expo-cicd-workflows/scripts/package.json +11 -0
- package/bundled-skills/expo-cicd-workflows/scripts/validate.js +84 -0
- package/bundled-skills/expo-deployment/SKILL.md +157 -53
- package/bundled-skills/expo-deployment/agents/openai.yaml +4 -0
- package/bundled-skills/expo-deployment/references/app-store-metadata.md +497 -0
- package/bundled-skills/expo-deployment/references/ios-app-store.md +371 -0
- package/bundled-skills/expo-deployment/references/play-store.md +246 -0
- package/bundled-skills/expo-deployment/references/testflight.md +58 -0
- package/bundled-skills/expo-deployment/references/workflows.md +160 -0
- package/bundled-skills/expo-dev-client/SKILL.md +25 -14
- package/bundled-skills/expo-dev-client/agents/openai.yaml +4 -0
- package/bundled-skills/expo-examples/SKILL.md +111 -0
- package/bundled-skills/expo-examples/references/catalog.md +105 -0
- package/bundled-skills/expo-module/SKILL.md +152 -0
- package/bundled-skills/expo-module/agents/openai.yaml +4 -0
- package/bundled-skills/expo-module/references/config-plugin.md +90 -0
- package/bundled-skills/expo-module/references/create-expo-module.md +206 -0
- package/bundled-skills/expo-module/references/lifecycle.md +127 -0
- package/bundled-skills/expo-module/references/module-config.md +48 -0
- package/bundled-skills/expo-module/references/native-module.md +286 -0
- package/bundled-skills/expo-module/references/native-view.md +171 -0
- package/bundled-skills/expo-observe/SKILL.md +44 -0
- package/bundled-skills/expo-observe/references/metrics.md +47 -0
- package/bundled-skills/expo-observe/references/queries.md +342 -0
- package/bundled-skills/expo-observe/references/setup.md +255 -0
- package/bundled-skills/expo-tailwind-setup/SKILL.md +13 -10
- package/bundled-skills/expo-tailwind-setup/agents/openai.yaml +4 -0
- package/bundled-skills/expo-ui/SKILL.md +61 -0
- package/bundled-skills/expo-ui/agents/openai.yaml +4 -0
- package/bundled-skills/expo-ui/references/drop-in-replacements.md +27 -0
- package/bundled-skills/expo-ui/references/jetpack-compose.md +73 -0
- package/bundled-skills/expo-ui/references/swift-ui.md +73 -0
- package/bundled-skills/expo-ui/references/universal.md +73 -0
- package/bundled-skills/expo-ui/scripts/list-components.js +193 -0
- package/bundled-skills/faf-context/SKILL.md +106 -0
- package/bundled-skills/faf-go/SKILL.md +336 -0
- package/bundled-skills/fixing-accessibility/SKILL.md +16 -5
- package/bundled-skills/fixing-metadata/SKILL.md +18 -8
- package/bundled-skills/fixing-motion-performance/SKILL.md +17 -6
- package/bundled-skills/formik-patterns/SKILL.md +379 -0
- package/bundled-skills/free-tier-strategy/README.md +39 -0
- package/bundled-skills/free-tier-strategy/SKILL.md +462 -0
- package/bundled-skills/frontend-architecture/SKILL.md +419 -0
- package/bundled-skills/frontend-data-contracts/SKILL.md +331 -0
- package/bundled-skills/frontend-observability/SKILL.md +434 -0
- package/bundled-skills/frontend-optimistic-mutations/SKILL.md +278 -0
- package/bundled-skills/frontend-seo/SKILL.md +710 -0
- package/bundled-skills/frontend-slides-frontend-slides/SKILL.md +397 -0
- package/bundled-skills/frontend-ui-engineering/SKILL.md +341 -0
- package/bundled-skills/gemini-api-dev/SKILL.md +96 -53
- package/bundled-skills/gemini-live-api-dev/SKILL.md +339 -0
- package/bundled-skills/gemini-omni-flash-api/SKILL.md +335 -0
- package/bundled-skills/gemini-omni-flash-api/scripts/upload_file.py +218 -0
- package/bundled-skills/gemini-omni-flash-api/scripts/video/generate_video.py +439 -0
- package/bundled-skills/gemini-omni-flash-api/scripts/video/inspect_video.py +197 -0
- package/bundled-skills/gemini-omni-flash-api/scripts/video/prep_video.py +255 -0
- package/bundled-skills/git-workflow-and-versioning/SKILL.md +313 -0
- package/bundled-skills/github-presence/README.md +67 -0
- package/bundled-skills/github-presence/SKILL.md +484 -0
- package/bundled-skills/graphql-schema/SKILL.md +309 -0
- package/bundled-skills/hf-mcp/SKILL.md +195 -0
- package/bundled-skills/hf-mem/SKILL.md +92 -0
- package/bundled-skills/hugging-face-cli/SKILL.md +155 -115
- package/bundled-skills/hugging-face-community-evals/SKILL.md +14 -7
- package/bundled-skills/hugging-face-dataset-viewer/SKILL.md +30 -37
- package/bundled-skills/hugging-face-gradio/SKILL.md +14 -7
- package/bundled-skills/hugging-face-model-trainer/SKILL.md +36 -10
- package/bundled-skills/hugging-face-model-trainer/scripts/convert_to_gguf.py +30 -52
- package/bundled-skills/hugging-face-model-trainer/scripts/hf_benchmarks.py +659 -0
- package/bundled-skills/hugging-face-paper-publisher/SKILL.md +13 -6
- package/bundled-skills/hugging-face-papers/SKILL.md +12 -5
- package/bundled-skills/hugging-face-trackio/SKILL.md +11 -5
- package/bundled-skills/hugging-face-vision-trainer/SKILL.md +11 -5
- package/bundled-skills/huggingface-best/SKILL.md +143 -0
- package/bundled-skills/huggingface-local-models/SKILL.md +130 -0
- package/bundled-skills/huggingface-local-models/references/hardware.md +38 -0
- package/bundled-skills/huggingface-local-models/references/hub-discovery.md +178 -0
- package/bundled-skills/huggingface-local-models/references/quantization.md +256 -0
- package/bundled-skills/huggingface-lora-space-builder/SKILL.md +409 -0
- package/bundled-skills/huggingface-lora-space-builder/references/adapting-to-the-lora.md +113 -0
- package/bundled-skills/huggingface-lora-space-builder/references/base-models/krea-2.md +63 -0
- package/bundled-skills/huggingface-lora-space-builder/references/base-models/ltx.md +205 -0
- package/bundled-skills/huggingface-lora-space-builder/references/base-models/qwen-image.md +144 -0
- package/bundled-skills/huggingface-lora-space-builder/references/creative-mode.md +262 -0
- package/bundled-skills/huggingface-lora-space-builder/references/tasks.md +124 -0
- package/bundled-skills/huggingface-lora-space-builder/references/zerogpu-and-publishing.md +194 -0
- package/bundled-skills/huggingface-spaces/SKILL.md +247 -0
- package/bundled-skills/huggingface-spaces/references/buckets.md +89 -0
- package/bundled-skills/huggingface-spaces/references/debugging.md +234 -0
- package/bundled-skills/huggingface-spaces/references/gradio.md +171 -0
- package/bundled-skills/huggingface-spaces/references/grants.md +56 -0
- package/bundled-skills/huggingface-spaces/references/inference-providers.md +85 -0
- package/bundled-skills/huggingface-spaces/references/known-errors.md +232 -0
- package/bundled-skills/huggingface-spaces/references/requirements.md +153 -0
- package/bundled-skills/huggingface-spaces/references/zerogpu.md +276 -0
- package/bundled-skills/huggingface-tool-builder/SKILL.md +137 -0
- package/bundled-skills/huggingface-tool-builder/references/baseline_hf_api.py +57 -0
- package/bundled-skills/huggingface-tool-builder/references/baseline_hf_api.sh +40 -0
- package/bundled-skills/huggingface-tool-builder/references/baseline_hf_api.tsx +57 -0
- package/bundled-skills/huggingface-tool-builder/references/find_models_by_paper.sh +230 -0
- package/bundled-skills/huggingface-tool-builder/references/hf_enrich_models.sh +96 -0
- package/bundled-skills/huggingface-tool-builder/references/hf_model_card_frontmatter.sh +188 -0
- package/bundled-skills/huggingface-tool-builder/references/hf_model_papers_auth.sh +171 -0
- package/bundled-skills/huggingface-zerogpu/SKILL.md +306 -0
- package/bundled-skills/huggingface-zerogpu/references/concurrency.md +79 -0
- package/bundled-skills/huggingface-zerogpu/references/cuda-and-deps.md +66 -0
- package/bundled-skills/huggingface-zerogpu/references/how-quota-works.md +74 -0
- package/bundled-skills/huggingface-zerogpu/references/how-zerogpu-works.md +50 -0
- package/bundled-skills/hugo-to-markdown/SKILL.md +201 -0
- package/bundled-skills/hugo-to-markdown/agents/openai.yaml +4 -0
- package/bundled-skills/hugo-to-markdown/references/conversion-workflow.md +143 -0
- package/bundled-skills/hugo-to-markdown/references/front-matter-and-content.md +145 -0
- package/bundled-skills/hugo-to-markdown/references/links-assets-and-validation.md +106 -0
- package/bundled-skills/hugo-to-markdown/references/shortcodes-and-render-hooks.md +281 -0
- package/bundled-skills/hugo-to-markdown/scripts/check_standard_markdown.py +70 -0
- package/bundled-skills/hugo-to-markdown/scripts/inventory_hugo_rules.py +188 -0
- package/bundled-skills/hyperexecute-skill/SKILL.md +65 -0
- package/bundled-skills/idea-refine/SKILL.md +195 -0
- package/bundled-skills/idea-refine/examples.md +238 -0
- package/bundled-skills/idea-refine/frameworks.md +99 -0
- package/bundled-skills/idea-refine/refinement-criteria.md +113 -0
- package/bundled-skills/idea-refine/scripts/idea-refine.sh +15 -0
- package/bundled-skills/implement/SKILL.md +32 -0
- package/bundled-skills/incremental-implementation/SKILL.md +262 -0
- package/bundled-skills/jest-skill/SKILL.md +182 -0
- package/bundled-skills/junit-5-skill/SKILL.md +236 -0
- package/bundled-skills/logic-diff/SKILL.md +50 -0
- package/bundled-skills/logic-diff/logic-diff-guide.md +75 -0
- package/bundled-skills/logic-explain/SKILL.md +50 -0
- package/bundled-skills/logic-explain/logic-explain-guide.md +74 -0
- package/bundled-skills/logic-fix-all/SKILL.md +87 -0
- package/bundled-skills/logic-fix-all/guide-phases-0-2-consent-scope-health.md +113 -0
- package/bundled-skills/logic-fix-all/guide-phases-3-5-review-locate-clarify.md +47 -0
- package/bundled-skills/logic-fix-all/guide-phases-6-9-fix-iterate-report.md +143 -0
- package/bundled-skills/logic-fix-all/logic-fix-all-guide.md +60 -0
- package/bundled-skills/logic-locate/SKILL.md +52 -0
- package/bundled-skills/logic-locate/logic-locate-guide.md +85 -0
- package/bundled-skills/logic-review/SKILL.md +100 -0
- package/bundled-skills/logic-review/logic-review-guide.md +296 -0
- package/bundled-skills/longbridge-content/SKILL.md +87 -0
- package/bundled-skills/longbridge-fundamentals/SKILL.md +134 -0
- package/bundled-skills/longbridge-market-data/SKILL.md +129 -0
- package/bundled-skills/loopy/SKILL.md +289 -0
- package/bundled-skills/loopy/agents/openai.yaml +4 -0
- package/bundled-skills/loopy/references/audit.md +61 -0
- package/bundled-skills/loopy/references/debrief.md +43 -0
- package/bundled-skills/loopy/references/discover.md +72 -0
- package/bundled-skills/loopy/references/publish.md +65 -0
- package/bundled-skills/loopy/references/run.md +73 -0
- package/bundled-skills/marketing-plan/SKILL.md +283 -0
- package/bundled-skills/marketing-plan/evals/evals.json +96 -0
- package/bundled-skills/marketing-plan/references/aarrr-framework.md +180 -0
- package/bundled-skills/marketing-plan/references/budget-planning.md +168 -0
- package/bundled-skills/marketing-plan/references/client-types.md +373 -0
- package/bundled-skills/marketing-plan/references/current-state-rubric.md +255 -0
- package/bundled-skills/marketing-plan/references/example-quietude.md +972 -0
- package/bundled-skills/marketing-plan/references/funding-stage-unlocks.md +230 -0
- package/bundled-skills/marketing-plan/references/growth-patterns.md +148 -0
- package/bundled-skills/marketing-plan/references/idea-cross-reference.md +265 -0
- package/bundled-skills/marketing-plan/references/measurement-framework.md +213 -0
- package/bundled-skills/marketing-plan/references/methodology.md +363 -0
- package/bundled-skills/marketing-plan/references/ops-stack-mapping.md +197 -0
- package/bundled-skills/marketing-plan/references/plan-template.md +494 -0
- package/bundled-skills/marketing-plan/references/team-and-agency-model.md +278 -0
- package/bundled-skills/monte-carlo-analyze-root-cause/SKILL.md +229 -0
- package/bundled-skills/monte-carlo-asset-health/SKILL.md +200 -0
- package/bundled-skills/monte-carlo-monitoring-advisor/SKILL.md +317 -0
- package/bundled-skills/monte-carlo-performance-diagnosis/SKILL.md +153 -0
- package/bundled-skills/monte-carlo-remediation/SKILL.md +359 -0
- package/bundled-skills/monte-carlo-storage-cost-analysis/SKILL.md +162 -0
- package/bundled-skills/native-data-fetching/SKILL.md +11 -8
- package/bundled-skills/native-data-fetching/agents/openai.yaml +4 -0
- package/bundled-skills/native-data-fetching/references/expo-router-loaders.md +341 -0
- package/bundled-skills/neon-ai-gateway/SKILL.md +237 -0
- package/bundled-skills/neon-functions/SKILL.md +465 -0
- package/bundled-skills/neon-functions/references/ai-sdk.md +139 -0
- package/bundled-skills/neon-functions/references/hono-websockets.md +145 -0
- package/bundled-skills/neon-functions/references/mastra-studio.md +132 -0
- package/bundled-skills/neon-functions/references/mcp.md +137 -0
- package/bundled-skills/neon-functions/references/sentry.md +131 -0
- package/bundled-skills/neon-functions/references/sse.md +143 -0
- package/bundled-skills/neon-object-storage/SKILL.md +200 -0
- package/bundled-skills/neon-postgres/SKILL.md +234 -469
- package/bundled-skills/neon-postgres-branches/SKILL.md +292 -0
- package/bundled-skills/neon-postgres-egress-optimizer/SKILL.md +256 -0
- package/bundled-skills/newman-cicd-integration/SKILL.md +330 -0
- package/bundled-skills/observability-and-instrumentation/SKILL.md +216 -0
- package/bundled-skills/odw/SKILL.md +57 -0
- package/bundled-skills/offers/SKILL.md +168 -0
- package/bundled-skills/offers/references/bonus-stacking.md +150 -0
- package/bundled-skills/offers/references/examples.md +215 -0
- package/bundled-skills/offers/references/guarantee-design.md +172 -0
- package/bundled-skills/offers/references/offer-anatomy.md +203 -0
- package/bundled-skills/offers/references/offer-formats.md +240 -0
- package/bundled-skills/offers/references/scarcity-urgency.md +175 -0
- package/bundled-skills/offers/references/value-equation.md +134 -0
- package/bundled-skills/onboarding/SKILL.md +235 -0
- package/bundled-skills/onboarding/evals/evals.json +92 -0
- package/bundled-skills/onboarding/references/experiments.md +258 -0
- package/bundled-skills/open-source-marketing/README.md +100 -0
- package/bundled-skills/open-source-marketing/SKILL.md +466 -0
- package/bundled-skills/openapi-spec-generator/SKILL.md +335 -0
- package/bundled-skills/performance-optimization/SKILL.md +363 -0
- package/bundled-skills/planning-and-task-breakdown/SKILL.md +240 -0
- package/bundled-skills/polis-protocol-a-self-optimizing-city-of-agents/SKILL.md +170 -0
- package/bundled-skills/postgresql-cli/SKILL.md +498 -0
- package/bundled-skills/postgresql-cli/references/cli-options-and-variables.md +444 -0
- package/bundled-skills/postgresql-cli/references/meta-commands-core.md +466 -0
- package/bundled-skills/postgresql-cli/references/meta-commands-formatting.md +154 -0
- package/bundled-skills/postgresql-cli/references/meta-commands-inspection.md +134 -0
- package/bundled-skills/postgresql-cli/references/tips-advanced.md +289 -0
- package/bundled-skills/postgresql-cli/references/tips-workflows.md +407 -0
- package/bundled-skills/postman-collection-generator/SKILL.md +184 -0
- package/bundled-skills/postman-newman-automation/SKILL.md +311 -0
- package/bundled-skills/postman-openapi-converter/SKILL.md +174 -0
- package/bundled-skills/power-user-cultivation/README.md +78 -0
- package/bundled-skills/power-user-cultivation/SKILL.md +598 -0
- package/bundled-skills/pricing/SKILL.md +246 -0
- package/bundled-skills/pricing/evals/evals.json +90 -0
- package/bundled-skills/pricing/references/research-methods.md +152 -0
- package/bundled-skills/pricing/references/tier-structure.md +232 -0
- package/bundled-skills/privacy-mask/SKILL.md +96 -0
- package/bundled-skills/product-marketing/SKILL.md +256 -0
- package/bundled-skills/product-marketing/evals/evals.json +85 -0
- package/bundled-skills/public-relations/SKILL.md +146 -0
- package/bundled-skills/public-relations/references/journalist-pitching.md +368 -0
- package/bundled-skills/public-relations/references/media-outlets.md +207 -0
- package/bundled-skills/public-relations/references/newsjacking.md +218 -0
- package/bundled-skills/public-relations/references/press-platforms.md +188 -0
- package/bundled-skills/puppeteer-skill/SKILL.md +143 -0
- package/bundled-skills/pytest-skill/SKILL.md +201 -0
- package/bundled-skills/rclone-cli/SKILL.md +351 -0
- package/bundled-skills/rclone-cli/references/bisync.md +2003 -0
- package/bundled-skills/rclone-cli/references/cache.md +726 -0
- package/bundled-skills/rclone-cli/references/chunker.md +484 -0
- package/bundled-skills/rclone-cli/references/combine.md +187 -0
- package/bundled-skills/rclone-cli/references/commands/rclone.md +1169 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_about.md +89 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_archive.md +49 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_archive_create.md +97 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_archive_extract.md +83 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_archive_list.md +98 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_authorize.md +53 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_backend.md +82 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_bisync.md +160 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_cat.md +122 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_check.md +134 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_checksum.md +120 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_cleanup.md +49 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_completion.md +40 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_completion_bash.md +70 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_completion_fish.md +57 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_completion_powershell.md +49 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_completion_zsh.md +57 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config.md +56 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_create.md +150 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_delete.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_disconnect.md +40 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_dump.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_edit.md +39 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_encryption.md +36 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_encryption_check.md +43 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_encryption_remove.md +44 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_encryption_set.md +54 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_file.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_password.md +49 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_paths.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_providers.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_reconnect.md +40 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_redacted.md +45 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_show.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_string.md +57 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_touch.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_update.md +150 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_config_userinfo.md +38 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_convmv.md +440 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_copy.md +258 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_copyto.md +219 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_copyurl.md +91 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_cryptcheck.md +141 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_cryptdecode.md +51 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_dedupe.md +166 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_delete.md +117 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_deletefile.md +50 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_gendocs.md +39 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_gitannex.md +113 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_hashsum.md +120 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_link.md +60 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_listremotes.md +55 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_ls.md +114 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_lsd.md +127 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_lsf.md +241 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_lsjson.md +195 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_lsl.md +115 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_md5sum.md +96 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_mkdir.md +43 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_mount.md +1105 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_move.md +223 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_moveto.md +218 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_ncdu.md +140 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_nfsmount.md +1111 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_obscure.md +60 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_purge.md +58 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_rc.md +111 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_rcat.md +79 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_rcd.md +219 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_rmdir.md +52 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_rmdirs.md +66 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_selfupdate.md +91 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve.md +61 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_dlna.md +619 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_docker.md +653 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_ftp.md +698 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_http.md +837 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_nfs.md +670 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_restic.md +246 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_s3.md +867 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_sftp.md +745 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_serve_webdav.md +896 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_settier.md +63 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_sha1sum.md +99 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_size.md +94 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_sync.md +252 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test.md +51 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_changenotify.md +34 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_histogram.md +41 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_info.md +51 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_makefile.md +39 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_makefiles.md +47 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_memory.md +33 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_test_speed.md +66 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_touch.md +110 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_tree.md +121 -0
- package/bundled-skills/rclone-cli/references/commands/rclone_version.md +83 -0
- package/bundled-skills/rclone-cli/references/crypt.md +844 -0
- package/bundled-skills/rclone-cli/references/docker.md +615 -0
- package/bundled-skills/rclone-cli/references/faq.md +364 -0
- package/bundled-skills/rclone-cli/references/filtering.md +991 -0
- package/bundled-skills/rclone-cli/references/flags.md +1221 -0
- package/bundled-skills/rclone-cli/references/hasher.md +383 -0
- package/bundled-skills/rclone-cli/references/install.md +686 -0
- package/bundled-skills/rclone-cli/references/overview.md +620 -0
- package/bundled-skills/rclone-cli/references/providers/alias.md +141 -0
- package/bundled-skills/rclone-cli/references/providers/archive.md +287 -0
- package/bundled-skills/rclone-cli/references/providers/azureblob.md +1140 -0
- package/bundled-skills/rclone-cli/references/providers/azurefiles.md +834 -0
- package/bundled-skills/rclone-cli/references/providers/b2.md +879 -0
- package/bundled-skills/rclone-cli/references/providers/box.md +573 -0
- package/bundled-skills/rclone-cli/references/providers/cloudinary.md +259 -0
- package/bundled-skills/rclone-cli/references/providers/compress.md +222 -0
- package/bundled-skills/rclone-cli/references/providers/drime.md +319 -0
- package/bundled-skills/rclone-cli/references/providers/drive.md +2032 -0
- package/bundled-skills/rclone-cli/references/providers/dropbox.md +661 -0
- package/bundled-skills/rclone-cli/references/providers/fichier.md +230 -0
- package/bundled-skills/rclone-cli/references/providers/filefabric.md +298 -0
- package/bundled-skills/rclone-cli/references/providers/filelu.md +256 -0
- package/bundled-skills/rclone-cli/references/providers/filen.md +243 -0
- package/bundled-skills/rclone-cli/references/providers/filescom.md +209 -0
- package/bundled-skills/rclone-cli/references/providers/ftp.md +621 -0
- package/bundled-skills/rclone-cli/references/providers/gofile.md +274 -0
- package/bundled-skills/rclone-cli/references/providers/googlecloudstorage.md +846 -0
- package/bundled-skills/rclone-cli/references/providers/googlephotos.md +676 -0
- package/bundled-skills/rclone-cli/references/providers/hdfs.md +263 -0
- package/bundled-skills/rclone-cli/references/providers/hidrive.md +487 -0
- package/bundled-skills/rclone-cli/references/providers/http.md +323 -0
- package/bundled-skills/rclone-cli/references/providers/iclouddrive.md +212 -0
- package/bundled-skills/rclone-cli/references/providers/internetarchive.md +355 -0
- package/bundled-skills/rclone-cli/references/providers/internxt.md +189 -0
- package/bundled-skills/rclone-cli/references/providers/jottacloud.md +604 -0
- package/bundled-skills/rclone-cli/references/providers/koofr.md +395 -0
- package/bundled-skills/rclone-cli/references/providers/linkbox.md +117 -0
- package/bundled-skills/rclone-cli/references/providers/local.md +749 -0
- package/bundled-skills/rclone-cli/references/providers/mailru.md +470 -0
- package/bundled-skills/rclone-cli/references/providers/mega.md +361 -0
- package/bundled-skills/rclone-cli/references/providers/memory.md +109 -0
- package/bundled-skills/rclone-cli/references/providers/netstorage.md +371 -0
- package/bundled-skills/rclone-cli/references/providers/onedrive.md +1322 -0
- package/bundled-skills/rclone-cli/references/providers/opendrive.md +222 -0
- package/bundled-skills/rclone-cli/references/providers/oracleobjectstorage/_index.md +932 -0
- package/bundled-skills/rclone-cli/references/providers/oracleobjectstorage/tutorial_mount.md +503 -0
- package/bundled-skills/rclone-cli/references/providers/pcloud.md +373 -0
- package/bundled-skills/rclone-cli/references/providers/pikpak.md +373 -0
- package/bundled-skills/rclone-cli/references/providers/pixeldrain.md +182 -0
- package/bundled-skills/rclone-cli/references/providers/premiumizeme.md +253 -0
- package/bundled-skills/rclone-cli/references/providers/protondrive.md +397 -0
- package/bundled-skills/rclone-cli/references/providers/putio.md +246 -0
- package/bundled-skills/rclone-cli/references/providers/qingstor.md +346 -0
- package/bundled-skills/rclone-cli/references/providers/quatrix.md +295 -0
- package/bundled-skills/rclone-cli/references/providers/s3.md +9687 -0
- package/bundled-skills/rclone-cli/references/providers/seafile.md +432 -0
- package/bundled-skills/rclone-cli/references/providers/sftp.md +1277 -0
- package/bundled-skills/rclone-cli/references/providers/shade.md +267 -0
- package/bundled-skills/rclone-cli/references/providers/sharefile.md +357 -0
- package/bundled-skills/rclone-cli/references/providers/sia.md +223 -0
- package/bundled-skills/rclone-cli/references/providers/smb.md +309 -0
- package/bundled-skills/rclone-cli/references/providers/storj.md +503 -0
- package/bundled-skills/rclone-cli/references/providers/sugarsync.md +305 -0
- package/bundled-skills/rclone-cli/references/providers/swift.md +744 -0
- package/bundled-skills/rclone-cli/references/providers/ulozto.md +283 -0
- package/bundled-skills/rclone-cli/references/providers/webdav.md +565 -0
- package/bundled-skills/rclone-cli/references/providers/yandex.md +283 -0
- package/bundled-skills/rclone-cli/references/providers/zoho.md +305 -0
- package/bundled-skills/rclone-cli/references/rc.md +2725 -0
- package/bundled-skills/rclone-cli/references/union.md +336 -0
- package/bundled-skills/rclone-cli/references/usage.md +3555 -0
- package/bundled-skills/rclone-cli/scripts/install.sh +204 -0
- package/bundled-skills/redis-cli/SKILL.md +392 -0
- package/bundled-skills/redis-cli/references/advanced-features.md +338 -0
- package/bundled-skills/redis-cli/references/connection-and-options.md +258 -0
- package/bundled-skills/redis-cli/references/data-query-commands.md +417 -0
- package/bundled-skills/redis-cli/references/inspection-and-monitoring.md +309 -0
- package/bundled-skills/redis-cli/references/key-management.md +252 -0
- package/bundled-skills/redis-cli/references/module-data-types.md +429 -0
- package/bundled-skills/redis-cli/references/server-administration.md +366 -0
- package/bundled-skills/repo-maintainer/SKILL.md +480 -0
- package/bundled-skills/resolving-merge-conflicts/SKILL.md +32 -0
- package/bundled-skills/review-and-simplify-changes/SKILL.md +202 -0
- package/bundled-skills/review-swarm/SKILL.md +185 -0
- package/bundled-skills/review-swarm/agents/openai.yaml +4 -0
- package/bundled-skills/riffkit/SKILL.md +122 -0
- package/bundled-skills/robot-framework-skill/SKILL.md +153 -0
- package/bundled-skills/sdk-dx/README.md +39 -0
- package/bundled-skills/sdk-dx/SKILL.md +541 -0
- package/bundled-skills/security-and-hardening/SKILL.md +474 -0
- package/bundled-skills/selenium-skill/SKILL.md +258 -0
- package/bundled-skills/shipping-and-launch/SKILL.md +323 -0
- package/bundled-skills/smartui-skill/SKILL.md +149 -0
- package/bundled-skills/source-driven-development/SKILL.md +207 -0
- package/bundled-skills/spec-driven-development/SKILL.md +217 -0
- package/bundled-skills/styleseed-design-review/SKILL.md +126 -0
- package/bundled-skills/supabase/CHANGELOG.md +35 -0
- package/bundled-skills/supabase/SKILL.md +149 -0
- package/bundled-skills/supabase/assets/feedback-issue-template.md +17 -0
- package/bundled-skills/supabase/references/skill-feedback.md +17 -0
- package/bundled-skills/supabase-postgres-best-practices/CHANGELOG.md +29 -0
- package/bundled-skills/supabase-postgres-best-practices/SKILL.md +74 -0
- package/bundled-skills/supabase-postgres-best-practices/references/_contributing.md +170 -0
- package/bundled-skills/supabase-postgres-best-practices/references/_sections.md +39 -0
- package/bundled-skills/supabase-postgres-best-practices/references/_template.md +34 -0
- package/bundled-skills/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -0
- package/bundled-skills/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -0
- package/bundled-skills/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -0
- package/bundled-skills/supabase-postgres-best-practices/references/conn-limits.md +44 -0
- package/bundled-skills/supabase-postgres-best-practices/references/conn-pooling.md +41 -0
- package/bundled-skills/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -0
- package/bundled-skills/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -0
- package/bundled-skills/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -0
- package/bundled-skills/supabase-postgres-best-practices/references/data-pagination.md +50 -0
- package/bundled-skills/supabase-postgres-best-practices/references/data-upsert.md +50 -0
- package/bundled-skills/supabase-postgres-best-practices/references/lock-advisory.md +56 -0
- package/bundled-skills/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -0
- package/bundled-skills/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -0
- package/bundled-skills/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -0
- package/bundled-skills/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -0
- package/bundled-skills/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -0
- package/bundled-skills/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -0
- package/bundled-skills/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -0
- package/bundled-skills/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -0
- package/bundled-skills/supabase-postgres-best-practices/references/query-index-types.md +48 -0
- package/bundled-skills/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -0
- package/bundled-skills/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-constraints.md +80 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-data-types.md +46 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-partitioning.md +55 -0
- package/bundled-skills/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -0
- package/bundled-skills/supabase-postgres-best-practices/references/security-privileges.md +54 -0
- package/bundled-skills/supabase-postgres-best-practices/references/security-rls-basics.md +50 -0
- package/bundled-skills/supabase-postgres-best-practices/references/security-rls-performance.md +63 -0
- package/bundled-skills/swiftui-expert-skill/SKILL.md +175 -242
- package/bundled-skills/swiftui-expert-skill/references/accessibility-patterns.md +215 -0
- package/bundled-skills/swiftui-expert-skill/references/animation-advanced.md +428 -0
- package/bundled-skills/swiftui-expert-skill/references/animation-basics.md +284 -0
- package/bundled-skills/swiftui-expert-skill/references/animation-transitions.md +326 -0
- package/bundled-skills/swiftui-expert-skill/references/charts-accessibility.md +135 -0
- package/bundled-skills/swiftui-expert-skill/references/charts.md +602 -0
- package/bundled-skills/swiftui-expert-skill/references/focus-patterns.md +299 -0
- package/bundled-skills/swiftui-expert-skill/references/image-optimization.md +203 -0
- package/bundled-skills/swiftui-expert-skill/references/latest-apis.md +528 -0
- package/bundled-skills/swiftui-expert-skill/references/layout-best-practices.md +266 -0
- package/bundled-skills/swiftui-expert-skill/references/liquid-glass.md +423 -0
- package/bundled-skills/swiftui-expert-skill/references/list-patterns.md +467 -0
- package/bundled-skills/swiftui-expert-skill/references/localization.md +194 -0
- package/bundled-skills/swiftui-expert-skill/references/macos-scenes.md +318 -0
- package/bundled-skills/swiftui-expert-skill/references/macos-views.md +357 -0
- package/bundled-skills/swiftui-expert-skill/references/macos-window-styling.md +303 -0
- package/bundled-skills/swiftui-expert-skill/references/performance-patterns.md +417 -0
- package/bundled-skills/swiftui-expert-skill/references/previews.md +313 -0
- package/bundled-skills/swiftui-expert-skill/references/scroll-patterns.md +293 -0
- package/bundled-skills/swiftui-expert-skill/references/sheet-navigation-patterns.md +363 -0
- package/bundled-skills/swiftui-expert-skill/references/soft-deprecation.md +39 -0
- package/bundled-skills/swiftui-expert-skill/references/state-management.md +492 -0
- package/bundled-skills/swiftui-expert-skill/references/text-patterns.md +34 -0
- package/bundled-skills/swiftui-expert-skill/references/trace-analysis.md +295 -0
- package/bundled-skills/swiftui-expert-skill/references/trace-recording.md +134 -0
- package/bundled-skills/swiftui-expert-skill/references/view-structure.md +854 -0
- package/bundled-skills/swiftui-expert-skill/scripts/analyze_trace.py +301 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/__init__.py +1 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/causes.py +187 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/correlate.py +179 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/events.py +291 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/hangs.py +108 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/hitches.py +145 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/summary.py +243 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/swiftui.py +195 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/time_profiler.py +135 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/xctrace.py +117 -0
- package/bundled-skills/swiftui-expert-skill/scripts/instruments_parser/xml_utils.py +224 -0
- package/bundled-skills/swiftui-expert-skill/scripts/record_trace.py +252 -0
- package/bundled-skills/technical-tutorials/README.md +90 -0
- package/bundled-skills/technical-tutorials/SKILL.md +581 -0
- package/bundled-skills/test-framework-migration-skill/SKILL.md +122 -0
- package/bundled-skills/testng-skill/SKILL.md +163 -0
- package/bundled-skills/train-sentence-transformers/SKILL.md +118 -0
- package/bundled-skills/train-sentence-transformers/references/base_model_selection.md +79 -0
- package/bundled-skills/train-sentence-transformers/references/dataset_formats.md +128 -0
- package/bundled-skills/train-sentence-transformers/references/evaluators_cross_encoder.md +116 -0
- package/bundled-skills/train-sentence-transformers/references/evaluators_sentence_transformer.md +151 -0
- package/bundled-skills/train-sentence-transformers/references/evaluators_sparse_encoder.md +121 -0
- package/bundled-skills/train-sentence-transformers/references/hardware_guide.md +105 -0
- package/bundled-skills/train-sentence-transformers/references/hf_jobs_execution.md +173 -0
- package/bundled-skills/train-sentence-transformers/references/losses_cross_encoder.md +137 -0
- package/bundled-skills/train-sentence-transformers/references/losses_sentence_transformer.md +246 -0
- package/bundled-skills/train-sentence-transformers/references/losses_sparse_encoder.md +106 -0
- package/bundled-skills/train-sentence-transformers/references/model_architectures.md +178 -0
- package/bundled-skills/train-sentence-transformers/references/prompts_and_instructions.md +160 -0
- package/bundled-skills/train-sentence-transformers/references/training_args.md +269 -0
- package/bundled-skills/train-sentence-transformers/references/troubleshooting.md +225 -0
- package/bundled-skills/train-sentence-transformers/scripts/mine_hard_negatives.py +199 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_cross_encoder_distillation_example.py +254 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_cross_encoder_example.py +253 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_cross_encoder_listwise_example.py +282 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_distillation_example.py +303 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_example.py +227 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_make_multilingual_example.py +308 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_matryoshka_example.py +212 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_multi_dataset_example.py +258 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_static_embedding_example.py +273 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sentence_transformer_with_lora_example.py +275 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sparse_encoder_distillation_example.py +262 -0
- package/bundled-skills/train-sentence-transformers/scripts/train_sparse_encoder_example.py +237 -0
- package/bundled-skills/transformers-js/SKILL.md +83 -29
- package/bundled-skills/transformers-js/references/CONFIGURATION.md +55 -7
- package/bundled-skills/transformers-js/references/EXAMPLES.md +98 -83
- package/bundled-skills/transformers-js/references/MODEL_REGISTRY.md +197 -0
- package/bundled-skills/transformers-js/references/PIPELINE_OPTIONS.md +31 -19
- package/bundled-skills/transformers-js/references/TEXT_GENERATION.md +18 -18
- package/bundled-skills/trl-training/SKILL.md +327 -0
- package/bundled-skills/tune-monitor/SKILL.md +268 -0
- package/bundled-skills/ui-a11y/SKILL.md +76 -68
- package/bundled-skills/ui-component/SKILL.md +54 -82
- package/bundled-skills/ui-lint/SKILL.md +111 -0
- package/bundled-skills/ui-motion/SKILL.md +181 -0
- package/bundled-skills/ui-page/SKILL.md +80 -90
- package/bundled-skills/ui-pattern/SKILL.md +50 -68
- package/bundled-skills/ui-review/SKILL.md +95 -77
- package/bundled-skills/ui-score/SKILL.md +145 -0
- package/bundled-skills/ui-setup/SKILL.md +196 -88
- package/bundled-skills/ui-skills-root/SKILL.md +72 -0
- package/bundled-skills/ui-tokens/SKILL.md +44 -52
- package/bundled-skills/ui-update/SKILL.md +167 -0
- package/bundled-skills/unslop-commit/SKILL.md +113 -0
- package/bundled-skills/unslop-file/SKILL.md +157 -0
- package/bundled-skills/unslop-review/SKILL.md +102 -0
- package/bundled-skills/update-swiftui-apis/SKILL.md +120 -0
- package/bundled-skills/update-swiftui-apis/references/scan-manifest.md +230 -0
- package/bundled-skills/upgrading-expo/SKILL.md +107 -82
- package/bundled-skills/upgrading-expo/agents/openai.yaml +4 -0
- package/bundled-skills/upgrading-expo/references/expo-av-to-audio.md +132 -0
- package/bundled-skills/upgrading-expo/references/expo-av-to-video.md +160 -0
- package/bundled-skills/upgrading-expo/references/native-tabs.md +124 -0
- package/bundled-skills/upgrading-expo/references/new-architecture.md +79 -0
- package/bundled-skills/upgrading-expo/references/react-19.md +79 -0
- package/bundled-skills/upgrading-expo/references/react-compiler.md +59 -0
- package/bundled-skills/upgrading-expo/references/react-navigation-to-expo-router.md +61 -0
- package/bundled-skills/usage-based-pricing/README.md +40 -0
- package/bundled-skills/usage-based-pricing/SKILL.md +547 -0
- package/bundled-skills/use-dom/SKILL.md +428 -0
- package/bundled-skills/use-dom/agents/openai.yaml +4 -0
- package/bundled-skills/ux-audit/SKILL.md +112 -44
- package/bundled-skills/ux-copy/SKILL.md +105 -73
- package/bundled-skills/ux-feedback/SKILL.md +106 -58
- package/bundled-skills/ux-flow/SKILL.md +51 -50
- package/bundled-skills/vitest-skill/SKILL.md +165 -0
- package/bundled-skills/weaviate/scripts/weaviate_conn.py +16 -6
- package/bundled-skills/webdriverio-skill/SKILL.md +157 -0
- package/bundled-skills/wjttc-builder/SKILL.md +355 -0
- package/bundled-skills/wjttc-tester/SKILL.md +190 -0
- package/package.json +1 -1
- package/skills_index.json +4320 -132
|
@@ -0,0 +1,854 @@
|
|
|
1
|
+
# SwiftUI View Structure Reference
|
|
2
|
+
|
|
3
|
+
## Table of Contents
|
|
4
|
+
|
|
5
|
+
- [View Structure Principles](#view-structure-principles)
|
|
6
|
+
- [View File Structure (optional readability suggestion)](#view-file-structure-optional-readability-suggestion)
|
|
7
|
+
- [Struct or Method / Computed Property?](#struct-or-method--computed-property)
|
|
8
|
+
- [Prefer Modifiers Over Conditional Views](#prefer-modifiers-over-conditional-views)
|
|
9
|
+
- [Extract Subviews, Not Computed Properties](#extract-subviews-not-computed-properties)
|
|
10
|
+
- [@ViewBuilder](#viewbuilder)
|
|
11
|
+
- [Keep View Body Simple and Avoid High-Cost Operations](#keep-view-body-simple-and-avoid-high-cost-operations)
|
|
12
|
+
- [Keep View `init` Cheap](#keep-view-init-cheap)
|
|
13
|
+
- [Single-Child Group](#single-child-group)
|
|
14
|
+
- [When to Extract Subviews](#when-to-extract-subviews)
|
|
15
|
+
- [Container View Pattern](#container-view-pattern)
|
|
16
|
+
- [Utilize Lazy Containers for Large Data Sets](#utilize-lazy-containers-for-large-data-sets)
|
|
17
|
+
- [ZStack vs overlay/background](#zstack-vs-overlaybackground)
|
|
18
|
+
- [Compositing Group Before Clipping](#compositing-group-before-clipping)
|
|
19
|
+
- [Split State-Driven Parts into Custom View Types](#split-state-driven-parts-into-custom-view-types)
|
|
20
|
+
- [Reusable Styling with ViewModifier](#reusable-styling-with-viewmodifier)
|
|
21
|
+
- [Skeleton Loading with Redacted Views](#skeleton-loading-with-redacted-views)
|
|
22
|
+
- [AnyView](#anyview)
|
|
23
|
+
- [UIViewRepresentable Essentials](#uiviewrepresentable-essentials)
|
|
24
|
+
- [Troubleshooting](#troubleshooting)
|
|
25
|
+
- [Summary Checklist](#summary-checklist)
|
|
26
|
+
|
|
27
|
+
## View Structure Principles
|
|
28
|
+
|
|
29
|
+
SwiftUI's diffing algorithm compares view hierarchies to determine what needs updating. Proper view composition directly impacts performance.
|
|
30
|
+
|
|
31
|
+
## View File Structure (optional readability suggestion)
|
|
32
|
+
|
|
33
|
+
Property ordering has no effect on correctness or performance, so treat this as a personal/team readability preference rather than a rule. Some developers find a consistent order easier to scan — for example, environment, then state, then passed-in properties, then `init`, body, and helper subviews. Adopt it only if your team wants the consistency; never reorder existing code solely to match it.
|
|
34
|
+
|
|
35
|
+
```swift
|
|
36
|
+
struct ContentView: View {
|
|
37
|
+
// MARK: - Environment Properties
|
|
38
|
+
@Environment(\.colorScheme) var colorScheme
|
|
39
|
+
|
|
40
|
+
// MARK: - State Properties
|
|
41
|
+
@Binding var isToggled: Bool
|
|
42
|
+
@State private var viewModel: SomeViewModel
|
|
43
|
+
|
|
44
|
+
// MARK: - Private Properties
|
|
45
|
+
private let title: String = "SwiftUI Guide"
|
|
46
|
+
|
|
47
|
+
// MARK: - Initializer (if needed)
|
|
48
|
+
init(isToggled: Binding<Bool>) {
|
|
49
|
+
self._isToggled = isToggled
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// MARK: - Body
|
|
53
|
+
var body: some View {
|
|
54
|
+
VStack {
|
|
55
|
+
header
|
|
56
|
+
content
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// MARK: - Computed Subviews
|
|
61
|
+
private var header: some View {
|
|
62
|
+
Text(title).font(.largeTitle).padding()
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private var content: some View {
|
|
66
|
+
VStack {
|
|
67
|
+
Text("Counter: \(counter)")
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Struct or Method / Computed Property?
|
|
74
|
+
|
|
75
|
+
If a `View` is intended to be reusable across multiple screens, encapsulate it within a separate `struct`. If its usage is confined to a single context, it can be declared as a function or computed property within the containing `View`.
|
|
76
|
+
|
|
77
|
+
However, if a view maintains state using `@State`, `@Binding`, `@ObservedObject`, `@Environment`, `@StateObject`, or similar wrappers, it should generally be a separate `struct`.
|
|
78
|
+
|
|
79
|
+
- For simple, static views: a computed property is acceptable.
|
|
80
|
+
- For views requiring parameters: a method is more appropriate, but only when those parameters are stable. If parameters change per-call (e.g. inside a `ForEach` where each call receives a different item), prefer a separate `struct` so SwiftUI can diff inputs and skip body evaluation.
|
|
81
|
+
- For reusable, stateful, or logically independent UI sections: prefer a dedicated `struct`.
|
|
82
|
+
|
|
83
|
+
```swift
|
|
84
|
+
struct ContentView: View {
|
|
85
|
+
var titleView: some View {
|
|
86
|
+
Text("Hello from Property")
|
|
87
|
+
.font(.largeTitle)
|
|
88
|
+
.foregroundColor(.blue)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
func messageView(text: String, color: Color) -> some View {
|
|
92
|
+
Text(text)
|
|
93
|
+
.font(.title)
|
|
94
|
+
.foregroundColor(color)
|
|
95
|
+
.padding()
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var body: some View {
|
|
99
|
+
VStack {
|
|
100
|
+
titleView
|
|
101
|
+
messageView(text: "Hello from Method", color: .red)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Prefer Modifiers Over Conditional Views
|
|
108
|
+
|
|
109
|
+
**Prefer "no-effect" modifiers over conditionally including views.** When you introduce a branch, consider whether you're representing multiple views or two states of the same view.
|
|
110
|
+
|
|
111
|
+
### Use Opacity Instead of Conditional Inclusion
|
|
112
|
+
|
|
113
|
+
```swift
|
|
114
|
+
// Good - same view, different states
|
|
115
|
+
SomeView()
|
|
116
|
+
.opacity(isVisible ? 1 : 0)
|
|
117
|
+
|
|
118
|
+
// Avoid - creates/destroys view identity
|
|
119
|
+
if isVisible {
|
|
120
|
+
SomeView()
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Why**: Conditional view inclusion can cause loss of state, poor animation performance, and breaks view identity. Using modifiers maintains view identity across state changes.
|
|
125
|
+
|
|
126
|
+
### When Conditionals Are Appropriate
|
|
127
|
+
|
|
128
|
+
Use conditionals when you truly have **different views**, not different states:
|
|
129
|
+
|
|
130
|
+
```swift
|
|
131
|
+
// Correct - fundamentally different views
|
|
132
|
+
if isLoggedIn {
|
|
133
|
+
DashboardView()
|
|
134
|
+
} else {
|
|
135
|
+
LoginView()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Correct - optional content
|
|
139
|
+
if let user {
|
|
140
|
+
UserProfileView(user: user)
|
|
141
|
+
}
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### Conditional View Modifier Extensions Break Identity
|
|
145
|
+
|
|
146
|
+
A common pattern is an `if`-based `View` extension for conditional modifiers. This changes the view's return type between branches, which destroys view identity and breaks animations:
|
|
147
|
+
|
|
148
|
+
```swift
|
|
149
|
+
// Problematic -- different return types per branch
|
|
150
|
+
extension View {
|
|
151
|
+
@ViewBuilder func `if`<T: View>(_ condition: Bool, transform: (Self) -> T) -> some View {
|
|
152
|
+
if condition {
|
|
153
|
+
transform(self) // Returns T
|
|
154
|
+
} else {
|
|
155
|
+
self // Returns Self
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Prefer applying the modifier directly with a ternary or always-present modifier:
|
|
162
|
+
|
|
163
|
+
```swift
|
|
164
|
+
// Good -- same view identity maintained
|
|
165
|
+
Text("Hello")
|
|
166
|
+
.opacity(isHighlighted ? 1 : 0.5)
|
|
167
|
+
|
|
168
|
+
// Good -- modifier always present, value changes
|
|
169
|
+
Text("Hello")
|
|
170
|
+
.foregroundStyle(isError ? .red : .primary)
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
When writing new code, never reach for a `.if` modifier. When reviewing existing code that already uses one, point out the identity/animation risk and show the ternary alternative, but don't silently refactor it as part of an unrelated change — swapping it can alter behavior (state resets, transition timing) and belongs in its own focused edit.
|
|
174
|
+
|
|
175
|
+
## Extract Subviews, Not Computed Properties
|
|
176
|
+
|
|
177
|
+
A view is SwiftUI's unit of invalidation. When an input changes, SwiftUI re-runs the body of the smallest enclosing **view type** that depends on it — every conditional, modifier chain, and string interpolation in that body, even if only one leaf actually depends on what changed. A computed property or `@ViewBuilder` helper is inlined into the parent's body, so it shares the parent's invalidation boundary and does not reduce update cost; it only reorganizes the code. A separate `View` type with narrow inputs becomes its own boundary and re-runs only when its own inputs change.
|
|
178
|
+
|
|
179
|
+
This is why "split your body for readability" is also a performance tool — but only when you split into real `View` types, not computed properties.
|
|
180
|
+
|
|
181
|
+
### The Problem with @ViewBuilder Functions
|
|
182
|
+
|
|
183
|
+
When you use `@ViewBuilder` functions or computed properties for complex views, the entire function re-executes on every parent state change:
|
|
184
|
+
|
|
185
|
+
```swift
|
|
186
|
+
// BAD - re-executes complexSection() on every tap
|
|
187
|
+
struct ParentView: View {
|
|
188
|
+
@State private var count = 0
|
|
189
|
+
|
|
190
|
+
var body: some View {
|
|
191
|
+
VStack {
|
|
192
|
+
Button("Tap: \(count)") { count += 1 }
|
|
193
|
+
complexSection() // Re-executes every tap!
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
@ViewBuilder
|
|
198
|
+
func complexSection() -> some View {
|
|
199
|
+
// Complex views that re-execute unnecessarily
|
|
200
|
+
ForEach(0..<100) { i in
|
|
201
|
+
HStack {
|
|
202
|
+
Image(systemName: "star")
|
|
203
|
+
Text("Item \(i)")
|
|
204
|
+
Spacer()
|
|
205
|
+
Text("Detail")
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### The Solution: Separate Structs
|
|
213
|
+
|
|
214
|
+
Extract to separate `struct` views. SwiftUI can skip their `body` when inputs don't change:
|
|
215
|
+
|
|
216
|
+
```swift
|
|
217
|
+
// GOOD - ComplexSection body SKIPPED when its inputs don't change
|
|
218
|
+
struct ParentView: View {
|
|
219
|
+
@State private var count = 0
|
|
220
|
+
|
|
221
|
+
var body: some View {
|
|
222
|
+
VStack {
|
|
223
|
+
Button("Tap: \(count)") { count += 1 }
|
|
224
|
+
ComplexSection() // Body skipped during re-evaluation
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
struct ComplexSection: View {
|
|
230
|
+
var body: some View {
|
|
231
|
+
ForEach(0..<100) { i in
|
|
232
|
+
HStack {
|
|
233
|
+
Image(systemName: "star")
|
|
234
|
+
Text("Item \(i)")
|
|
235
|
+
Spacer()
|
|
236
|
+
Text("Detail")
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### Why This Works
|
|
244
|
+
|
|
245
|
+
1. SwiftUI compares the `ComplexSection` struct (which has no properties)
|
|
246
|
+
2. Since nothing changed, SwiftUI skips calling `ComplexSection.body`
|
|
247
|
+
3. The complex view code never executes unnecessarily
|
|
248
|
+
|
|
249
|
+
### Multi-section detail views
|
|
250
|
+
|
|
251
|
+
The most common place this rule gets dropped is a detail screen with several distinct sections — `header + gallery + description + reviews`, `header + ingredients + steps`, `hero + specs + related`. The tempting shape is one big view with `private var header: some View`, `private var gallery: some View`, and so on. That shape shares one invalidation boundary, so a change that affects one section re-evaluates all of them. Factor each named section into its own `View` type that takes only the fields it renders, and keep the parent thin — it just composes the sections.
|
|
252
|
+
|
|
253
|
+
```swift
|
|
254
|
+
// PREFER: each section is its own type with narrow inputs.
|
|
255
|
+
struct ProductDetailView: View {
|
|
256
|
+
let product: Product
|
|
257
|
+
|
|
258
|
+
var body: some View {
|
|
259
|
+
ScrollView {
|
|
260
|
+
VStack(alignment: .leading, spacing: 24) {
|
|
261
|
+
ProductHeader(name: product.name, price: product.price)
|
|
262
|
+
ProductGallery(images: product.imageURLs)
|
|
263
|
+
ProductDescription(text: product.descriptionText)
|
|
264
|
+
ProductReviews(average: product.averageStars, count: product.reviewCount)
|
|
265
|
+
}
|
|
266
|
+
.padding()
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
This generalizes to every `*DetailView`: one `View` type per section, narrow inputs each, a thin parent that composes them. Small `@ViewBuilder` fragments reused two or three times within the same body are still fine — the rule targets factoring done for organization or to manage body length, where a real `View` type does the right thing.
|
|
273
|
+
|
|
274
|
+
## @ViewBuilder
|
|
275
|
+
|
|
276
|
+
Use `@ViewBuilder` functions for small, simple sections (a few views, no expensive computation) that don't affect performance. They work particularly well for static content that doesn't depend on any `@State` or `@Binding`, since SwiftUI won't need to diff them independently. Extract to a separate `struct` when the section is complex, depends on state, or needs to be skipped during re-evaluation.
|
|
277
|
+
|
|
278
|
+
The `@ViewBuilder` attribute is only required when a function or computed property returns multiple different views conditionally, for example through `if` or `switch`:
|
|
279
|
+
|
|
280
|
+
```swift
|
|
281
|
+
@ViewBuilder
|
|
282
|
+
private var conditionalView: some View {
|
|
283
|
+
if isExpanded {
|
|
284
|
+
VStack {
|
|
285
|
+
Text("Expanded View")
|
|
286
|
+
Image(systemName: "star")
|
|
287
|
+
}
|
|
288
|
+
} else {
|
|
289
|
+
Text("Collapsed View")
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
If every branch returns the same concrete type, `@ViewBuilder` is unnecessary:
|
|
295
|
+
|
|
296
|
+
```swift
|
|
297
|
+
var conditionalText: some View {
|
|
298
|
+
if Bool.random() {
|
|
299
|
+
Text("Hello")
|
|
300
|
+
} else {
|
|
301
|
+
Text("World")
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
Prefer `@ViewBuilder` when:
|
|
307
|
+
|
|
308
|
+
- there is conditional branching between multiple view types
|
|
309
|
+
- extracting a separate `struct` would not provide meaningful separation
|
|
310
|
+
|
|
311
|
+
## Keep View Body Simple and Avoid High-Cost Operations
|
|
312
|
+
|
|
313
|
+
Refrain from performing complex operations within the `body` of your view. Instead of passing a ready-to-use sequence with filtering, mapping, or sorting directly into `ForEach`, prepare the sequence outside the body.
|
|
314
|
+
|
|
315
|
+
```swift
|
|
316
|
+
// Avoid such things ...
|
|
317
|
+
var body: some View {
|
|
318
|
+
List {
|
|
319
|
+
ForEach(model.values.filter { $0 > 0 }, id: \.self) {
|
|
320
|
+
Text(String($0))
|
|
321
|
+
.padding()
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Prefer:
|
|
328
|
+
|
|
329
|
+
```swift
|
|
330
|
+
struct FilteredListView: View {
|
|
331
|
+
private let filteredValues: [Int]
|
|
332
|
+
|
|
333
|
+
init(values: [Int]) {
|
|
334
|
+
self.filteredValues = values.filter { $0 > 0 } // Perform filtering once
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
var body: some View {
|
|
338
|
+
List {
|
|
339
|
+
content
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
private var content: some View {
|
|
344
|
+
ForEach(filteredValues, id: \.self) { value in
|
|
345
|
+
Text(String(value))
|
|
346
|
+
.padding()
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
The reason this matters is that the system can call `body` multiple times during a single layout phase. Complex body computation makes those calls more expensive than necessary.
|
|
353
|
+
|
|
354
|
+
General guidance:
|
|
355
|
+
|
|
356
|
+
- avoid filtering, sorting, and mapping inline in `body`
|
|
357
|
+
- avoid constructing expensive formatters in `body`
|
|
358
|
+
- avoid heavy branching in large view trees
|
|
359
|
+
- move data preparation into the model layer or dedicated helpers
|
|
360
|
+
|
|
361
|
+
## Keep View `init` Cheap
|
|
362
|
+
|
|
363
|
+
A view's `init` runs every time the parent re-evaluates its body, which can be many times per second for views inside `List`, `LazyVStack`, scroll containers, or animated parents. Treat `init` as a constant-time copy of inputs into stored properties. Don't decode JSON, build a `DateFormatter`, touch the file system, or allocate large structures there — that work repeats on every parent body pass even when the inputs are identical.
|
|
364
|
+
|
|
365
|
+
```swift
|
|
366
|
+
// AVOID: decoding and formatting on every init
|
|
367
|
+
init(rawJSON: Data, date: Date) {
|
|
368
|
+
self.summary = try! JSONDecoder().decode(WeatherSummary.self, from: rawJSON)
|
|
369
|
+
let formatter = DateFormatter()
|
|
370
|
+
formatter.dateStyle = .medium
|
|
371
|
+
self.formattedDate = formatter.string(from: date)
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// PREFER: take already-prepared values; format lazily in body
|
|
375
|
+
let summary: WeatherSummary
|
|
376
|
+
let date: Date
|
|
377
|
+
|
|
378
|
+
var body: some View {
|
|
379
|
+
VStack {
|
|
380
|
+
Text(summary.headline)
|
|
381
|
+
Text(date, format: .dateTime.day().month().year()) // cached, locale-aware
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
If a derived value genuinely needs to be computed once and kept, store it on an `@State`-owned `@Observable` model or compute it asynchronously in `.task` — not in `init`. `init` is not a one-time setup hook; it runs as often as the parent's body does.
|
|
387
|
+
|
|
388
|
+
## Single-Child Group
|
|
389
|
+
|
|
390
|
+
`Group { SomeView() }` — a `Group` with exactly one concrete child — wraps the view in an extra `Group<SomeView>` type for no visual benefit. Every modifier chained after it must be type-checked against that wrapper, adding avoidable type-checking overhead in long chains. Drop the `Group` and chain modifiers directly on the child.
|
|
391
|
+
|
|
392
|
+
```swift
|
|
393
|
+
// AVOID: single concrete child wrapped in Group
|
|
394
|
+
Group { Text(status) }
|
|
395
|
+
.padding(.horizontal, 8)
|
|
396
|
+
.background(.thinMaterial, in: Capsule())
|
|
397
|
+
|
|
398
|
+
// PREFER: chain directly on the child
|
|
399
|
+
Text(status)
|
|
400
|
+
.padding(.horizontal, 8)
|
|
401
|
+
.background(.thinMaterial, in: Capsule())
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
The rule is specifically about one concrete view. A `Group` whose content is a `ForEach`, multiple sibling views, or an `if`/`else` (which produces `_ConditionalContent`) is doing real work — applying a shared modifier across siblings or both branches — and is fine.
|
|
405
|
+
|
|
406
|
+
## When to Extract Subviews
|
|
407
|
+
|
|
408
|
+
Extract complex views into separate subviews when:
|
|
409
|
+
- The view has multiple logical sections or responsibilities
|
|
410
|
+
- The view contains reusable components
|
|
411
|
+
- The view body becomes difficult to read or understand
|
|
412
|
+
- You need to isolate state changes for performance
|
|
413
|
+
- The view is becoming large (keep views small for better performance)
|
|
414
|
+
- The section may evolve independently over time
|
|
415
|
+
|
|
416
|
+
## Container View Pattern
|
|
417
|
+
|
|
418
|
+
### Avoid Closure-Based Content
|
|
419
|
+
|
|
420
|
+
Closures can't be compared, causing unnecessary re-renders:
|
|
421
|
+
|
|
422
|
+
```swift
|
|
423
|
+
// BAD - closure prevents SwiftUI from skipping updates
|
|
424
|
+
struct MyContainer<Content: View>: View {
|
|
425
|
+
let content: () -> Content
|
|
426
|
+
|
|
427
|
+
var body: some View {
|
|
428
|
+
VStack {
|
|
429
|
+
Text("Header")
|
|
430
|
+
content() // Always called, can't compare closures
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Usage forces re-render on every parent update
|
|
436
|
+
MyContainer {
|
|
437
|
+
ExpensiveView()
|
|
438
|
+
}
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Use @ViewBuilder Property Instead
|
|
442
|
+
|
|
443
|
+
```swift
|
|
444
|
+
// GOOD - view can be compared
|
|
445
|
+
struct MyContainer<Content: View>: View {
|
|
446
|
+
@ViewBuilder let content: Content
|
|
447
|
+
|
|
448
|
+
var body: some View {
|
|
449
|
+
VStack {
|
|
450
|
+
Text("Header")
|
|
451
|
+
content // SwiftUI can compare and skip if unchanged
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
// Usage - SwiftUI can diff ExpensiveView
|
|
457
|
+
MyContainer {
|
|
458
|
+
ExpensiveView()
|
|
459
|
+
}
|
|
460
|
+
```
|
|
461
|
+
|
|
462
|
+
## Utilize Lazy Containers for Large Data Sets
|
|
463
|
+
|
|
464
|
+
When displaying extensive lists or grids, prefer `LazyVStack`, `LazyHStack`, `LazyVGrid`, or `LazyHGrid`. These containers load views only when they appear on the screen, reducing memory usage and improving performance.
|
|
465
|
+
|
|
466
|
+
```swift
|
|
467
|
+
struct ContentView: View {
|
|
468
|
+
let items = Array(0..<1000)
|
|
469
|
+
|
|
470
|
+
var body: some View {
|
|
471
|
+
ScrollView {
|
|
472
|
+
LazyVStack {
|
|
473
|
+
ForEach(items, id: \.self) { item in
|
|
474
|
+
Text("Item \(item)")
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
Prefer lazy containers when:
|
|
483
|
+
|
|
484
|
+
- rendering large collections
|
|
485
|
+
- row views are non-trivial
|
|
486
|
+
- memory usage matters
|
|
487
|
+
- the content is inside `ScrollView`
|
|
488
|
+
|
|
489
|
+
## ZStack vs overlay/background
|
|
490
|
+
|
|
491
|
+
Use `ZStack` to **compose multiple peer views** that should be layered together and jointly define layout.
|
|
492
|
+
|
|
493
|
+
Prefer `overlay` / `background` when you’re **decorating a primary view**.
|
|
494
|
+
Not primarily because they don’t affect layout size, but because they **express intent and improve readability**: the view being modified remains the clear layout anchor.
|
|
495
|
+
|
|
496
|
+
A key difference is **size proposal behavior**:
|
|
497
|
+
- In `overlay` / `background`, the child view implicitly adopts the size proposed to the parent when it doesn’t define its own size, making decorative attachments feel natural and predictable.
|
|
498
|
+
- In `ZStack`, each child participates independently in layout, and no implicit size inheritance exists. This makes it better suited for peer composition, but less intuitive for simple decoration.
|
|
499
|
+
|
|
500
|
+
Use `ZStack` (or another container) when the “decoration” **must explicitly participate in layout sizing**—for example, when reserving space, extending tappable/visible bounds, or preventing overlap with neighboring views.
|
|
501
|
+
|
|
502
|
+
### Examples
|
|
503
|
+
|
|
504
|
+
```swift
|
|
505
|
+
// GOOD - decoration via overlay (layout anchored to button)
|
|
506
|
+
Button("Continue") { }
|
|
507
|
+
.overlay(alignment: .trailing) {
|
|
508
|
+
Image(systemName: "lock.fill").padding(.trailing, 8)
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// BAD - ZStack when overlay suffices (layout no longer anchored to button)
|
|
512
|
+
ZStack(alignment: .trailing) {
|
|
513
|
+
Button("Continue") { }
|
|
514
|
+
Image(systemName: "lock.fill").padding(.trailing, 8)
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// GOOD - background shape takes parent size
|
|
518
|
+
HStack(spacing: 12) { Text("Inbox"); Text("Next") }
|
|
519
|
+
.background { Capsule().strokeBorder(.blue, lineWidth: 2) }
|
|
520
|
+
```
|
|
521
|
+
|
|
522
|
+
## Compositing Group Before Clipping
|
|
523
|
+
|
|
524
|
+
**Always add `.compositingGroup()` before `.clipShape()` when clipping layered views (`.overlay` or `.background`).** Without it, each layer is antialiased separately and then composited. Where antialiased edges overlap — typically at rounded corners — you get visible color fringes (semi-transparent pixels of different colors blending together).
|
|
525
|
+
|
|
526
|
+
```swift
|
|
527
|
+
let shape = RoundedRectangle(cornerRadius: 16)
|
|
528
|
+
|
|
529
|
+
// BAD - each layer antialiased separately, producing color fringes at corners
|
|
530
|
+
Color.red
|
|
531
|
+
.overlay(.white, in: shape)
|
|
532
|
+
.clipShape(shape)
|
|
533
|
+
.frame(width: 200, height: 150)
|
|
534
|
+
|
|
535
|
+
// GOOD - layers composited first, antialiasing applied once during clipping
|
|
536
|
+
Color.red
|
|
537
|
+
.overlay(.white, in: .rect)
|
|
538
|
+
.compositingGroup()
|
|
539
|
+
.clipShape(shape)
|
|
540
|
+
.frame(width: 200, height: 150)
|
|
541
|
+
```
|
|
542
|
+
|
|
543
|
+
`.compositingGroup()` forces all child layers to be rendered into a single offscreen buffer before the clip is applied. This means antialiasing only happens once — on the final composited result — eliminating the fringe artifacts.
|
|
544
|
+
|
|
545
|
+
## Split State-Driven Parts into Custom View Types
|
|
546
|
+
|
|
547
|
+
Large views often depend on multiple independent state sources. If a single view body depends on all of them, then any state change can cause the entire body to re-evaluate.
|
|
548
|
+
|
|
549
|
+
```swift
|
|
550
|
+
struct BigAndComplicatedView: View {
|
|
551
|
+
@State private var counter = 0
|
|
552
|
+
@State private var isToggled = false
|
|
553
|
+
@StateObject private var viewModel = SomeViewModel()
|
|
554
|
+
|
|
555
|
+
let title = "Big and Complicated View"
|
|
556
|
+
|
|
557
|
+
var body: some View {
|
|
558
|
+
VStack {
|
|
559
|
+
Text(title)
|
|
560
|
+
.font(.largeTitle)
|
|
561
|
+
|
|
562
|
+
Text("Counter: \(counter)")
|
|
563
|
+
.font(.title)
|
|
564
|
+
|
|
565
|
+
Toggle("Enable Feature", isOn: $isToggled)
|
|
566
|
+
.padding()
|
|
567
|
+
|
|
568
|
+
Button("Increment Counter") {
|
|
569
|
+
counter += 1
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
Text("ViewModel Data: \(viewModel.data)")
|
|
573
|
+
.padding()
|
|
574
|
+
|
|
575
|
+
Button("Fetch Data") {
|
|
576
|
+
viewModel.fetchData()
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Better: Split Into Smaller Components
|
|
584
|
+
|
|
585
|
+
```swift
|
|
586
|
+
struct BigAndComplicatedView: View {
|
|
587
|
+
@State private var counter = 0
|
|
588
|
+
@State private var isToggled = false
|
|
589
|
+
@StateObject private var viewModel = SomeViewModel()
|
|
590
|
+
|
|
591
|
+
var body: some View {
|
|
592
|
+
VStack {
|
|
593
|
+
titleView
|
|
594
|
+
CounterView(counter: $counter)
|
|
595
|
+
ToggleView(isToggled: $isToggled)
|
|
596
|
+
ViewModelDataView(data: viewModel.data) {
|
|
597
|
+
viewModel.updateData()
|
|
598
|
+
}
|
|
599
|
+
.equatable()
|
|
600
|
+
}
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
private var titleView: some View {
|
|
604
|
+
Text("Big and Complicated View")
|
|
605
|
+
.font(.largeTitle)
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
Why this is better:
|
|
611
|
+
|
|
612
|
+
- changing `counter` only affects `CounterView`
|
|
613
|
+
- toggling only affects `ToggleView`
|
|
614
|
+
- updating the model data only affects `ViewModelDataView`
|
|
615
|
+
|
|
616
|
+
### Notes on Equatable
|
|
617
|
+
|
|
618
|
+
Using `Equatable` for a view is not a universal best practice, but it can be useful in targeted cases where:
|
|
619
|
+
|
|
620
|
+
- the input is small and well-defined
|
|
621
|
+
- the comparison logic is meaningful
|
|
622
|
+
- you want to reduce unnecessary body evaluation for a specific subtree
|
|
623
|
+
|
|
624
|
+
Do not use `Equatable` as a blanket optimization technique.
|
|
625
|
+
|
|
626
|
+
## Reusable Styling with ViewModifier
|
|
627
|
+
|
|
628
|
+
Extract repeated modifier combinations into a `ViewModifier` struct. Expose via a `View` extension for autocompletion:
|
|
629
|
+
|
|
630
|
+
```swift
|
|
631
|
+
private struct CardStyle: ViewModifier {
|
|
632
|
+
func body(content: Content) -> some View {
|
|
633
|
+
content
|
|
634
|
+
.padding()
|
|
635
|
+
.background(Color(.secondarySystemBackground))
|
|
636
|
+
.clipShape(.rect(cornerRadius: 12))
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
extension View {
|
|
641
|
+
func cardStyle() -> some View {
|
|
642
|
+
modifier(CardStyle())
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
```
|
|
646
|
+
|
|
647
|
+
### Custom ButtonStyle
|
|
648
|
+
|
|
649
|
+
Use the `ButtonStyle` protocol for reusable button designs. Use `PrimitiveButtonStyle` only when you need custom interaction handling (e.g., simultaneous gestures):
|
|
650
|
+
|
|
651
|
+
```swift
|
|
652
|
+
struct PrimaryButtonStyle: ButtonStyle {
|
|
653
|
+
func makeBody(configuration: Configuration) -> some View {
|
|
654
|
+
configuration.label
|
|
655
|
+
.bold()
|
|
656
|
+
.foregroundStyle(.white)
|
|
657
|
+
.padding(.horizontal, 16)
|
|
658
|
+
.padding(.vertical, 8)
|
|
659
|
+
.background(Color.accentColor)
|
|
660
|
+
.clipShape(Capsule())
|
|
661
|
+
.scaleEffect(configuration.isPressed ? 0.95 : 1)
|
|
662
|
+
.animation(.smooth, value: configuration.isPressed)
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
```
|
|
666
|
+
|
|
667
|
+
### Discoverability with Static Member Lookup
|
|
668
|
+
|
|
669
|
+
Make custom styles and modifiers discoverable via leading-dot syntax:
|
|
670
|
+
|
|
671
|
+
```swift
|
|
672
|
+
extension ButtonStyle where Self == PrimaryButtonStyle {
|
|
673
|
+
static var primary: PrimaryButtonStyle { .init() }
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// Usage: .buttonStyle(.primary)
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
This pattern works for any SwiftUI style protocol (`ButtonStyle`, `ListStyle`, `ToggleStyle`, etc.).
|
|
680
|
+
|
|
681
|
+
## Skeleton Loading with Redacted Views
|
|
682
|
+
|
|
683
|
+
Use `.redacted(reason: .placeholder)` to show skeleton views while data loads. Use `.unredacted()` to opt out specific views:
|
|
684
|
+
|
|
685
|
+
```swift
|
|
686
|
+
VStack(alignment: .leading) {
|
|
687
|
+
Text(article?.title ?? String(repeating: "X", count: 20))
|
|
688
|
+
.font(.headline)
|
|
689
|
+
Text(article?.author ?? String(repeating: "X", count: 12))
|
|
690
|
+
.font(.subheadline)
|
|
691
|
+
Text("SwiftLee")
|
|
692
|
+
.font(.caption)
|
|
693
|
+
.unredacted()
|
|
694
|
+
}
|
|
695
|
+
.redacted(reason: article == nil ? .placeholder : [])
|
|
696
|
+
```
|
|
697
|
+
|
|
698
|
+
Apply `.redacted` on a container to redact all children at once.
|
|
699
|
+
|
|
700
|
+
## AnyView
|
|
701
|
+
|
|
702
|
+
`AnyView` is type erasure. SwiftUI uses structural identity based on type information to determine when views should be updated.
|
|
703
|
+
|
|
704
|
+
```swift
|
|
705
|
+
private var nameView: some View {
|
|
706
|
+
if isEditable {
|
|
707
|
+
TextField("Your name", text: $name)
|
|
708
|
+
} else {
|
|
709
|
+
Text(name)
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
```
|
|
713
|
+
|
|
714
|
+
Avoid patterns like:
|
|
715
|
+
|
|
716
|
+
```swift
|
|
717
|
+
private var nameView: some View {
|
|
718
|
+
if isEditable {
|
|
719
|
+
return AnyView(TextField("Your name", text: $name))
|
|
720
|
+
} else {
|
|
721
|
+
return AnyView(Text(name))
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
```
|
|
725
|
+
|
|
726
|
+
Because `AnyView` erases type information, SwiftUI loses some optimization opportunities. Prefer `@ViewBuilder` or conditional branches with concrete view types.
|
|
727
|
+
|
|
728
|
+
Use `AnyView` only when type erasure is truly necessary for API design.
|
|
729
|
+
|
|
730
|
+
## UIViewRepresentable Essentials
|
|
731
|
+
|
|
732
|
+
When bridging UIKit views into SwiftUI:
|
|
733
|
+
|
|
734
|
+
- `makeUIView(context:)` is called **once** to create the UIKit view
|
|
735
|
+
- `updateUIView(_:context:)` is called on **every SwiftUI redraw** to sync state
|
|
736
|
+
- The representable struct itself is **recreated on every redraw** -- avoid heavy work in its init
|
|
737
|
+
- Use a `Coordinator` for delegate callbacks and two-way communication
|
|
738
|
+
|
|
739
|
+
```swift
|
|
740
|
+
struct MapView: UIViewRepresentable {
|
|
741
|
+
let coordinate: CLLocationCoordinate2D
|
|
742
|
+
|
|
743
|
+
func makeUIView(context: Context) -> MKMapView {
|
|
744
|
+
let map = MKMapView()
|
|
745
|
+
map.delegate = context.coordinator
|
|
746
|
+
return map
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
func updateUIView(_ map: MKMapView, context: Context) {
|
|
750
|
+
map.setCenter(coordinate, animated: true)
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
func makeCoordinator() -> Coordinator { Coordinator() }
|
|
754
|
+
|
|
755
|
+
class Coordinator: NSObject, MKMapViewDelegate { }
|
|
756
|
+
}
|
|
757
|
+
```
|
|
758
|
+
|
|
759
|
+
## Troubleshooting
|
|
760
|
+
|
|
761
|
+
### Debug SwiftUI Renderings
|
|
762
|
+
|
|
763
|
+
> See `references/performance-patterns.md` (item #8) for the `_printChanges()` vs `_logChanges()` comparison and the `@self`/`@identity` output meaning. The snippets below show the call sites.
|
|
764
|
+
|
|
765
|
+
If it is needed to debug render cycles and read console output you can leverage the `_printChanges()` or `_logChanges()` methods on `View`. These methods print information about when the view is being evaluated and what changes are triggering updates. This can be very helpful when your view body is called multiple times and you want to know why.
|
|
766
|
+
|
|
767
|
+
```swift
|
|
768
|
+
struct ContentView: View {
|
|
769
|
+
@State private var counter: Int = 99
|
|
770
|
+
|
|
771
|
+
init() {
|
|
772
|
+
print(Self.self, #function)
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
var body: some View {
|
|
776
|
+
let _ = Self._printChanges()
|
|
777
|
+
|
|
778
|
+
VStack {
|
|
779
|
+
Text("Counter: \(counter)")
|
|
780
|
+
Button {
|
|
781
|
+
counter += 1
|
|
782
|
+
} label: {
|
|
783
|
+
Text("Counter +1")
|
|
784
|
+
}
|
|
785
|
+
.buttonStyle(.borderedProminent)
|
|
786
|
+
}
|
|
787
|
+
.padding()
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
As an alternative to `Self._printChanges()`, you can use `_logChanges()`
|
|
793
|
+
|
|
794
|
+
```swift
|
|
795
|
+
struct ContentView: View {
|
|
796
|
+
@State private var counter: Int = 99
|
|
797
|
+
|
|
798
|
+
var body: some View {
|
|
799
|
+
let _ = Self._logChanges()
|
|
800
|
+
|
|
801
|
+
VStack {
|
|
802
|
+
Text("Counter: \(counter)")
|
|
803
|
+
Button {
|
|
804
|
+
counter += 1
|
|
805
|
+
} label: {
|
|
806
|
+
Text("Counter +1")
|
|
807
|
+
}
|
|
808
|
+
.buttonStyle(.borderedProminent)
|
|
809
|
+
}
|
|
810
|
+
.padding()
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
Use these tools only for debugging and remove them from production code.
|
|
816
|
+
|
|
817
|
+
### Handling "The Compiler Is Unable to Type-Check This Expression in Reasonable Time"
|
|
818
|
+
|
|
819
|
+
If you encounter:
|
|
820
|
+
|
|
821
|
+
> The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions
|
|
822
|
+
|
|
823
|
+
it is often caused by overly complex view structures or expressions.
|
|
824
|
+
|
|
825
|
+
Ways to fix it:
|
|
826
|
+
|
|
827
|
+
- break large expressions into smaller computed values
|
|
828
|
+
- extract subviews
|
|
829
|
+
- split long modifier chains
|
|
830
|
+
- simplify nested generics and builders
|
|
831
|
+
- avoid huge inline closures
|
|
832
|
+
|
|
833
|
+
## Summary Checklist
|
|
834
|
+
|
|
835
|
+
- [ ] Prefer modifiers over conditional views for state changes
|
|
836
|
+
- [ ] Avoid `if`-based conditional modifier extensions (they break view identity)
|
|
837
|
+
- [ ] Extract complex views into separate subviews, not computed properties
|
|
838
|
+
- [ ] Keep views small for readability and performance
|
|
839
|
+
- [ ] Use `@ViewBuilder` only where it actually adds value
|
|
840
|
+
- [ ] Avoid heavy filtering, mapping, sorting, or formatter creation inside `body`
|
|
841
|
+
- [ ] Keep view `init` cheap (no decoding/formatting/allocation; it runs on every parent body pass)
|
|
842
|
+
- [ ] Avoid single-child `Group { OneView() }` (chain modifiers directly on the child)
|
|
843
|
+
- [ ] Use lazy containers for large data sets
|
|
844
|
+
- [ ] Container views use `@ViewBuilder let content: Content`
|
|
845
|
+
- [ ] Prefer `overlay` / `background` for decoration and `ZStack` for peer composition
|
|
846
|
+
- [ ] `.compositingGroup()` before `.clipShape()` on layered views to avoid antialiasing fringes
|
|
847
|
+
- [ ] Split state-heavy areas into smaller view types
|
|
848
|
+
- [ ] Extract repeated styling into `ViewModifier` or `ButtonStyle`
|
|
849
|
+
- [ ] Expose reusable styles via static member lookup when it improves discoverability
|
|
850
|
+
- [ ] Use `.redacted(reason: .placeholder)` for loading skeletons
|
|
851
|
+
- [ ] Avoid `AnyView` unless type erasure is truly needed
|
|
852
|
+
- [ ] In `UIViewRepresentable`, keep heavy work out of struct init
|
|
853
|
+
- [ ] Use `_printChanges()` / `_logChanges()` to debug rendering behavior
|
|
854
|
+
- [ ] Break up overly complex expressions when the compiler struggles
|