quiver-cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +188 -0
- package/bin/quiver-cli.mjs +2 -0
- package/dist/cli.js +3074 -0
- package/package.json +55 -0
- package/template/.agents/AGENTS.md +25 -0
- package/template/.agents/commands/cp.md +116 -0
- package/template/.agents/commands/next-setup.md +1064 -0
- package/template/.agents/commands/tf-readme.md +38 -0
- package/template/.agents/config.json +60 -0
- package/template/.agents/skills/agent-browser/SKILL.md +55 -0
- package/template/.agents/skills/apps/skybridge/SKILL.md +46 -0
- package/template/.agents/skills/apps/skybridge/references/architecture.md +175 -0
- package/template/.agents/skills/apps/skybridge/references/copy-template.md +24 -0
- package/template/.agents/skills/apps/skybridge/references/csp.md +33 -0
- package/template/.agents/skills/apps/skybridge/references/deploy.md +33 -0
- package/template/.agents/skills/apps/skybridge/references/discover.md +84 -0
- package/template/.agents/skills/apps/skybridge/references/download-file.md +77 -0
- package/template/.agents/skills/apps/skybridge/references/fetch-and-render-data.md +151 -0
- package/template/.agents/skills/apps/skybridge/references/oauth.md +115 -0
- package/template/.agents/skills/apps/skybridge/references/open-external-links.md +71 -0
- package/template/.agents/skills/apps/skybridge/references/prompt-llm.md +20 -0
- package/template/.agents/skills/apps/skybridge/references/publish.md +19 -0
- package/template/.agents/skills/apps/skybridge/references/run-locally.md +51 -0
- package/template/.agents/skills/apps/skybridge/references/state-and-context.md +151 -0
- package/template/.agents/skills/apps/skybridge/references/ui-guidelines.md +205 -0
- package/template/.agents/skills/code/cleanup/SKILL.md +26 -0
- package/template/.agents/skills/code/vercel-react-best-practices/AGENTS.md +3810 -0
- package/template/.agents/skills/code/vercel-react-best-practices/README.md +123 -0
- package/template/.agents/skills/code/vercel-react-best-practices/SKILL.md +149 -0
- package/template/.agents/skills/code/vercel-react-best-practices/metadata.json +15 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_sections.md +46 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/_template.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-effect-event-deps.md +56 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-event-handler-refs.md +55 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-init-once.md +42 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/advanced-use-latest.md +39 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-api-routes.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-defer-await.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-dependencies.md +51 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-parallel.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/async-suspense-boundaries.md +99 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-analyzable-paths.md +63 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-barrel-imports.md +60 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-conditional.md +31 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-defer-third-party.md +49 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-dynamic-imports.md +35 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/bundle-preload.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-event-listeners.md +74 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-localstorage-schema.md +71 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-passive-event-listeners.md +48 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/client-swr-dedup.md +56 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-batch-dom-css.md +107 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-function-results.md +80 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-property-access.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-cache-storage.md +70 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-combine-iterations.md +32 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-early-exit.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-flatmap-filter.md +60 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-hoist-regexp.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-index-maps.md +37 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-length-check-first.md +49 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-min-max-loop.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-request-idle-callback.md +105 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-set-map-lookups.md +24 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/js-tosorted-immutable.md +57 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-activity.md +26 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-animate-svg-wrapper.md +47 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-conditional-render.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-content-visibility.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hoist-jsx.md +46 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-no-flicker.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-hydration-suppress-warning.md +30 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-resource-hints.md +85 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-script-defer-async.md +68 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-svg-precision.md +28 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rendering-usetransition-loading.md +75 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-defer-reads.md +39 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-dependencies.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-derived-state.md +29 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-functional-setstate.md +74 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-lazy-state-init.md +58 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo-with-default-value.md +38 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-memo.md +44 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-no-inline-components.md +82 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-transitions.md +40 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-deferred-value.md +59 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-after-nonblocking.md +73 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-auth-actions.md +96 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-lru.md +41 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-cache-react.md +76 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-dedup-props.md +65 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-hoist-static-io.md +149 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-no-shared-module-state.md +50 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-fetching.md +83 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-parallel-nested-fetching.md +34 -0
- package/template/.agents/skills/code/vercel-react-best-practices/rules/server-serialization.md +38 -0
- package/template/.agents/skills/data/prisma-cli/SKILL.md +247 -0
- package/template/.agents/skills/data/prisma-cli/references/db-execute.md +78 -0
- package/template/.agents/skills/data/prisma-cli/references/db-pull.md +185 -0
- package/template/.agents/skills/data/prisma-cli/references/db-push.md +148 -0
- package/template/.agents/skills/data/prisma-cli/references/db-seed.md +188 -0
- package/template/.agents/skills/data/prisma-cli/references/debug.md +46 -0
- package/template/.agents/skills/data/prisma-cli/references/dev.md +157 -0
- package/template/.agents/skills/data/prisma-cli/references/format.md +48 -0
- package/template/.agents/skills/data/prisma-cli/references/generate.md +173 -0
- package/template/.agents/skills/data/prisma-cli/references/init.md +136 -0
- package/template/.agents/skills/data/prisma-cli/references/mcp.md +38 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-deploy.md +127 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-dev.md +145 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-diff.md +89 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-reset.md +78 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-resolve.md +57 -0
- package/template/.agents/skills/data/prisma-cli/references/migrate-status.md +65 -0
- package/template/.agents/skills/data/prisma-cli/references/studio.md +137 -0
- package/template/.agents/skills/data/prisma-cli/references/validate.md +53 -0
- package/template/.agents/skills/data/prisma-client-api/SKILL.md +216 -0
- package/template/.agents/skills/data/prisma-client-api/references/client-methods.md +223 -0
- package/template/.agents/skills/data/prisma-client-api/references/constructor.md +208 -0
- package/template/.agents/skills/data/prisma-client-api/references/filters.md +256 -0
- package/template/.agents/skills/data/prisma-client-api/references/model-queries.md +281 -0
- package/template/.agents/skills/data/prisma-client-api/references/query-options.md +276 -0
- package/template/.agents/skills/data/prisma-client-api/references/raw-queries.md +194 -0
- package/template/.agents/skills/data/prisma-client-api/references/relations.md +308 -0
- package/template/.agents/skills/data/prisma-client-api/references/transactions.md +184 -0
- package/template/.agents/skills/design/impeccable/SKILL.md +176 -0
- package/template/.agents/skills/design/impeccable/reference/adapt.md +311 -0
- package/template/.agents/skills/design/impeccable/reference/animate.md +201 -0
- package/template/.agents/skills/design/impeccable/reference/audit.md +133 -0
- package/template/.agents/skills/design/impeccable/reference/bolder.md +113 -0
- package/template/.agents/skills/design/impeccable/reference/brand.md +108 -0
- package/template/.agents/skills/design/impeccable/reference/clarify.md +288 -0
- package/template/.agents/skills/design/impeccable/reference/codex.md +105 -0
- package/template/.agents/skills/design/impeccable/reference/colorize.md +257 -0
- package/template/.agents/skills/design/impeccable/reference/craft.md +123 -0
- package/template/.agents/skills/design/impeccable/reference/critique.md +767 -0
- package/template/.agents/skills/design/impeccable/reference/delight.md +302 -0
- package/template/.agents/skills/design/impeccable/reference/distill.md +111 -0
- package/template/.agents/skills/design/impeccable/reference/document.md +429 -0
- package/template/.agents/skills/design/impeccable/reference/extract.md +69 -0
- package/template/.agents/skills/design/impeccable/reference/harden.md +347 -0
- package/template/.agents/skills/design/impeccable/reference/init.md +172 -0
- package/template/.agents/skills/design/impeccable/reference/interaction-design.md +189 -0
- package/template/.agents/skills/design/impeccable/reference/layout.md +161 -0
- package/template/.agents/skills/design/impeccable/reference/live.md +718 -0
- package/template/.agents/skills/design/impeccable/reference/onboard.md +234 -0
- package/template/.agents/skills/design/impeccable/reference/optimize.md +258 -0
- package/template/.agents/skills/design/impeccable/reference/overdrive.md +130 -0
- package/template/.agents/skills/design/impeccable/reference/polish.md +241 -0
- package/template/.agents/skills/design/impeccable/reference/product.md +60 -0
- package/template/.agents/skills/design/impeccable/reference/quieter.md +99 -0
- package/template/.agents/skills/design/impeccable/reference/shape.md +165 -0
- package/template/.agents/skills/design/impeccable/reference/typeset.md +279 -0
- package/template/.agents/skills/design/impeccable/scripts/cleanup-deprecated.mjs +284 -0
- package/template/.agents/skills/design/impeccable/scripts/command-metadata.json +94 -0
- package/template/.agents/skills/design/impeccable/scripts/context-signals.mjs +225 -0
- package/template/.agents/skills/design/impeccable/scripts/context.mjs +270 -0
- package/template/.agents/skills/design/impeccable/scripts/critique-storage.mjs +242 -0
- package/template/.agents/skills/design/impeccable/scripts/design-parser.mjs +835 -0
- package/template/.agents/skills/design/impeccable/scripts/detect-csp.mjs +198 -0
- package/template/.agents/skills/design/impeccable/scripts/detect.mjs +21 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/browser/injected/index.mjs +1733 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/cli/main.mjs +244 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns-browser.js +4551 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/findings.mjs +12 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/node/file-system.mjs +198 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/profile/profiler.mjs +166 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/rules/checks.mjs +2316 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/color.mjs +124 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/constants.mjs +101 -0
- package/template/.agents/skills/design/impeccable/scripts/detector/shared/page.mjs +7 -0
- package/template/.agents/skills/design/impeccable/scripts/impeccable-paths.mjs +126 -0
- package/template/.agents/skills/design/impeccable/scripts/is-generated.mjs +69 -0
- package/template/.agents/skills/design/impeccable/scripts/live-accept.mjs +812 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser-session.js +123 -0
- package/template/.agents/skills/design/impeccable/scripts/live-browser.js +10316 -0
- package/template/.agents/skills/design/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
- package/template/.agents/skills/design/impeccable/scripts/live-complete.mjs +75 -0
- package/template/.agents/skills/design/impeccable/scripts/live-completion.mjs +19 -0
- package/template/.agents/skills/design/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
- package/template/.agents/skills/design/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
- package/template/.agents/skills/design/impeccable/scripts/live-event-validation.mjs +136 -0
- package/template/.agents/skills/design/impeccable/scripts/live-inject.mjs +557 -0
- package/template/.agents/skills/design/impeccable/scripts/live-insert-ui.mjs +458 -0
- package/template/.agents/skills/design/impeccable/scripts/live-insert.mjs +272 -0
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
- package/template/.agents/skills/design/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
- package/template/.agents/skills/design/impeccable/scripts/live-poll.mjs +379 -0
- package/template/.agents/skills/design/impeccable/scripts/live-resume.mjs +94 -0
- package/template/.agents/skills/design/impeccable/scripts/live-server.mjs +2322 -0
- package/template/.agents/skills/design/impeccable/scripts/live-session-store.mjs +289 -0
- package/template/.agents/skills/design/impeccable/scripts/live-status.mjs +61 -0
- package/template/.agents/skills/design/impeccable/scripts/live-svelte-component.mjs +826 -0
- package/template/.agents/skills/design/impeccable/scripts/live-sveltekit-adapter.mjs +274 -0
- package/template/.agents/skills/design/impeccable/scripts/live-ui-core.mjs +179 -0
- package/template/.agents/skills/design/impeccable/scripts/live-wrap.mjs +894 -0
- package/template/.agents/skills/design/impeccable/scripts/live.mjs +246 -0
- package/template/.agents/skills/design/impeccable/scripts/modern-screenshot.umd.js +14 -0
- package/template/.agents/skills/design/impeccable/scripts/palette.mjs +633 -0
- package/template/.agents/skills/design/impeccable/scripts/pin.mjs +214 -0
- package/template/.agents/skills/design/shadcn/SKILL.md +242 -0
- package/template/.agents/skills/design/shadcn/agents/openai.yml +5 -0
- package/template/.agents/skills/design/shadcn/assets/shadcn-small.png +0 -0
- package/template/.agents/skills/design/shadcn/assets/shadcn.png +0 -0
- package/template/.agents/skills/design/shadcn/cli.md +257 -0
- package/template/.agents/skills/design/shadcn/customization.md +202 -0
- package/template/.agents/skills/design/shadcn/evals/evals.json +47 -0
- package/template/.agents/skills/design/shadcn/mcp.md +94 -0
- package/template/.agents/skills/design/shadcn/rules/base-vs-radix.md +306 -0
- package/template/.agents/skills/design/shadcn/rules/composition.md +195 -0
- package/template/.agents/skills/design/shadcn/rules/forms.md +192 -0
- package/template/.agents/skills/design/shadcn/rules/icons.md +101 -0
- package/template/.agents/skills/design/shadcn/rules/styling.md +162 -0
- package/template/.agents/skills/find-skills/SKILL.md +142 -0
- package/template/.agents/skills/integrations/langfuse/SKILL.md +142 -0
- package/template/.agents/skills/integrations/langfuse/references/cli.md +52 -0
- package/template/.agents/skills/integrations/langfuse/references/error-analysis.md +100 -0
- package/template/.agents/skills/integrations/langfuse/references/instrumentation.md +134 -0
- package/template/.agents/skills/integrations/langfuse/references/judge-calibration.md +288 -0
- package/template/.agents/skills/integrations/langfuse/references/prompt-migration.md +234 -0
- package/template/.agents/skills/integrations/langfuse/references/sdk-upgrade.md +175 -0
- package/template/.agents/skills/integrations/langfuse/references/skill-feedback.md +52 -0
- package/template/.agents/skills/integrations/langfuse/references/user-feedback.md +88 -0
- package/template/.agents/skills/integrations/posthog/SKILL.md +102 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-alerts.md +63 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-assigning-issues.md +77 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-fingerprints.md +57 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-monitoring.md +140 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-nextjs.md +490 -0
- package/template/.agents/skills/integrations/posthog/references/error-tracking-source-maps.md +45 -0
- package/template/.agents/skills/integrations/posthog/references/feature-flags-best-practices.md +139 -0
- package/template/.agents/skills/integrations/posthog/references/feature-flags-react.md +302 -0
- package/template/.agents/skills/integrations/posthog/references/identify-users.md +202 -0
- package/template/.agents/skills/integrations/posthog/references/integration-example.md +706 -0
- package/template/.agents/skills/integrations/posthog/references/integration-nextjs.md +385 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-1-begin.md +43 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-2-edit.md +37 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-3-revise.md +22 -0
- package/template/.agents/skills/integrations/posthog/references/integration-step-4-conclude.md +38 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-anthropic.md +200 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-basics.md +62 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-costs.md +197 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-manual-capture.md +397 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-traces.md +98 -0
- package/template/.agents/skills/integrations/posthog/references/llm-analytics-vercel-ai.md +120 -0
- package/template/.agents/skills/repo/repo-ci/SKILL.md +265 -0
- package/template/.agents/skills/repo/repo-init-next-js/SKILL.md +129 -0
- package/template/.agents/skills/repo/repo-init-next-js/references/file-contents.md +800 -0
- package/template/.agents/skills/repo/repo-init-next-js/scripts/setup.sh +47 -0
- package/template/.agents/skills/repo/repo-init-node/SKILL.md +196 -0
- package/template/.agents/skills/skill-creator/LICENSE.txt +202 -0
- package/template/.agents/skills/skill-creator/SKILL.md +485 -0
- package/template/.agents/skills/skill-creator/agents/analyzer.md +274 -0
- package/template/.agents/skills/skill-creator/agents/comparator.md +202 -0
- package/template/.agents/skills/skill-creator/agents/grader.md +223 -0
- package/template/.agents/skills/skill-creator/assets/eval_review.html +146 -0
- package/template/.agents/skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/template/.agents/skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/template/.agents/skills/skill-creator/references/schemas.md +430 -0
- package/template/.agents/skills/skill-creator/scripts/__init__.py +0 -0
- package/template/.agents/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/template/.agents/skills/skill-creator/scripts/generate_report.py +326 -0
- package/template/.agents/skills/skill-creator/scripts/improve_description.py +247 -0
- package/template/.agents/skills/skill-creator/scripts/package_skill.py +136 -0
- package/template/.agents/skills/skill-creator/scripts/quick_validate.py +103 -0
- package/template/.agents/skills/skill-creator/scripts/run_eval.py +310 -0
- package/template/.agents/skills/skill-creator/scripts/run_loop.py +328 -0
- package/template/.agents/skills/skill-creator/scripts/utils.py +47 -0
- package/template/.agents/upstreams.json +80 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
# Next.js error tracking installation - Docs
|
|
2
|
+
|
|
3
|
+
1. 1
|
|
4
|
+
|
|
5
|
+
## Install the package
|
|
6
|
+
|
|
7
|
+
Required
|
|
8
|
+
|
|
9
|
+
Install the PostHog JavaScript library using your package manager:
|
|
10
|
+
|
|
11
|
+
PostHog AI
|
|
12
|
+
|
|
13
|
+
### npm
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install posthog-js
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### yarn
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
yarn add posthog-js
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### pnpm
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
pnpm add posthog-js
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
2. 2
|
|
32
|
+
|
|
33
|
+
## Add environment variables
|
|
34
|
+
|
|
35
|
+
Required
|
|
36
|
+
|
|
37
|
+
Add your PostHog project token and host to your `.env.local` file and to your hosting provider (e.g. Vercel, Netlify). These values need to start with `NEXT_PUBLIC_` to be accessible on the client-side.
|
|
38
|
+
|
|
39
|
+
.env.local
|
|
40
|
+
|
|
41
|
+
PostHog AI
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN=<ph_project_token>
|
|
45
|
+
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
3. 3
|
|
49
|
+
|
|
50
|
+
## Initialize PostHog
|
|
51
|
+
|
|
52
|
+
Required
|
|
53
|
+
|
|
54
|
+
Choose the integration method based on your Next.js version and router type.
|
|
55
|
+
|
|
56
|
+
## Next.js 15.3+
|
|
57
|
+
|
|
58
|
+
If you're using Next.js 15.3+, you can use `instrumentation-client.ts` for a lightweight, fast integration:
|
|
59
|
+
|
|
60
|
+
instrumentation-client.ts
|
|
61
|
+
|
|
62
|
+
PostHog AI
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
import posthog from 'posthog-js'
|
|
66
|
+
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN!, {
|
|
67
|
+
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
68
|
+
defaults: '2026-01-30'
|
|
69
|
+
})
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## App router
|
|
73
|
+
|
|
74
|
+
For the App router, create a `providers.tsx` file in your `app` folder. The `posthog-js` library needs to be initialized on the client-side using the `'use client'` directive:
|
|
75
|
+
|
|
76
|
+
app/providers.tsx
|
|
77
|
+
|
|
78
|
+
PostHog AI
|
|
79
|
+
|
|
80
|
+
```typescript
|
|
81
|
+
'use client'
|
|
82
|
+
import { usePathname, useSearchParams } from "next/navigation"
|
|
83
|
+
import { useEffect } from "react"
|
|
84
|
+
import posthog from 'posthog-js'
|
|
85
|
+
import { PostHogProvider as PHProvider } from 'posthog-js/react'
|
|
86
|
+
export function PostHogProvider({ children }: { children: React.ReactNode }) {
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN as string, {
|
|
89
|
+
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
90
|
+
defaults: '2026-01-30'
|
|
91
|
+
})
|
|
92
|
+
}, [])
|
|
93
|
+
return (
|
|
94
|
+
<PHProvider client={posthog}>
|
|
95
|
+
{children}
|
|
96
|
+
</PHProvider>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Then import the `PostHogProvider` component in your `app/layout.tsx` and wrap your app with it:
|
|
102
|
+
|
|
103
|
+
app/layout.tsx
|
|
104
|
+
|
|
105
|
+
PostHog AI
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
import './globals.css'
|
|
109
|
+
import { PostHogProvider } from './providers'
|
|
110
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
111
|
+
return (
|
|
112
|
+
<html lang="en">
|
|
113
|
+
<body>
|
|
114
|
+
<PostHogProvider>
|
|
115
|
+
{children}
|
|
116
|
+
</PostHogProvider>
|
|
117
|
+
</body>
|
|
118
|
+
</html>
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Pages router
|
|
124
|
+
|
|
125
|
+
For the Pages router, integrate PostHog at the root of your app in `pages/_app.tsx`:
|
|
126
|
+
|
|
127
|
+
pages/\_app.tsx
|
|
128
|
+
|
|
129
|
+
PostHog AI
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
import { useEffect } from 'react'
|
|
133
|
+
import { Router } from 'next/router'
|
|
134
|
+
import posthog from 'posthog-js'
|
|
135
|
+
import { PostHogProvider } from 'posthog-js/react'
|
|
136
|
+
import type { AppProps } from 'next/app'
|
|
137
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
138
|
+
useEffect(() => {
|
|
139
|
+
posthog.init(process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN as string, {
|
|
140
|
+
api_host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
141
|
+
defaults: '2026-01-30',
|
|
142
|
+
loaded: (posthog) => {
|
|
143
|
+
if (process.env.NODE_ENV === 'development') posthog.debug()
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
}, [])
|
|
147
|
+
return (
|
|
148
|
+
<PostHogProvider client={posthog}>
|
|
149
|
+
<Component {...pageProps} />
|
|
150
|
+
</PostHogProvider>
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
**Defaults option**
|
|
156
|
+
|
|
157
|
+
The `defaults` option automatically configures PostHog with recommended settings for new projects. See [SDK defaults](/docs/libraries/js.md#sdk-defaults) for details.
|
|
158
|
+
|
|
159
|
+
4. 4
|
|
160
|
+
|
|
161
|
+
## Accessing PostHog on the client
|
|
162
|
+
|
|
163
|
+
Recommended
|
|
164
|
+
|
|
165
|
+
## Next.js 15.3+
|
|
166
|
+
|
|
167
|
+
Once initialized in `instrumentation-client.ts`, import `posthog` from `posthog-js` anywhere and call the methods you need:
|
|
168
|
+
|
|
169
|
+
app/checkout/page.tsx
|
|
170
|
+
|
|
171
|
+
PostHog AI
|
|
172
|
+
|
|
173
|
+
```typescript
|
|
174
|
+
'use client'
|
|
175
|
+
import posthog from 'posthog-js'
|
|
176
|
+
export default function CheckoutPage() {
|
|
177
|
+
function handlePurchase() {
|
|
178
|
+
posthog.capture('purchase_completed', { amount: 99 })
|
|
179
|
+
}
|
|
180
|
+
return <button onClick={handlePurchase}>Complete purchase</button>
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## App/Pages router
|
|
185
|
+
|
|
186
|
+
Use the `usePostHog` hook to access PostHog in client components:
|
|
187
|
+
|
|
188
|
+
app/checkout/page.tsx
|
|
189
|
+
|
|
190
|
+
PostHog AI
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
'use client'
|
|
194
|
+
import { usePostHog } from 'posthog-js/react'
|
|
195
|
+
export default function CheckoutPage() {
|
|
196
|
+
const posthog = usePostHog()
|
|
197
|
+
function handlePurchase() {
|
|
198
|
+
posthog.capture('purchase_completed', { amount: 99 })
|
|
199
|
+
}
|
|
200
|
+
return <button onClick={handlePurchase}>Complete purchase</button>
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
5. 5
|
|
205
|
+
|
|
206
|
+
## Capture client-side exceptions
|
|
207
|
+
|
|
208
|
+
Required
|
|
209
|
+
|
|
210
|
+
PostHog can automatically capture unhandled exceptions in your Next.js app using the JavaScript Web SDK.
|
|
211
|
+
|
|
212
|
+
You can enable exception autocapture for the JavaScript Web SDK in the **Error tracking** section of [your project settings](https://us.posthog.com/settings/project-error-tracking#exception-autocapture).
|
|
213
|
+
|
|
214
|
+
It is also possible to manually capture exceptions using the `captureException` method:
|
|
215
|
+
|
|
216
|
+
JavaScript
|
|
217
|
+
|
|
218
|
+
PostHog AI
|
|
219
|
+
|
|
220
|
+
```javascript
|
|
221
|
+
posthog.captureException(error, additionalProperties)
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Manual capture is very useful if you already use error boundaries to handle errors in your app:
|
|
225
|
+
|
|
226
|
+
## App router
|
|
227
|
+
|
|
228
|
+
Next.js uses [error boundaries](https://nextjs.org/docs/app/building-your-application/routing/error-handling#using-error-boundaries) to handle uncaught exceptions by rendering a fallback UI instead of the crashing components. To set one up, create a `error.tsx` file in any of your route directories. This triggers when there is an error rendering your component and should look like this:
|
|
229
|
+
|
|
230
|
+
error.tsx
|
|
231
|
+
|
|
232
|
+
PostHog AI
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
"use client"
|
|
236
|
+
import posthog from "posthog-js"
|
|
237
|
+
import { useEffect } from "react"
|
|
238
|
+
export default function Error({
|
|
239
|
+
error,
|
|
240
|
+
reset,
|
|
241
|
+
}: {
|
|
242
|
+
error: Error & { digest?: string }
|
|
243
|
+
reset: () => void
|
|
244
|
+
}) {
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
posthog.captureException(error)
|
|
247
|
+
}, [error])
|
|
248
|
+
return (
|
|
249
|
+
...
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
You can also create a [Global Error component](https://nextjs.org/docs/app/building-your-application/routing/error-handling#handling-global-errors) in your root layout to capture unhandled exceptions in your root layout.
|
|
255
|
+
|
|
256
|
+
app/global-error.tsx
|
|
257
|
+
|
|
258
|
+
PostHog AI
|
|
259
|
+
|
|
260
|
+
```typescript
|
|
261
|
+
'use client'
|
|
262
|
+
import posthog from "posthog-js"
|
|
263
|
+
import NextError from "next/error"
|
|
264
|
+
import { useEffect } from "react"
|
|
265
|
+
export default function GlobalError({
|
|
266
|
+
error,
|
|
267
|
+
reset,
|
|
268
|
+
}: {
|
|
269
|
+
error: Error & { digest?: string }
|
|
270
|
+
reset: () => void
|
|
271
|
+
}) {
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
posthog.captureException(error)
|
|
274
|
+
}, [error])
|
|
275
|
+
return (
|
|
276
|
+
// global-error must include html and body tags
|
|
277
|
+
<html>
|
|
278
|
+
<body>
|
|
279
|
+
{/* `NextError` is the default Next.js error page component */}
|
|
280
|
+
<NextError statusCode={0} />
|
|
281
|
+
</body>
|
|
282
|
+
</html>
|
|
283
|
+
)
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
## Pages router
|
|
288
|
+
|
|
289
|
+
For Pages Router, you can use React's [Error Boundaries](https://react.dev/reference/react/Component#catching-rendering-errors-with-an-error-boundary) to catch JavaScript errors anywhere in the component tree. Create a custom error boundary component and report errors to PostHog in the `componentDidCatch` method:
|
|
290
|
+
|
|
291
|
+
components/ErrorBoundary.tsx
|
|
292
|
+
|
|
293
|
+
PostHog AI
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
componentDidCatch(error, errorInfo) {
|
|
297
|
+
posthog.captureException(error)
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
Then wrap your app or specific components with the error boundary:
|
|
302
|
+
|
|
303
|
+
pages/\_app.tsx
|
|
304
|
+
|
|
305
|
+
PostHog AI
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import type { AppProps } from 'next/app'
|
|
309
|
+
import ErrorBoundary from '../components/ErrorBoundary'
|
|
310
|
+
export default function App({ Component, pageProps }: AppProps) {
|
|
311
|
+
return (
|
|
312
|
+
<ErrorBoundary>
|
|
313
|
+
<Component {...pageProps} />
|
|
314
|
+
</ErrorBoundary>
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
6. 6
|
|
320
|
+
|
|
321
|
+
## Installing PostHog SDK for server-side
|
|
322
|
+
|
|
323
|
+
Required
|
|
324
|
+
|
|
325
|
+
Next.js enables you to both server-side render pages and add server-side functionality. To integrate PostHog into your Next.js app on the server-side, you can use the [Node SDK](/docs/libraries/node.md).
|
|
326
|
+
|
|
327
|
+
First, install the `posthog-node` library:
|
|
328
|
+
|
|
329
|
+
PostHog AI
|
|
330
|
+
|
|
331
|
+
### npm
|
|
332
|
+
|
|
333
|
+
```bash
|
|
334
|
+
npm install posthog-node --save
|
|
335
|
+
```
|
|
336
|
+
|
|
337
|
+
### yarn
|
|
338
|
+
|
|
339
|
+
```bash
|
|
340
|
+
yarn add posthog-node
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### pnpm
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
pnpm add posthog-node
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### bun
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
bun add posthog-node
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
For the backend, we can create a `lib/posthog-server.js` file. In it, initialize PostHog from `posthog-node` as a singleton with your project token and host from [your project settings](https://app.posthog.com/settings/project).
|
|
356
|
+
|
|
357
|
+
This looks like this:
|
|
358
|
+
|
|
359
|
+
lib/posthog-server.js
|
|
360
|
+
|
|
361
|
+
PostHog AI
|
|
362
|
+
|
|
363
|
+
```javascript
|
|
364
|
+
import { PostHog } from 'posthog-node'
|
|
365
|
+
let posthogInstance = null
|
|
366
|
+
export function getPostHogServer() {
|
|
367
|
+
if (!posthogInstance) {
|
|
368
|
+
posthogInstance = new PostHog(
|
|
369
|
+
process.env.NEXT_PUBLIC_POSTHOG_PROJECT_TOKEN,
|
|
370
|
+
{
|
|
371
|
+
host: process.env.NEXT_PUBLIC_POSTHOG_HOST,
|
|
372
|
+
flushAt: 1,
|
|
373
|
+
flushInterval: 0,
|
|
374
|
+
}
|
|
375
|
+
)
|
|
376
|
+
}
|
|
377
|
+
return posthogInstance
|
|
378
|
+
}
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
You can now use the `getPostHogServer` function to capture exceptions in server-side code.
|
|
382
|
+
|
|
383
|
+
JavaScript
|
|
384
|
+
|
|
385
|
+
PostHog AI
|
|
386
|
+
|
|
387
|
+
```javascript
|
|
388
|
+
const posthog = getPostHogServer()
|
|
389
|
+
try {
|
|
390
|
+
throw new Error("This is a test exception for error tracking")
|
|
391
|
+
} catch (error) {
|
|
392
|
+
posthog.captureException(error, {
|
|
393
|
+
source: 'test',
|
|
394
|
+
user_id: 'test-user-123',
|
|
395
|
+
})
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
7. ## Verify server-side exceptions
|
|
400
|
+
|
|
401
|
+
Recommended
|
|
402
|
+
|
|
403
|
+
You should also see events and exceptions in PostHog coming from your server-side code in the activity feed.
|
|
404
|
+
|
|
405
|
+
[Check for server events in PostHog](https://app.posthog.com/activity/explore)
|
|
406
|
+
|
|
407
|
+
8. 7
|
|
408
|
+
|
|
409
|
+
## Capturing server-side exceptions
|
|
410
|
+
|
|
411
|
+
Required
|
|
412
|
+
|
|
413
|
+
To capture errors that occur in your server-side code, you can set up an [`instrumentation.ts`](https://nextjs.org/docs/app/building-your-application/optimizing/instrumentation) file at the root of your project. This provides a `onRequestError` hook that you can use to capture errors.
|
|
414
|
+
|
|
415
|
+
Importantly, you need to:
|
|
416
|
+
|
|
417
|
+
1. Set up a `posthog-node` client in your server-side code. See our doc on [setting up Next.js server-side analytics](/docs/libraries/next-js.md#server-side-analytics.md) for more.
|
|
418
|
+
2. Check the request is running in the `nodejs` runtime to ensure PostHog works. You can call `posthog.debug()` to get verbose logging.
|
|
419
|
+
3. Get the `distinct_id` from the cookie to connect the error to a specific user.
|
|
420
|
+
|
|
421
|
+
This looks like this:
|
|
422
|
+
|
|
423
|
+
JavaScript
|
|
424
|
+
|
|
425
|
+
PostHog AI
|
|
426
|
+
|
|
427
|
+
```javascript
|
|
428
|
+
// instrumentation.js
|
|
429
|
+
export function register() {
|
|
430
|
+
// No-op for initialization
|
|
431
|
+
}
|
|
432
|
+
export const onRequestError = async (err, request, context) => {
|
|
433
|
+
if (process.env.NEXT_RUNTIME === 'nodejs') {
|
|
434
|
+
const { getPostHogServer } = require('./lib/posthog-server')
|
|
435
|
+
const posthog = getPostHogServer()
|
|
436
|
+
let distinctId = null
|
|
437
|
+
if (request.headers.cookie) {
|
|
438
|
+
// Normalize multiple cookie arrays to string
|
|
439
|
+
const cookieString = Array.isArray(request.headers.cookie)
|
|
440
|
+
? request.headers.cookie.join('; ')
|
|
441
|
+
: request.headers.cookie
|
|
442
|
+
const postHogCookieMatch = cookieString.match(/ph_phc_.*?_posthog=([^;]+)/)
|
|
443
|
+
if (postHogCookieMatch && postHogCookieMatch[1]) {
|
|
444
|
+
try {
|
|
445
|
+
const decodedCookie = decodeURIComponent(postHogCookieMatch[1])
|
|
446
|
+
const postHogData = JSON.parse(decodedCookie)
|
|
447
|
+
distinctId = postHogData.distinct_id
|
|
448
|
+
} catch (e) {
|
|
449
|
+
console.error('Error parsing PostHog cookie:', e)
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
await posthog.captureException(err, distinctId || undefined)
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
You can find a full example of both this and client-side error tracking in our [Next.js error monitoring tutorial](/tutorials/nextjs-error-monitoring.md).
|
|
459
|
+
|
|
460
|
+
9. ## Verify error tracking
|
|
461
|
+
|
|
462
|
+
Recommended
|
|
463
|
+
|
|
464
|
+
*Confirm events are being sent to PostHog*
|
|
465
|
+
|
|
466
|
+
Before proceeding, let's make sure exception events are being captured and sent to PostHog. You should see events appear in the activity feed.
|
|
467
|
+
|
|
468
|
+

|
|
469
|
+
|
|
470
|
+
[Check for exceptions in PostHog](https://app.posthog.com/activity/explore)
|
|
471
|
+
|
|
472
|
+
10. 8
|
|
473
|
+
|
|
474
|
+
## Upload source maps
|
|
475
|
+
|
|
476
|
+
Required
|
|
477
|
+
|
|
478
|
+
Great, you're capturing exceptions! If you serve minified bundles, the next step is to upload source maps to generate accurate stack traces.
|
|
479
|
+
|
|
480
|
+
Let's continue to the next section.
|
|
481
|
+
|
|
482
|
+
[Upload source maps](/docs/error-tracking/upload-source-maps/nextjs.md)
|
|
483
|
+
|
|
484
|
+
### Community questions
|
|
485
|
+
|
|
486
|
+
Ask a question
|
|
487
|
+
|
|
488
|
+
### Was this page useful?
|
|
489
|
+
|
|
490
|
+
HelpfulCould be better
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Upload source maps - Docs
|
|
2
|
+
|
|
3
|
+
If you serve compiled or minified code, PostHog requires source maps to generate accurate stack traces.
|
|
4
|
+
|
|
5
|
+
If your source maps are not publicly hosted, you will need to upload them during your build process to see unminified code in your stack traces.
|
|
6
|
+
|
|
7
|
+
Choose your platform to view specific instructions.
|
|
8
|
+
|
|
9
|
+
- [Web](/docs/error-tracking/upload-source-maps/web.md)
|
|
10
|
+
|
|
11
|
+
- [Next.js](/docs/error-tracking/upload-source-maps/nextjs.md)
|
|
12
|
+
|
|
13
|
+
- [Node.js](/docs/error-tracking/upload-source-maps/node.md)
|
|
14
|
+
|
|
15
|
+
- [React](/docs/error-tracking/upload-source-maps/react.md)
|
|
16
|
+
|
|
17
|
+
- [Angular](/docs/error-tracking/upload-source-maps/angular.md)
|
|
18
|
+
|
|
19
|
+
- [Nuxt](/docs/error-tracking/upload-source-maps/nuxt.md)
|
|
20
|
+
|
|
21
|
+
- [React Native](/docs/error-tracking/upload-source-maps/react-native.md)
|
|
22
|
+
|
|
23
|
+
- [Android](/docs/error-tracking/upload-mappings/android.md)
|
|
24
|
+
|
|
25
|
+
- [Flutter](/docs/error-tracking/upload-source-maps/flutter.md)
|
|
26
|
+
|
|
27
|
+
- [iOS](/docs/error-tracking/upload-source-maps/ios.md)
|
|
28
|
+
|
|
29
|
+
- [Rollup](/docs/error-tracking/upload-source-maps/rollup.md)
|
|
30
|
+
|
|
31
|
+
- [Webpack](/docs/error-tracking/upload-source-maps/webpack.md)
|
|
32
|
+
|
|
33
|
+
- [Vite](/docs/error-tracking/upload-source-maps/vite.md)
|
|
34
|
+
|
|
35
|
+
- [CLI](/docs/error-tracking/upload-source-maps/cli.md)
|
|
36
|
+
|
|
37
|
+
- [GitHub Action](/docs/error-tracking/upload-source-maps/github-actions.md)
|
|
38
|
+
|
|
39
|
+
### Community questions
|
|
40
|
+
|
|
41
|
+
Ask a question
|
|
42
|
+
|
|
43
|
+
### Was this page useful?
|
|
44
|
+
|
|
45
|
+
HelpfulCould be better
|
package/template/.agents/skills/integrations/posthog/references/feature-flags-best-practices.md
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Feature flag best practices - Docs
|
|
2
|
+
|
|
3
|
+
## 1\. Use a reverse proxy
|
|
4
|
+
|
|
5
|
+
Ad blockers have the potential to disable your feature flags, which can lead to bad experiences, such as users seeing the wrong version of your app, or missing a new feature rollout.
|
|
6
|
+
|
|
7
|
+
To avoid this, deploy a reverse proxy, which enables you to make requests and send events to PostHog Cloud using your own domain.
|
|
8
|
+
|
|
9
|
+
This means that requests are less likely to be intercepted by tracking blockers, and your feature flags are more likely to work as intended. You'll also capture more usage data.
|
|
10
|
+
|
|
11
|
+
PostHog offers a free [managed reverse proxy](/docs/advanced/proxy/managed-reverse-proxy.md), or you can run your own. See our [reverse proxy docs](/docs/advanced/proxy.md) for more.
|
|
12
|
+
|
|
13
|
+
## 2\. Call your flag in as few places as possible
|
|
14
|
+
|
|
15
|
+
It should be easy to understand how feature flags affect your code. The more locations a flag is in, the more likely it is to cause problems. For example, a developer could remove the flag in one place but forget to remove it in another.
|
|
16
|
+
|
|
17
|
+
If you expect to use a feature flag in multiple places, it's a good idea to wrap the flag in a single function or method. For example:
|
|
18
|
+
|
|
19
|
+
JavaScript
|
|
20
|
+
|
|
21
|
+
PostHog AI
|
|
22
|
+
|
|
23
|
+
```javascript
|
|
24
|
+
function useBetaFeature() {
|
|
25
|
+
return posthog.isFeatureEnabled('beta-feature')
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## 3\. Targeting
|
|
30
|
+
|
|
31
|
+
PostHog evaluates flags based on the user's distinct ID, having different IDs can cause the same user to receive different flag values across different sessions, devices, and platforms. By [identifying](/docs/getting-started/identify-users.md) them, you can ensure consistent flag values.
|
|
32
|
+
|
|
33
|
+
The same applies to identifying [groups](/docs/product-analytics/group-analytics.md) for group-level flags.
|
|
34
|
+
|
|
35
|
+
For flags targeting anonymous users, such as signup flows or landing page experiments, consider using [device bucketing](/docs/feature-flags/device-bucketing.md) instead. This evaluates the flag based on the device ID, ensuring a consistent experience on the device even after the user logs in.
|
|
36
|
+
|
|
37
|
+
## 4\. Use server-side local evaluation for faster flags
|
|
38
|
+
|
|
39
|
+
Evaluating feature flags requires making a request to PostHog for each flag. However, you can improve performance by evaluating flags locally. Instead of making a request for each flag, PostHog will periodically request and store feature flag definitions locally, enabling you to evaluate flags without making additional requests.
|
|
40
|
+
|
|
41
|
+
Evaluate flags locally when possible, since this enables you to resolve flags faster and with fewer API calls. See our docs on [local evaluation](/docs/feature-flags/local-evaluation.md) for more details.
|
|
42
|
+
|
|
43
|
+
## 5\. Bootstrap flags on the client to make them available immediately
|
|
44
|
+
|
|
45
|
+
Since there is a delay between initializing PostHog and fetching feature flags, feature flags are not always available immediately. This makes them unusable if you want to do something like redirecting a user to a different page based on a feature flag.
|
|
46
|
+
|
|
47
|
+
To have your feature flags available immediately, you can initialize PostHog with precomputed values until it has had a chance to fetch them. This is called bootstrapping.
|
|
48
|
+
|
|
49
|
+
See our docs on [bootstrapping](/docs/feature-flags/bootstrapping.md) for more details on how to do this.
|
|
50
|
+
|
|
51
|
+
## 6\. Naming tips
|
|
52
|
+
|
|
53
|
+
Good naming conventions for your flags makes them easier to understand and maintain. Below are tips for naming your flags:
|
|
54
|
+
|
|
55
|
+
- **Use descriptive names.** For example, `is_v2_billing_dashboard_enabled` is much clearer than `is_dashboard_enabled`.
|
|
56
|
+
|
|
57
|
+
- **Use name "types".** This helps organize them and makes their purpose clear. Types might include experiments, releases, and permissions. For example, instead of `new-billing`, they would be `new-billing-experiment` or `new-billing-release`.
|
|
58
|
+
|
|
59
|
+
- **Name flags to reflect their return type.** For example, `is_premium_user` for a boolean, `enabled_integrations` for an array, or `selected_theme` for a single string.
|
|
60
|
+
|
|
61
|
+
- **Use positive language for boolean flags.** For example, `is_premium_user` instead of `is_not_premium_user`. This helps avoid double negatives when checking the flag value (e.g. `if !is_not_premium_user` is confusing).
|
|
62
|
+
|
|
63
|
+
## 7\. Roll out progressively
|
|
64
|
+
|
|
65
|
+
When testing a change behind a feature flag, it is best to roll it out to a small group of users and increase that group over time. This is also known as a [phased rollout](/tutorials/phased-rollout.md). It enables you to identify any potential issues ahead of the full release.
|
|
66
|
+
|
|
67
|
+
For example, at PostHog we often roll out the flag to just the responsible developer. It then moves on to the internal team, then beta users, and finally into a full rollout. This enables us to [test in production](/product-engineers/testing-in-production.md), get multiple rounds of feedback, identify issues, and polish the feature before the full release.
|
|
68
|
+
|
|
69
|
+
## 8\. Clean up after yourself
|
|
70
|
+
|
|
71
|
+
Leaving flags in your code for too long can confuse future developers and create technical debt, especially if it's already rolled out and integrated. Be sure to remove stale flags once they are completely rolled out or no longer needed.
|
|
72
|
+
|
|
73
|
+
When you have many flags to clean up, use [bulk delete](/docs/feature-flags/creating-feature-flags.md#deleting-feature-flags-in-bulk) to select and delete multiple flags at once. Select flags using checkboxes (shift-click to select a range), or filter by name or status and use "select all matching" to select all flags that match your criteria. PostHog validates that flags aren't used by experiments, early access features, or other dependent flags before deletion.
|
|
74
|
+
|
|
75
|
+
## 9\. Fallback to working code
|
|
76
|
+
|
|
77
|
+
It's possible that a feature flag will return an [unexpected value](/docs/feature-flags/common-questions.md#my-feature-flag-called-events-show-none-empty-string-or-false-instead-of-my-variant-names). For example, if the flag is disabled or failed to load due to a network error.
|
|
78
|
+
|
|
79
|
+
In this case, its best to check that the feature flag returns a valid expected value before using it. If it isn't, fallback to working code.
|
|
80
|
+
|
|
81
|
+
## 10\. Use dependencies for complex rollouts
|
|
82
|
+
|
|
83
|
+
For sophisticated feature rollouts, consider using [feature flag dependencies](/docs/feature-flags/dependencies.md) where one flag's activation depends on another flag's state. This is useful for:
|
|
84
|
+
|
|
85
|
+
- Enabling complex features only after foundational components are active
|
|
86
|
+
- Running experiments only on users with specific features enabled
|
|
87
|
+
- Creating safety mechanisms where critical flags must be enabled first
|
|
88
|
+
|
|
89
|
+
When using dependencies, keep the dependency chains simple and avoid circular dependencies.
|
|
90
|
+
|
|
91
|
+
## 11\. Reducing your bill
|
|
92
|
+
|
|
93
|
+
We aim to be significantly cheaper than our competitors. To help you reduce your bill, we've created a [dedicated guide](/docs/feature-flags/cutting-costs.md) to estimating and reducing your feature flag costs.
|
|
94
|
+
|
|
95
|
+
## 12\. Consistent flag evaluations across frontend and backend
|
|
96
|
+
|
|
97
|
+
For feature flags with flag persistence enabled and used across both your frontend and backend, you will need to do one of the following to ensure the evaluation result of the flag is consistent between both environments:
|
|
98
|
+
|
|
99
|
+
1. Identify the user on the frontend and use the same identified distinct ID when evaluating the flag on the backend.
|
|
100
|
+
|
|
101
|
+
JavaScript
|
|
102
|
+
|
|
103
|
+
PostHog AI
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
// Frontend: Identify the user
|
|
107
|
+
posthog.identify('user123')
|
|
108
|
+
// Backend: Use the same distinct ID
|
|
109
|
+
const flagValue = await posthog.getFeatureFlag('my-flag', 'user123')
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
2. If you are unable to call identify on the frontend, and only have access to the anonymous distinct ID when evaluating the flag on the backend, you can include the anonymous distinct ID as a person property override in the `getFeatureFlag` call.
|
|
113
|
+
|
|
114
|
+
JavaScript
|
|
115
|
+
|
|
116
|
+
PostHog AI
|
|
117
|
+
|
|
118
|
+
```javascript
|
|
119
|
+
// Frontend: Get the anonymous ID (before identify is called)
|
|
120
|
+
const anonId = posthog.getAnonymousId()
|
|
121
|
+
// Backend: Pass the anonymous ID as a person property override
|
|
122
|
+
const flagValue = await posthog.getFeatureFlag(
|
|
123
|
+
'my-flag',
|
|
124
|
+
'user123', // identified distinct ID
|
|
125
|
+
{
|
|
126
|
+
personProperties: {
|
|
127
|
+
$anon_distinct_id: anonId
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### Community questions
|
|
134
|
+
|
|
135
|
+
Ask a question
|
|
136
|
+
|
|
137
|
+
### Was this page useful?
|
|
138
|
+
|
|
139
|
+
HelpfulCould be better
|