@thierrynakoa/fire-flow 12.2.1 → 13.0.1
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/CREDITS.md +25 -0
- package/DOMINION-FLOW-OVERVIEW.md +182 -38
- package/README.md +399 -455
- package/TROUBLESHOOTING.md +264 -264
- package/agents/fire-debugger.md +54 -0
- package/agents/fire-executor.md +1610 -1033
- package/agents/fire-fact-checker.md +1 -1
- package/agents/fire-planner.md +85 -17
- package/agents/fire-project-researcher.md +1 -1
- package/agents/fire-researcher.md +4 -22
- package/agents/{fire-phoenix-analyst.md → fire-resurrection-analyst.md} +394 -394
- package/agents/fire-reviewer.md +552 -499
- package/agents/fire-verifier.md +114 -19
- package/bin/cli.js +18 -101
- package/commands/fire-0-orient.md +2 -2
- package/commands/fire-1a-new.md +50 -15
- package/commands/fire-1c-setup.md +33 -5
- package/commands/fire-1d-discuss.md +87 -1
- package/commands/fire-2-plan.md +556 -527
- package/commands/fire-3-execute.md +2046 -1356
- package/commands/fire-4-verify.md +975 -906
- package/commands/fire-5-handoff.md +46 -5
- package/commands/fire-6-resume.md +2 -31
- package/commands/fire-add-new-skill.md +138 -19
- package/commands/fire-autonomous.md +14 -2
- package/commands/fire-complete-milestone.md +1 -1
- package/commands/fire-cost.md +179 -183
- package/commands/fire-debug.md +1 -6
- package/commands/fire-loop-resume.md +2 -2
- package/commands/fire-loop-stop.md +1 -1
- package/commands/fire-loop.md +2 -15
- package/commands/fire-map-codebase.md +1 -1
- package/commands/fire-migrate-database.md +548 -0
- package/commands/fire-new-milestone.md +1 -1
- package/commands/fire-reflect.md +1 -2
- package/commands/fire-research.md +142 -21
- package/commands/{fire-phoenix.md → fire-resurrect.md} +859 -603
- package/commands/fire-scaffold.md +297 -0
- package/commands/fire-search.md +1 -2
- package/commands/fire-security-scan.md +483 -484
- package/commands/fire-setup.md +359 -0
- package/commands/fire-skill.md +770 -0
- package/commands/fire-skills-diff.md +506 -506
- package/commands/fire-skills-history.md +388 -388
- package/commands/fire-skills-rollback.md +7 -7
- package/commands/fire-skills-sync.md +470 -470
- package/commands/fire-test.md +5 -5
- package/commands/fire-todos.md +1 -1
- package/commands/fire-update.md +5 -5
- package/commands/fire-validate-skills.md +282 -0
- package/commands/fire-vuln-scan.md +492 -493
- package/hooks/run-hook.sh +8 -8
- package/hooks/run-session-end.sh +7 -7
- package/hooks/session-end.sh +90 -90
- package/hooks/session-start.sh +1 -1
- package/package.json +4 -24
- package/plugin.json +7 -7
- package/references/autonomy-levels.md +235 -0
- package/references/behavioral-directives.md +95 -3
- package/references/blocker-tracking.md +1 -1
- package/references/circuit-breaker.md +93 -2
- package/references/context-engineering.md +227 -9
- package/references/honesty-protocols.md +70 -1
- package/references/issue-to-pr-pipeline.md +149 -150
- package/references/metrics-and-trends.md +1 -2
- package/references/research-improvements.md +4 -108
- package/references/sdlc-mapping.md +73 -0
- package/references/state-machine.md +151 -0
- package/skills-library/AVAILABLE_TOOLS_REFERENCE.md +333 -0
- package/skills-library/SKILLS-INDEX.md +57 -558
- package/skills-library/SKILLS_LIBRARY_INDEX.md +532 -0
- package/skills-library/_general/api-patterns/api-field-name-mismatch.md +107 -0
- package/skills-library/_general/api-patterns/streaming-command-timeout.md +122 -0
- package/skills-library/_general/api-patterns/streaming-proxy-cors-bypass.md +102 -0
- package/skills-library/_general/automation/settings-gui-generator.md +172 -0
- package/skills-library/_general/database-solutions/data-type-mapping-reference.md +181 -0
- package/skills-library/_general/database-solutions/mysql-limit-offset-string-coercion.md +102 -0
- package/skills-library/_general/database-solutions/mysql-to-pg-migration.md +195 -0
- package/skills-library/_general/database-solutions/orm-schema-portability.md +193 -0
- package/skills-library/_general/database-solutions/persistent-analysis-storage.md +207 -0
- package/skills-library/_general/database-solutions/pg-to-mysql-schema-migration-methodology.md +190 -0
- package/skills-library/_general/database-solutions/sql-dialect-compatibility-matrix.md +306 -0
- package/skills-library/_general/database-solutions/sqlite-to-pg-migration.md +219 -0
- package/skills-library/_general/frontend/canvas-bubble-animation-grouping.md +270 -0
- package/skills-library/_general/frontend/color-token-migration.md +112 -0
- package/skills-library/_general/frontend/framer-motion-layoutid-grouping.md +150 -0
- package/skills-library/_general/frontend/pyqt6-settings-dialog.md +191 -0
- package/skills-library/_general/frontend/react-flow-animated-layout-switching.md +101 -0
- package/skills-library/_general/frontend/react-hooks-order-debugging.md +141 -0
- package/skills-library/_general/frontend/redux-localstorage-auth-desync.md +126 -0
- package/skills-library/_general/frontend/safari-csp-theme-color-debugging.md +124 -0
- package/skills-library/_general/frontend/safari-sw-cache-poisoning.md +138 -0
- package/skills-library/_general/frontend/svg-sparkline-no-charting-library.md +131 -0
- package/skills-library/_general/growth-marketing/oss-daily-growth-intelligence.md +224 -0
- package/skills-library/_general/integrations/claude-code-local-mcp-integration.md +250 -0
- package/skills-library/_general/integrations/mcp-composite-tool-orchestration.md +200 -0
- package/skills-library/_general/methodology/AGENT_SDK_STANDALONE_TOOLING.md +181 -0
- package/skills-library/_general/methodology/AGENT_TEAMS_GUIDE.md +169 -0
- package/skills-library/_general/methodology/ALAS_STATEFUL_EXECUTION.md +207 -0
- package/skills-library/_general/methodology/AUTO_REVIEWER_SUBAGENT.md +211 -0
- package/skills-library/_general/methodology/CONSISTENCY_CHECK_AMBIGUITY_GATE.md +96 -0
- package/skills-library/_general/methodology/DEAD_ENDS_SHELF.md +4 -4
- package/skills-library/_general/methodology/DISTILL_NOT_DUMP.md +108 -0
- package/skills-library/_general/methodology/EXECUTION_PROGRESS_MONITOR.md +157 -0
- package/skills-library/_general/methodology/HIERARCHICAL_REVIEW_MARS.md +122 -0
- package/skills-library/_general/methodology/MCP_INTER_AGENT_BRIDGE.md +207 -0
- package/skills-library/_general/methodology/MERMAID_WIZARD_DIAGRAMS.md +77 -0
- package/skills-library/_general/methodology/MISSING_DIMENSION_DETECTOR.md +89 -0
- package/skills-library/_general/methodology/MULTI_AGENT_COORDINATION.md +397 -0
- package/skills-library/_general/methodology/OBSERVATION_MASKING.md +100 -0
- package/skills-library/_general/methodology/PHOENIX_REBUILD_METHODOLOGY.md +82 -11
- package/skills-library/_general/methodology/REVIEW_BACKTRACK_PANEL.md +140 -0
- package/skills-library/_general/methodology/REVIEW_FIX_LOOP.md +117 -0
- package/skills-library/_general/methodology/VOTING_VERDICT_ARBITRATION.md +155 -0
- package/skills-library/_general/methodology/ZERO_FRICTION_CLI_SETUP.md +2 -2
- package/skills-library/_general/methodology/dead-code-activation.md +123 -0
- package/skills-library/_general/methodology/debug-swarm-researcher-escape-hatch.md +240 -240
- package/skills-library/_general/methodology/shell-autonomous-loop-fixplan.md +1 -1
- package/skills-library/_general/patterns-standards/GOF_DESIGN_PATTERNS_FOR_AI_AGENTS.md +5 -5
- package/skills-library/_general/patterns-standards/cascading-failure-diagnosis.md +119 -0
- package/skills-library/_general/patterns-standards/domain-specific-layout-algorithms.md +209 -0
- package/skills-library/_general/patterns-standards/python-desktop-app-architecture.md +399 -0
- package/skills-library/_general/patterns-standards/realtime-monitoring-dashboard.md +457 -0
- package/skills-library/_general/patterns-standards/togglable-processing-pipeline.md +169 -0
- package/skills-library/_general/performance/liveclock-extraction.md +112 -0
- package/skills-library/_general/performance/ref-based-canvas-animation.md +117 -0
- package/skills-library/_general/performance/use-visible-interval.md +131 -0
- package/skills-library/_general/testing/playwright-firefox-withcredentials-auth-issue.md +104 -0
- package/skills-library/_quarantine/README.md +30 -0
- package/skills-library/api-patterns/BROADCAST_SCHEDULER_SHARED_EXECUTE_FUNCTION.md +150 -0
- package/skills-library/api-patterns/ERROR_RESPONSE_STANDARDS.md +145 -0
- package/skills-library/api-patterns/EXPRESS_ROUTE_ORDERING_MIDDLEWARE_INTERCEPTION.md +326 -0
- package/skills-library/api-patterns/PAGINATION_PATTERNS.md +137 -0
- package/skills-library/api-patterns/PODCAST_PROGRESS_TRACKING_THREE_ROOT_CAUSES.md +277 -0
- package/skills-library/api-patterns/RATE_LIMITING_TOGGLE.md +155 -0
- package/skills-library/api-patterns/graphql-content-queries.md +708 -0
- package/skills-library/appointment-scheduler-design.md +423 -0
- package/skills-library/automation/AUTO_POPULATE_COMPLETE_GUIDE.md +631 -0
- package/skills-library/automation/CC_WORKFLOW_STUDIO.md +83 -0
- package/skills-library/automation/CLAUDE_CODE_SWARM_MODE.md +95 -0
- package/skills-library/automation/DAEMON_TRIGGER_FILE_IPC.md +195 -0
- package/skills-library/automation/scheduled-content-publishing.md +608 -0
- package/skills-library/awesome-workflows/Blogging-Platform-Instructions/view_commands.md +25 -0
- package/skills-library/awesome-workflows/CREDENTIAL-SECURITY-WORKFLOW.md +109 -0
- package/skills-library/awesome-workflows/DEBUGGING-WORKFLOW.md +124 -0
- package/skills-library/awesome-workflows/Design-Review-Workflow/README.md +31 -0
- package/skills-library/awesome-workflows/Design-Review-Workflow/design-principles-example.md +129 -0
- package/skills-library/awesome-workflows/Design-Review-Workflow/design-review-agent.md +107 -0
- package/skills-library/awesome-workflows/Design-Review-Workflow/design-review-claude-md-snippet.md +24 -0
- package/skills-library/awesome-workflows/Design-Review-Workflow/design-review-slash-command.md +38 -0
- package/skills-library/awesome-workflows/PARALLEL-RESEARCH-WORKFLOW.md +89 -0
- package/skills-library/awesome-workflows/PHASE-EXECUTION-WORKFLOW.md +97 -0
- package/skills-library/awesome-workflows/SESSION-HANDOFF-WORKFLOW.md +116 -0
- package/skills-library/cms-patterns/content-branch-preview.md +515 -0
- package/skills-library/cms-patterns/inline-visual-editing.md +666 -0
- package/skills-library/cms-patterns/mdx-component-content.md +649 -0
- package/skills-library/cms-patterns/media-manager-abstraction.md +827 -0
- package/skills-library/cms-patterns/schema-driven-form-generator.md +838 -0
- package/skills-library/complexity-metrics/complexity-divider.md +707 -0
- package/skills-library/complexity-metrics/work-with-complexity.md +193 -0
- package/skills-library/creative-multimedia/animation-stack-guide.md +577 -0
- package/skills-library/creative-multimedia/audio-enhancement-pipeline.md +625 -0
- package/skills-library/creative-multimedia/content-repurposing-pipeline.md +1146 -0
- package/skills-library/creative-multimedia/data-visualization-generator.md +862 -0
- package/skills-library/creative-multimedia/doc-to-podcast-pipeline.md +2184 -0
- package/skills-library/creative-multimedia/ffmpeg-command-generator.md +405 -0
- package/skills-library/creative-multimedia/image-optimization-pipeline.md +605 -0
- package/skills-library/creative-multimedia/multi-format-content-generator.md +1759 -0
- package/skills-library/creative-multimedia/og-image-generator.md +635 -0
- package/skills-library/creative-multimedia/podcast-audio-composition.md +1355 -0
- package/skills-library/creative-multimedia/podcast-quality-evaluation.md +1452 -0
- package/skills-library/creative-multimedia/podcast-script-generation.md +1841 -0
- package/skills-library/creative-multimedia/svg-generation.md +750 -0
- package/skills-library/creative-multimedia/text-to-speech-provider-selector.md +1414 -0
- package/skills-library/creative-multimedia/transcription-pipeline-selector.md +677 -0
- package/skills-library/creative-multimedia/video-streaming-setup.md +559 -0
- package/skills-library/database-solutions/AI_RESPONSE_DATABASE_CACHING.md +520 -0
- package/skills-library/database-solutions/CONDITIONAL_SQL_MIGRATION_PATTERN.md +119 -0
- package/skills-library/database-solutions/DATABASE_COLUMN_NAME_MISMATCH.md +393 -0
- package/skills-library/database-solutions/DATABASE_SCHEMA.md +394 -0
- package/skills-library/database-solutions/DATABASE_SCHEMA_VERIFICATION_GUIDE.md +348 -0
- package/skills-library/database-solutions/DATABASE_STRATEGY.md +71 -0
- package/skills-library/database-solutions/ES_MODULE_SEED_SCRIPT_PATTERN.md +52 -0
- package/skills-library/database-solutions/MIGRATION_GUIDE.md +3 -0
- package/skills-library/database-solutions/PLPGSQL_VARIABLE_CONFLICT_FIX.md +208 -0
- package/skills-library/database-solutions/POSTGRESQL_JSONB_DOUBLE_STRINGIFY_FIX.md +245 -0
- package/skills-library/database-solutions/POSTGRESQL_LICENSE_TABLE_DESIGN.md +393 -0
- package/skills-library/database-solutions/POSTGRESQL_UUID_DOCUMENT_RAG_DUAL_SCOPE.md +732 -0
- package/skills-library/database-solutions/POSTGRES_SQL_TEMPLATE_BINDING_ERROR.md +240 -0
- package/skills-library/database-solutions/PRISMA_DB_PUSH_DATA_LOSS_PREVENTION.md +141 -0
- package/skills-library/database-solutions/PRODUCTION_QUERY_OPTIMIZATION_RESTART_FIX.md +389 -0
- package/skills-library/database-solutions/RLS_SECURITY_GUIDE.md +107 -0
- package/skills-library/database-solutions/SCHEMA_ENHANCEMENTS_GUIDE.md +373 -0
- package/skills-library/database-solutions/SCHEMA_MIGRATION_GUIDE.md +368 -0
- package/skills-library/database-solutions/SCHEMA_VERIFICATION_QUICK_REFERENCE.md +104 -0
- package/skills-library/database-solutions/ai-erd-generator.md +1213 -0
- package/skills-library/database-solutions/content-publishing-states.md +631 -0
- package/skills-library/database-solutions/database-schema-designer.md +522 -0
- package/skills-library/database-solutions/er-diagram-components.md +569 -0
- package/skills-library/database-solutions/er-to-ddl-mapping.md +1405 -0
- package/skills-library/database-solutions/erd-creator-textbook-research.md +433 -0
- package/skills-library/database-solutions/erd-react-flow-architecture.md +1965 -0
- package/skills-library/database-solutions/mariadb-aggregate-function-replacement.md +145 -0
- package/skills-library/database-solutions/normalization-validator.md +778 -0
- package/skills-library/database-solutions/postgres-full-text-search-content.md +494 -0
- package/skills-library/database-solutions/postgresql-to-mysql-runtime-translation.md +286 -0
- package/skills-library/database-solutions/regex-alternation-ordering-sql-types.md +92 -0
- package/skills-library/database-solutions/reserved-word-context-aware-quoting.md +142 -0
- package/skills-library/database-solutions/sql-ddl-generator.md +756 -0
- package/skills-library/database-solutions/supabase-connection-pooler-fix.md +102 -0
- package/skills-library/deployment-security/CPANEL_NODE_DEPLOYMENT.md +166 -0
- package/skills-library/deployment-security/DEPLOYMENT.md +275 -0
- package/skills-library/deployment-security/DEPLOYMENT_CHECKLIST.md +363 -0
- package/skills-library/deployment-security/DEPLOYMENT_PLAN.md +669 -0
- package/skills-library/deployment-security/KNEX_DATABASE_ABSTRACTION.md +444 -0
- package/skills-library/deployment-security/LICENSE_KEY_SYSTEM.md +206 -0
- package/skills-library/deployment-security/NODE18_DEPENDENCY_COMPATIBILITY.md +284 -0
- package/skills-library/deployment-security/PHP_INSTALLER_WIZARD_GUIDE.md +315 -0
- package/skills-library/deployment-security/PM2_ENVIRONMENT_VARIABLE_CACHING.md +256 -0
- package/skills-library/deployment-security/PM2_MEMORY_EXHAUSTION_FIX.md +370 -0
- package/skills-library/deployment-security/PRODUCTION_DEPLOYMENT_GUIDE.md +592 -0
- package/skills-library/deployment-security/PRODUCTION_HARDENING_DOCUMENTATION.md +307 -0
- package/skills-library/deployment-security/PRODUCTION_RECOVERY_CHERRY_PICK_PATTERN.md +202 -0
- package/skills-library/deployment-security/PYINSTALLER_CUDA_WHISPER_BUNDLING.md +236 -0
- package/skills-library/deployment-security/SECURITY.md +41 -0
- package/skills-library/deployment-security/SMTP_SSL_HOSTNAME_MISMATCH_SHARED_HOSTING.md +220 -0
- package/skills-library/deployment-security/SPA_SEO_OPTIMIZATION_CPANEL.md +200 -0
- package/skills-library/deployment-security/SUPABASE_EDGE_FUNCTIONS.md +338 -0
- package/skills-library/deployment-security/VERCEL_GITHUB_DEPLOYMENT_GUIDE.md +858 -0
- package/skills-library/deployment-security/VPS_DEPLOYMENT_READINESS.md +356 -0
- package/skills-library/deployment-security/deployment-changes-not-applying.md +241 -0
- package/skills-library/deployment-security/env-file-management-production-local.md +203 -0
- package/skills-library/deployment-security/express-secure-file-downloads.md +413 -0
- package/skills-library/deployment-security/react-production-deployment-desktop-guide.md +2011 -0
- package/skills-library/deployment-security/self-hosted-supabase-coolify-guide.md +1684 -0
- package/skills-library/deployment-security/unique-features-ai-strategy-plaid-security.md +1613 -0
- package/skills-library/deployment-security/vps-deployment.md +135 -0
- package/skills-library/document-processing/WORD_EXPORT_MARKDOWN_FORMATTING.md +482 -0
- package/skills-library/document-processing/document-ai-landingai-integration.md +677 -0
- package/skills-library/document-processing/express-secure-file-downloads-mern.md +413 -0
- package/skills-library/document-processing/express-secure-file-downloads.md +413 -0
- package/skills-library/document-processing/md-to-word-converter.md +318 -0
- package/skills-library/document-processing/pdf-forms-integration/README.md +101 -0
- package/skills-library/document-processing/pdf-forms-integration/SKILL.md +662 -0
- package/skills-library/ecommerce/ADMIN_PRODUCTS_GUIDE.md +428 -0
- package/skills-library/ecommerce/ECOMMERCE_API_REFERENCE.md +776 -0
- package/skills-library/ecommerce/ECOMMERCE_COMPLETION_SUMMARY.md +673 -0
- package/skills-library/ecommerce/ECOMMERCE_IMPLEMENTATION_GUIDE.md +729 -0
- package/skills-library/ecommerce/ECOMMERCE_QUICK_REFERENCE.md +521 -0
- package/skills-library/ecommerce/ECOMMERCE_TESTING_CHECKLIST.md +565 -0
- package/skills-library/ecommerce/ECOMMERCE_WORKFLOW_GUIDE.md +1059 -0
- package/skills-library/ecommerce/PRODUCT_CREATION_EXPANDED.md +522 -0
- package/skills-library/ecommerce/agentic-commerce-protocol.md +203 -0
- package/skills-library/ecommerce/cart-abandonment-recovery.md +236 -0
- package/skills-library/ecommerce/cart-architecture-patterns.md +300 -0
- package/skills-library/ecommerce/cart-item-count-indicator.md +264 -0
- package/skills-library/ecommerce/checkout-ux-conversion.md +227 -0
- package/skills-library/ecommerce/composable-commerce-selection.md +166 -0
- package/skills-library/ecommerce/ecommerce-analytics-patterns.md +167 -0
- package/skills-library/ecommerce/fraud-detection-patterns.md +179 -0
- package/skills-library/ecommerce/inventory-stock-management.md +270 -0
- package/skills-library/ecommerce/order-saga-state-machine.md +336 -0
- package/skills-library/ecommerce/payment-provider-abstraction.md +245 -0
- package/skills-library/ecommerce/pci-compliance-checklist.md +192 -0
- package/skills-library/ecommerce/refund-chargeback-handling.md +177 -0
- package/skills-library/ecommerce/shipping-carrier-integration.md +218 -0
- package/skills-library/ecommerce/webhook-idempotency-patterns.md +253 -0
- package/skills-library/excalidraw-diagrams/.github/workflows/ci.yml +558 -0
- package/skills-library/excalidraw-diagrams/.github/workflows/prompt-gallery.yml +448 -0
- package/skills-library/excalidraw-diagrams/.github/workflows/release.yml +42 -0
- package/skills-library/excalidraw-diagrams/.github/workflows/test-reusable-ci.yml +25 -0
- package/skills-library/excalidraw-diagrams/CLAUDE.md +57 -0
- package/skills-library/excalidraw-diagrams/LICENSE +21 -0
- package/skills-library/excalidraw-diagrams/README.md +178 -0
- package/skills-library/excalidraw-diagrams/SKILL.md +715 -0
- package/skills-library/form-solutions/BUTTON_TYPE_FORM_SUBMISSION.md +336 -0
- package/skills-library/form-solutions/FILLABLE_PDF_IMPLEMENTATION.md +226 -0
- package/skills-library/form-solutions/SURVEYJS_QUESTIONNAIRE_SYSTEM.md +367 -0
- package/skills-library/form-solutions/tiptap-minimal-setup.md +690 -0
- package/skills-library/frontend/scholarly-classification-bubble-map.md +149 -0
- package/skills-library/infrastructure/ci-cd-pipeline-builder.md +517 -0
- package/skills-library/infrastructure/observability-designer.md +264 -0
- package/skills-library/infrastructure/performance-profiler.md +621 -0
- package/skills-library/installer-wizard-patterns.md +249 -0
- package/skills-library/integrations/CLAUDE_CODE_TOKEN_ANALYTICS.md +160 -0
- package/skills-library/integrations/CONFIGURABLE_AI_PROVIDER_SELECTION.md +728 -0
- package/skills-library/integrations/SOCKET_IO_BROADCAST_ALL_VS_ROOM.md +141 -0
- package/skills-library/integrations/VIRTUAL_MEETINGS_IMPLEMENTATION.md +374 -0
- package/skills-library/integrations/WORDPRESS_LEARNDASH_DATA_RECOVERY.md +53 -0
- package/skills-library/integrations/YOUTUBE_API_SETUP.md +141 -0
- package/skills-library/integrations/YOUTUBE_BOOKMARKING_EXPLANATION.md +252 -0
- package/skills-library/integrations/YOUTUBE_BOOKMARKING_SOLUTION.md +268 -0
- package/skills-library/integrations/YOUTUBE_OAUTH_SETUP_GUIDE.md +200 -0
- package/skills-library/integrations/YOUTUBE_VIDEO_FIX_COMPLETE.md +192 -0
- package/skills-library/integrations/ai-ml/GEMINI_AI_RAG_PIPELINE_COMPLETE_GUIDE.md +195 -0
- package/skills-library/integrations/ai-ml/GEMINI_IMAGE_GENERATION_SETUP.md +64 -0
- package/skills-library/integrations/cloudflare/cloudflare-turnstile-debugging.md +202 -0
- package/skills-library/integrations/cloudflare/cloudflare-turnstile-implementation.md +476 -0
- package/skills-library/integrations/cloudflare-turnstile-debugging.md +202 -0
- package/skills-library/integrations/cloudflare-turnstile-implementation.md +476 -0
- package/skills-library/integrations/ghost-creator-monetization-pattern.md +454 -0
- package/skills-library/integrations/headless-cms-architecture.md +484 -0
- package/skills-library/integrations/headless-cms-stack-selection.md +183 -0
- package/skills-library/integrations/payload-cms-patterns.md +674 -0
- package/skills-library/integrations/realtimestt-openwakeword-cuda-windows.md +229 -0
- package/skills-library/integrations/rss-podcast-integration.md +300 -0
- package/skills-library/integrations/wordpress/WORDPRESS_LEARNDASH_DATA_RECOVERY.md +53 -0
- package/skills-library/integrations/youtube/YOUTUBE_API_SETUP.md +141 -0
- package/skills-library/integrations/youtube/YOUTUBE_BOOKMARKING_EXPLANATION.md +252 -0
- package/skills-library/integrations/youtube/YOUTUBE_BOOKMARKING_SOLUTION.md +268 -0
- package/skills-library/integrations/youtube/YOUTUBE_OAUTH_SETUP_GUIDE.md +200 -0
- package/skills-library/integrations/youtube/YOUTUBE_VIDEO_FIX_COMPLETE.md +192 -0
- package/skills-library/marketing/campaign-analytics.md +97 -0
- package/skills-library/marketing/content-creator.md +105 -0
- package/skills-library/marketing/marketing-strategy-pmm.md +94 -0
- package/skills-library/marketing/social-media-analyzer.md +81 -0
- package/skills-library/methodology/ADVANCED_ORCHESTRATION_PATTERNS.md +401 -0
- package/skills-library/methodology/AGENT_SELF_IMPROVEMENT_LOOP.md +179 -0
- package/skills-library/methodology/BREATH_BASED_PARALLEL_EXECUTION.md +1 -1
- package/skills-library/methodology/CLEANSING_CYCLE.md +358 -0
- package/skills-library/methodology/CONFIDENCE_ANNOTATION_PATTERN.md +143 -0
- package/skills-library/methodology/CRITICAL_PATTERNS_DOCUMENTATION_COMPLETE.md +204 -0
- package/skills-library/methodology/DELIVERABLES_SUMMARY.md +341 -0
- package/skills-library/methodology/DIFFICULTY_AWARE_AGENT_ROUTING.md +252 -0
- package/skills-library/methodology/EVOLUTIONARY_SKILL_SYNTHESIS.md +219 -0
- package/skills-library/methodology/GLOMERULUS_DECISION_GATE.md +223 -0
- package/skills-library/methodology/HIBERNATION_SYSTEM.md +231 -0
- package/skills-library/methodology/INSTRUMENTATION_OVER_RESTRICTION.md +192 -0
- package/skills-library/methodology/MASTER_COMPLETION_SUMMARY.md +444 -0
- package/skills-library/methodology/MASTER_SESSION_COMPLETION.md +743 -0
- package/skills-library/methodology/MERN_QUICK_REFERENCE.md +358 -0
- package/skills-library/methodology/ORGAN_AGENT_MAPPING.md +177 -0
- package/skills-library/methodology/PARALLEL_WAVE_BASED_REFACTORING.md +440 -0
- package/skills-library/methodology/QUICK_REFERENCE.md +358 -0
- package/skills-library/methodology/SDFT_ONPOLICY_SELF_DISTILLATION.md +186 -0
- package/skills-library/methodology/SELF_QUESTIONING_TASK_GENERATION.md +270 -0
- package/skills-library/methodology/SESSION_COMPLETION_SUMMARY.md +304 -0
- package/skills-library/methodology/SESSION_SUMMARY.md +432 -0
- package/skills-library/methodology/WARRIOR_WORKFLOW_DEBUGGING_PROTOCOL.md +252 -0
- package/skills-library/methodology/tech-debt-tracker.md +570 -0
- package/skills-library/parallel-debug/SKILL.md +60 -0
- package/skills-library/patterns-standards/API_PATTERN_FIX_SUMMARY.md +236 -0
- package/skills-library/patterns-standards/BATCH_OPERATIONS_WITH_PROGRESS_MODAL.md +362 -0
- package/skills-library/patterns-standards/CRITICAL_CODING_PATTERNS.md +639 -0
- package/skills-library/patterns-standards/DARK_MODE_MODAL_VISIBILITY.md +258 -0
- package/skills-library/patterns-standards/ERROR_RESILIENCE_IMPLEMENTATION.md +375 -0
- package/skills-library/patterns-standards/ES_MODULE_IMPORT_HOISTING_DOTENV.md +298 -0
- package/skills-library/patterns-standards/NESTED_BACKDROP_FILTER_CSS_ARTIFACT_FIX.md +76 -0
- package/skills-library/patterns-standards/ORDERED_DETECTOR_PIPELINE_GRACEFUL_FALLBACK.md +333 -0
- package/skills-library/patterns-standards/PHASE_IMPORT_ERROR_DEBUGGING.md +271 -0
- package/skills-library/patterns-standards/PYNPUT_GLOBAL_HOTKEY_VK_MATCHING.md +252 -0
- package/skills-library/patterns-standards/REACT_USEEFFECT_CASCADE_RESET_FIX.md +132 -0
- package/skills-library/patterns-standards/SUBMENU_HOVER_DROPDOWN_PATTERN.md +225 -0
- package/skills-library/patterns-standards/TAILWIND_TEXT_VISIBILITY_OVERRIDE.md +322 -0
- package/skills-library/patterns-standards/THEME_AWARE_CSS_VARIABLES_PATTERN.md +209 -0
- package/skills-library/patterns-standards/THEME_USER_OBJECT_PROPERTY_NAMING.md +194 -0
- package/skills-library/patterns-standards/TOOLTIP_BLOCKING_CLICKS_FIX.md +267 -0
- package/skills-library/patterns-standards/claude-code-plugin-structure.md +235 -0
- package/skills-library/patterns-standards/react-i18next-setup.md +429 -0
- package/skills-library/patterns-standards/thesys-c1-generative-ui-integration.md +967 -0
- package/skills-library/plugin-development/CLAUDE_CODE_COMMAND_REGISTRATION_SILENT_FAILURE.md +315 -0
- package/skills-library/plugin-development/plugin-command-namespace-vs-global.md +390 -0
- package/skills-library/plugin-development/plugin-doc-auto-generation.md +172 -0
- package/skills-library/security/GITHUB_REPO_SECURITY_AUDIT.md +115 -0
- package/skills-library/security/admin-deletion-safety.md +396 -0
- package/skills-library/security/application-vuln-patterns.md +477 -0
- package/skills-library/security/env-secrets-manager.md +686 -0
- package/skills-library/security/secure-ai-application-templates.md +347 -0
- package/skills-library/security/sql-injection-prevention-postgresjs.md +151 -0
- package/skills-library/supabase-connection-pooler-fix.md +102 -0
- package/skills-library/system-context/POWERSHELL_BASH_INTEROP.md +82 -0
- package/skills-library/system-context/SERVICE_LIFECYCLE_MANAGEMENT.md +119 -0
- package/skills-library/system-context/SKILL.md +40 -0
- package/skills-library/system-context/WINDOWS_DEV_ENVIRONMENT.md +73 -0
- package/skills-library/testing/E2E_PLAYWRIGHT_PATTERNS.md +99 -0
- package/skills-library/testing/INTEGRATION_TEST_STRATEGY.md +82 -0
- package/skills-library/testing/RED_GREEN_BUGFIX_GATE.md +203 -0
- package/skills-library/testing/TEST_DATA_MANAGEMENT.md +69 -0
- package/skills-library/testing/VITEST_UNIT_TEST_PATTERNS.md +75 -0
- package/skills-library/testing/playwright-api-security-tests.md +202 -0
- package/skills-library/toolbox/SKILL.md +84 -0
- package/skills-library/toolbox/code-graph-and-web-scraping-mcps.md +237 -0
- package/skills-library/ui-ux-pro-max/ACCESSIBILITY_ESSENTIALS.md +115 -0
- package/skills-library/ui-ux-pro-max/DESIGN_SYSTEM_SCAFFOLDING.md +133 -0
- package/skills-library/ui-ux-pro-max/RESPONSIVE_LAYOUT_PATTERNS.md +119 -0
- package/skills-library/ui-ux-pro-max/SKILL.md +386 -0
- package/skills-library/ui-ux-pro-max/data/charts.csv +26 -0
- package/skills-library/ui-ux-pro-max/data/colors.csv +97 -0
- package/skills-library/ui-ux-pro-max/data/icons.csv +101 -0
- package/skills-library/ui-ux-pro-max/data/landing.csv +31 -0
- package/skills-library/ui-ux-pro-max/data/products.csv +97 -0
- package/skills-library/ui-ux-pro-max/data/react-performance.csv +45 -0
- package/skills-library/ui-ux-pro-max/data/stacks/astro.csv +54 -0
- package/skills-library/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/skills-library/ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -0
- package/skills-library/ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -0
- package/skills-library/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/skills-library/ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -0
- package/skills-library/ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -0
- package/skills-library/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/skills-library/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/skills-library/ui-ux-pro-max/data/stacks/shadcn.csv +61 -0
- package/skills-library/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/skills-library/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/skills-library/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/skills-library/ui-ux-pro-max/data/styles.csv +68 -0
- package/skills-library/ui-ux-pro-max/data/typography.csv +58 -0
- package/skills-library/ui-ux-pro-max/data/ui-reasoning.csv +101 -0
- package/skills-library/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/skills-library/ui-ux-pro-max/data/web-interface.csv +31 -0
- package/skills-library/wordpress-style-theme-components.md +1526 -0
- package/templates/ASSUMPTIONS.md +1 -1
- package/templates/DECISION_LOG.md +0 -1
- package/templates/phase-prompt.md +1 -1
- package/templates/phoenix-comparison.md +6 -6
- package/templates/skill-api-integration.md +106 -0
- package/templates/skill-architecture-pattern.md +92 -0
- package/templates/skill-debug-pattern.md +98 -0
- package/templates/skill-devops-recipe.md +107 -0
- package/templates/skill-general.md +65 -0
- package/templates/skill-ui-component.md +113 -0
- package/tools/uat-runner.py +179 -0
- package/version.json +7 -3
- package/workflows/handoff-session.md +2 -2
- package/workflows/new-project.md +2 -2
- package/workflows/plan-phase.md +1 -1
- package/.claude-plugin/plugin.json +0 -64
- package/skills-library/_general/methodology/LIVE_BREADCRUMB_PROTOCOL.md +0 -242
- package/skills-library/_general/methodology/llm-judge-memory-crud.md +0 -241
- package/skills-library/methodology/REFLEXION_MEMORY_PATTERN.md +0 -183
- package/skills-library/methodology/RESEARCH_BACKED_WORKFLOW_UPGRADE.md +0 -263
- package/skills-library/methodology/SABBATH_REST_PATTERN.md +0 -267
- package/skills-library/methodology/STONE_AND_SCAFFOLD.md +0 -220
- package/skills-library/specialists/api-architecture/api-designer.md +0 -49
- package/skills-library/specialists/api-architecture/graphql-architect.md +0 -49
- package/skills-library/specialists/api-architecture/mcp-developer.md +0 -51
- package/skills-library/specialists/api-architecture/microservices-architect.md +0 -50
- package/skills-library/specialists/api-architecture/websocket-engineer.md +0 -48
- package/skills-library/specialists/backend/django-expert.md +0 -52
- package/skills-library/specialists/backend/fastapi-expert.md +0 -52
- package/skills-library/specialists/backend/laravel-specialist.md +0 -52
- package/skills-library/specialists/backend/nestjs-expert.md +0 -51
- package/skills-library/specialists/backend/rails-expert.md +0 -53
- package/skills-library/specialists/backend/spring-boot-engineer.md +0 -56
- package/skills-library/specialists/data-ml/fine-tuning-expert.md +0 -48
- package/skills-library/specialists/data-ml/ml-pipeline.md +0 -47
- package/skills-library/specialists/data-ml/pandas-pro.md +0 -47
- package/skills-library/specialists/data-ml/rag-architect.md +0 -51
- package/skills-library/specialists/data-ml/spark-engineer.md +0 -47
- package/skills-library/specialists/frontend/angular-architect.md +0 -52
- package/skills-library/specialists/frontend/flutter-expert.md +0 -51
- package/skills-library/specialists/frontend/nextjs-developer.md +0 -54
- package/skills-library/specialists/frontend/react-native-expert.md +0 -50
- package/skills-library/specialists/frontend/vue-expert.md +0 -51
- package/skills-library/specialists/infrastructure/chaos-engineer.md +0 -74
- package/skills-library/specialists/infrastructure/cloud-architect.md +0 -70
- package/skills-library/specialists/infrastructure/database-optimizer.md +0 -64
- package/skills-library/specialists/infrastructure/devops-engineer.md +0 -70
- package/skills-library/specialists/infrastructure/kubernetes-specialist.md +0 -52
- package/skills-library/specialists/infrastructure/monitoring-expert.md +0 -70
- package/skills-library/specialists/infrastructure/sre-engineer.md +0 -70
- package/skills-library/specialists/infrastructure/terraform-engineer.md +0 -51
- package/skills-library/specialists/languages/cpp-pro.md +0 -74
- package/skills-library/specialists/languages/csharp-developer.md +0 -69
- package/skills-library/specialists/languages/dotnet-core-expert.md +0 -54
- package/skills-library/specialists/languages/golang-pro.md +0 -51
- package/skills-library/specialists/languages/java-architect.md +0 -49
- package/skills-library/specialists/languages/javascript-pro.md +0 -68
- package/skills-library/specialists/languages/kotlin-specialist.md +0 -68
- package/skills-library/specialists/languages/php-pro.md +0 -49
- package/skills-library/specialists/languages/python-pro.md +0 -52
- package/skills-library/specialists/languages/react-expert.md +0 -51
- package/skills-library/specialists/languages/rust-engineer.md +0 -50
- package/skills-library/specialists/languages/sql-pro.md +0 -56
- package/skills-library/specialists/languages/swift-expert.md +0 -69
- package/skills-library/specialists/languages/typescript-pro.md +0 -51
- package/skills-library/specialists/platform/atlassian-mcp.md +0 -52
- package/skills-library/specialists/platform/embedded-systems.md +0 -53
- package/skills-library/specialists/platform/game-developer.md +0 -53
- package/skills-library/specialists/platform/salesforce-developer.md +0 -53
- package/skills-library/specialists/platform/shopify-expert.md +0 -49
- package/skills-library/specialists/platform/wordpress-pro.md +0 -49
- package/skills-library/specialists/quality/code-documenter.md +0 -51
- package/skills-library/specialists/quality/code-reviewer.md +0 -67
- package/skills-library/specialists/quality/debugging-wizard.md +0 -51
- package/skills-library/specialists/quality/fullstack-guardian.md +0 -51
- package/skills-library/specialists/quality/legacy-modernizer.md +0 -50
- package/skills-library/specialists/quality/playwright-expert.md +0 -65
- package/skills-library/specialists/quality/spec-miner.md +0 -56
- package/skills-library/specialists/quality/test-master.md +0 -65
- package/skills-library/specialists/security/secure-code-guardian.md +0 -55
- package/skills-library/specialists/security/security-reviewer.md +0 -53
- package/skills-library/specialists/workflow/architecture-designer.md +0 -53
- package/skills-library/specialists/workflow/cli-developer.md +0 -70
- package/skills-library/specialists/workflow/feature-forge.md +0 -65
- package/skills-library/specialists/workflow/prompt-engineer.md +0 -54
- package/skills-library/specialists/workflow/the-fool.md +0 -62
- /package/skills-library/{performance → _general/performance}/cache-augmented-generation.md +0 -0
- /package/skills-library/{debugging → parallel-debug}/FAILURE_TAXONOMY_CLASSIFICATION.md +0 -0
- /package/skills-library/{debugging → parallel-debug}/THREE_AGENT_HYPOTHESIS_DEBUGGING.md +0 -0
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# ES Module Import Hoisting & dotenv - The Silent Initialization Bug
|
|
2
|
+
|
|
3
|
+
## The Problem
|
|
4
|
+
|
|
5
|
+
Environment variables from `.env` files are always `undefined` when checked at module load time, even though:
|
|
6
|
+
- The `.env` file exists and has correct values
|
|
7
|
+
- `dotenv.config()` is called at the top of your entry file
|
|
8
|
+
- The server logs show `.env` was loaded
|
|
9
|
+
|
|
10
|
+
### Error Messages
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
Error: Stripe is not configured. Please set STRIPE_SECRET_KEY environment variable.
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
[PaymentService] STRIPE_SECRET_KEY available: false
|
|
18
|
+
[PaymentService] Stripe initialized: false
|
|
19
|
+
[dotenv@17.2.3] injecting env (46) from .env ← Notice: dotenv loads AFTER!
|
|
20
|
+
[Server] Loaded environment from: .env
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Why It Was Hard
|
|
24
|
+
|
|
25
|
+
- **Counter-intuitive** - `dotenv.config()` is at the TOP of server.js, yet runs AFTER imports
|
|
26
|
+
- **Silent failure** - No errors during startup, services just initialize with `null`
|
|
27
|
+
- **Misleading logs** - Server says "Loaded environment" but services already failed
|
|
28
|
+
- **Works in CommonJS** - The same pattern works fine with `require()`, so developers don't expect it to break with ES Modules
|
|
29
|
+
- **Intermittent appearance** - Sometimes works if import order happens to be favorable
|
|
30
|
+
|
|
31
|
+
### Impact
|
|
32
|
+
|
|
33
|
+
- Payment processing fails (Stripe)
|
|
34
|
+
- Authentication fails (JWT secrets)
|
|
35
|
+
- Database connections fail
|
|
36
|
+
- Email services fail
|
|
37
|
+
- Any service initialized at module load time fails
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## The Solution
|
|
42
|
+
|
|
43
|
+
### Root Cause: ES Module Execution Order
|
|
44
|
+
|
|
45
|
+
In ES Modules, **all imports are hoisted and fully executed** before ANY of the importing module's code runs.
|
|
46
|
+
|
|
47
|
+
```javascript
|
|
48
|
+
// server.js - What you WRITE:
|
|
49
|
+
import dotenv from 'dotenv';
|
|
50
|
+
dotenv.config(); // You think this runs first
|
|
51
|
+
|
|
52
|
+
import { paymentService } from './services/paymentService.js';
|
|
53
|
+
|
|
54
|
+
// server.js - What ACTUALLY HAPPENS:
|
|
55
|
+
// 1. paymentService.js is FULLY EXECUTED (including top-level code)
|
|
56
|
+
// 2. dotenv module is loaded
|
|
57
|
+
// 3. THEN server.js code runs (dotenv.config())
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
So if `paymentService.js` has:
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
// paymentService.js - TOP-LEVEL CODE (runs at import time!)
|
|
64
|
+
const stripe = process.env.STRIPE_SECRET_KEY
|
|
65
|
+
? new Stripe(process.env.STRIPE_SECRET_KEY)
|
|
66
|
+
: null; // Always null because dotenv hasn't loaded yet!
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
This code runs **before** `dotenv.config()` is called, so `process.env.STRIPE_SECRET_KEY` is always `undefined`.
|
|
70
|
+
|
|
71
|
+
### How to Fix: Lazy Initialization Pattern
|
|
72
|
+
|
|
73
|
+
Replace top-level initialization with a getter function that initializes on first use:
|
|
74
|
+
|
|
75
|
+
**BEFORE (Broken):**
|
|
76
|
+
```javascript
|
|
77
|
+
// paymentService.js
|
|
78
|
+
import Stripe from 'stripe';
|
|
79
|
+
|
|
80
|
+
// BAD: Runs at import time, before dotenv loads!
|
|
81
|
+
const stripe = process.env.STRIPE_SECRET_KEY
|
|
82
|
+
? new Stripe(process.env.STRIPE_SECRET_KEY)
|
|
83
|
+
: null;
|
|
84
|
+
|
|
85
|
+
export const createPayment = async () => {
|
|
86
|
+
if (!stripe) throw new Error('Stripe not configured');
|
|
87
|
+
// ...
|
|
88
|
+
};
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**AFTER (Fixed):**
|
|
92
|
+
```javascript
|
|
93
|
+
// paymentService.js
|
|
94
|
+
import Stripe from 'stripe';
|
|
95
|
+
|
|
96
|
+
// GOOD: Lazy initialization - runs on first use, after dotenv loads
|
|
97
|
+
let stripe = null;
|
|
98
|
+
let stripeInitialized = false;
|
|
99
|
+
|
|
100
|
+
const getStripe = () => {
|
|
101
|
+
if (!stripeInitialized) {
|
|
102
|
+
stripeInitialized = true;
|
|
103
|
+
if (process.env.STRIPE_SECRET_KEY) {
|
|
104
|
+
stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
105
|
+
console.log('[PaymentService] ✅ Stripe initialized successfully');
|
|
106
|
+
} else {
|
|
107
|
+
console.warn('[PaymentService] ⚠️ STRIPE_SECRET_KEY not set');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
return stripe;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
export const createPayment = async () => {
|
|
114
|
+
const stripeInstance = getStripe();
|
|
115
|
+
if (!stripeInstance) throw new Error('Stripe not configured');
|
|
116
|
+
// Use stripeInstance instead of stripe
|
|
117
|
+
};
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Alternative Fix: Dynamic Import
|
|
121
|
+
|
|
122
|
+
If you can't modify the service file, use dynamic import:
|
|
123
|
+
|
|
124
|
+
```javascript
|
|
125
|
+
// server.js
|
|
126
|
+
import dotenv from 'dotenv';
|
|
127
|
+
dotenv.config();
|
|
128
|
+
|
|
129
|
+
// Dynamic import - runs AFTER this point
|
|
130
|
+
const { paymentService } = await import('./services/paymentService.js');
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Testing the Fix
|
|
136
|
+
|
|
137
|
+
### Before Fix - Logs Show Wrong Order
|
|
138
|
+
```
|
|
139
|
+
[PaymentService] STRIPE_SECRET_KEY available: false ← Checked BEFORE dotenv
|
|
140
|
+
[PaymentService] Stripe initialized: false
|
|
141
|
+
[dotenv@17.2.3] injecting env from .env ← dotenv loads AFTER
|
|
142
|
+
[Server] Loaded environment from: .env
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### After Fix - Lazy Init Works
|
|
146
|
+
```
|
|
147
|
+
[dotenv@17.2.3] injecting env from .env
|
|
148
|
+
[Server] Loaded environment from: .env
|
|
149
|
+
[Server] Starting...
|
|
150
|
+
[PaymentService] ✅ Stripe initialized successfully (lazy) ← On first use
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Verification Test
|
|
154
|
+
```javascript
|
|
155
|
+
// Add this to verify the fix
|
|
156
|
+
console.log('[DEBUG] At import time, STRIPE_SECRET_KEY is:',
|
|
157
|
+
process.env.STRIPE_SECRET_KEY ? 'SET' : 'NOT SET');
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
If this shows "NOT SET" at the top of your service file but "SET" inside a function, you have this bug.
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Prevention
|
|
165
|
+
|
|
166
|
+
### 1. Never Initialize at Top Level
|
|
167
|
+
```javascript
|
|
168
|
+
// ❌ BAD - Top-level initialization
|
|
169
|
+
const client = new ThirdPartyClient(process.env.API_KEY);
|
|
170
|
+
|
|
171
|
+
// ✅ GOOD - Lazy initialization
|
|
172
|
+
let client = null;
|
|
173
|
+
const getClient = () => {
|
|
174
|
+
if (!client && process.env.API_KEY) {
|
|
175
|
+
client = new ThirdPartyClient(process.env.API_KEY);
|
|
176
|
+
}
|
|
177
|
+
return client;
|
|
178
|
+
};
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### 2. Use Config Modules with Lazy Loading
|
|
182
|
+
```javascript
|
|
183
|
+
// config/stripe.js
|
|
184
|
+
let stripe = null;
|
|
185
|
+
let initialized = false;
|
|
186
|
+
|
|
187
|
+
export const getStripe = () => {
|
|
188
|
+
if (!initialized) {
|
|
189
|
+
initialized = true;
|
|
190
|
+
if (process.env.STRIPE_SECRET_KEY) {
|
|
191
|
+
stripe = new Stripe(process.env.STRIPE_SECRET_KEY);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return stripe;
|
|
195
|
+
};
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### 3. Check for This Pattern in Code Reviews
|
|
199
|
+
|
|
200
|
+
Look for:
|
|
201
|
+
```javascript
|
|
202
|
+
// Red flags at module top level:
|
|
203
|
+
const x = process.env.SOMETHING;
|
|
204
|
+
const client = new Client(process.env.KEY);
|
|
205
|
+
if (process.env.FEATURE_FLAG) { ... }
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 4. Add Startup Verification
|
|
209
|
+
|
|
210
|
+
```javascript
|
|
211
|
+
// server.js - after dotenv.config()
|
|
212
|
+
const requiredEnvVars = ['STRIPE_SECRET_KEY', 'JWT_SECRET', 'DATABASE_URL'];
|
|
213
|
+
const missing = requiredEnvVars.filter(v => !process.env[v]);
|
|
214
|
+
if (missing.length) {
|
|
215
|
+
console.error('Missing required environment variables:', missing);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Related Patterns
|
|
223
|
+
|
|
224
|
+
- [PM2 Environment Variable Caching](../deployment-security/PM2_ENVIRONMENT_VARIABLE_CACHING.md)
|
|
225
|
+
- [Environment File Management](../deployment-security/env-file-management-production-local.md)
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Common Mistakes to Avoid
|
|
230
|
+
|
|
231
|
+
- ❌ **Top-level `process.env` checks** - Always undefined before dotenv
|
|
232
|
+
- ❌ **Assuming import order matters** - ES Modules hoist ALL imports
|
|
233
|
+
- ❌ **Using CommonJS patterns in ES Modules** - `require()` order ≠ `import` order
|
|
234
|
+
- ❌ **Debug logging at top level** - Shows misleading "not set" messages
|
|
235
|
+
- ❌ **Conditional exports based on env** - Will always use the "else" branch
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## Why This Works in CommonJS But Not ES Modules
|
|
240
|
+
|
|
241
|
+
### CommonJS (require) - Works
|
|
242
|
+
```javascript
|
|
243
|
+
// server.js - CommonJS
|
|
244
|
+
require('dotenv').config(); // Runs immediately, synchronously
|
|
245
|
+
|
|
246
|
+
// This import happens AFTER dotenv.config()
|
|
247
|
+
const payment = require('./services/payment');
|
|
248
|
+
// payment.js top-level code now has access to env vars
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### ES Modules (import) - Broken
|
|
252
|
+
```javascript
|
|
253
|
+
// server.js - ES Modules
|
|
254
|
+
import dotenv from 'dotenv';
|
|
255
|
+
dotenv.config(); // You THINK this runs first...
|
|
256
|
+
|
|
257
|
+
import { payment } from './services/payment.js';
|
|
258
|
+
// BUT payment.js was already FULLY EXECUTED before this line!
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
The key difference: `require()` is a function that runs synchronously at that point in the code. `import` is a declaration that's hoisted and resolved before any code runs.
|
|
262
|
+
|
|
263
|
+
---
|
|
264
|
+
|
|
265
|
+
## Resources
|
|
266
|
+
|
|
267
|
+
- [MDN: ES Modules](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules)
|
|
268
|
+
- [Node.js: ES Modules](https://nodejs.org/api/esm.html)
|
|
269
|
+
- [dotenv with ES Modules](https://github.com/motdotla/dotenv#how-do-i-use-dotenv-with-import)
|
|
270
|
+
|
|
271
|
+
---
|
|
272
|
+
|
|
273
|
+
## Time to Implement
|
|
274
|
+
|
|
275
|
+
**10-15 minutes** per service - Convert top-level init to lazy getter pattern
|
|
276
|
+
|
|
277
|
+
## Difficulty Level
|
|
278
|
+
|
|
279
|
+
⭐⭐⭐⭐ (4/5) - Very hard to diagnose, easy to fix once understood
|
|
280
|
+
|
|
281
|
+
---
|
|
282
|
+
|
|
283
|
+
**Author Notes:**
|
|
284
|
+
|
|
285
|
+
This bug cost 2+ hours of debugging. The symptoms are extremely confusing:
|
|
286
|
+
- `.env` file has the right values
|
|
287
|
+
- Server logs show "Loaded environment from: .env"
|
|
288
|
+
- But services report env vars as undefined
|
|
289
|
+
|
|
290
|
+
The critical insight: **In ES Modules, ALL imports execute BEFORE your code runs.**
|
|
291
|
+
|
|
292
|
+
Once you understand this, the fix is obvious. But getting there requires understanding the fundamental difference between CommonJS and ES Modules execution models.
|
|
293
|
+
|
|
294
|
+
**Key diagnostic:** Look at the LOG ORDER. If service initialization logs appear BEFORE the dotenv loading log, you have this bug.
|
|
295
|
+
|
|
296
|
+
**Discovery date:** January 2026
|
|
297
|
+
**Project:** MERN Community LMS
|
|
298
|
+
**Symptom:** "Stripe is not configured" despite valid .env file
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Nested CSS backdrop-filter Artifact Fix
|
|
2
|
+
|
|
3
|
+
## Problem
|
|
4
|
+
|
|
5
|
+
A white blurry line or haze overlay appears on UI elements when using glassmorphism / frosted glass CSS effects. The artifact is most visible in dark mode and appears as a semi-transparent white strip or blur effect layered on top of content.
|
|
6
|
+
|
|
7
|
+
## Root Cause
|
|
8
|
+
|
|
9
|
+
**Nested `backdrop-filter: blur()` declarations** on parent and child elements create compounding blur artifacts. Each `backdrop-filter` creates a new stacking context and compositing layer. When two blur layers overlap, the browser renders an extra semi-transparent white haze at the boundary.
|
|
10
|
+
|
|
11
|
+
### Example of the Problem
|
|
12
|
+
|
|
13
|
+
```css
|
|
14
|
+
/* Parent element */
|
|
15
|
+
.panel-container {
|
|
16
|
+
background-color: rgba(17, 24, 39, 0.85);
|
|
17
|
+
-webkit-backdrop-filter: blur(20px);
|
|
18
|
+
backdrop-filter: blur(20px);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/* Child element — REDUNDANT blur causes artifact */
|
|
22
|
+
[data-theme='dark'] .bible-viewer {
|
|
23
|
+
background-color: rgba(17, 24, 39, 0.5); /* Semi-transparent */
|
|
24
|
+
-webkit-backdrop-filter: blur(20px);
|
|
25
|
+
backdrop-filter: blur(20px);
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
The child's blur composites on top of the parent's blur, creating a visible white line at the boundary.
|
|
30
|
+
|
|
31
|
+
## Solution
|
|
32
|
+
|
|
33
|
+
Remove `backdrop-filter` from the **inner/child** element and use an opaque or semi-opaque background instead:
|
|
34
|
+
|
|
35
|
+
```css
|
|
36
|
+
/* Parent keeps the glass effect */
|
|
37
|
+
.panel-container {
|
|
38
|
+
background-color: rgba(17, 24, 39, 0.85);
|
|
39
|
+
-webkit-backdrop-filter: blur(20px);
|
|
40
|
+
backdrop-filter: blur(20px);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/* Child uses opaque background — NO blur */
|
|
44
|
+
[data-theme='dark'] .bible-viewer {
|
|
45
|
+
background-color: var(--bg-secondary); /* Opaque, no blur */
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Rule of Thumb
|
|
50
|
+
|
|
51
|
+
**Only ONE element in any ancestor chain should have `backdrop-filter`.** If the parent already blurs, children should use:
|
|
52
|
+
- Opaque backgrounds (`var(--bg-secondary)`)
|
|
53
|
+
- Semi-transparent backgrounds without blur (`rgba(...)` alone)
|
|
54
|
+
- `background: inherit` to match the parent
|
|
55
|
+
|
|
56
|
+
## Debugging Tips
|
|
57
|
+
|
|
58
|
+
1. **Inspect with DevTools** — Toggle `backdrop-filter` off on each element to find which one is redundant
|
|
59
|
+
2. **Check dark mode specifically** — Artifacts are most visible when backgrounds are semi-transparent dark colors
|
|
60
|
+
3. **Search for all blur declarations**: `grep -r "backdrop-filter" src/` to find all instances
|
|
61
|
+
4. **Test across browsers** — Chrome, Firefox, and Safari handle compositing differently
|
|
62
|
+
|
|
63
|
+
## When This Happens
|
|
64
|
+
|
|
65
|
+
- Glassmorphism / frosted glass UI designs
|
|
66
|
+
- Dark mode implementations with semi-transparent panels
|
|
67
|
+
- Nested panel layouts (sidebar → content → sub-panel)
|
|
68
|
+
- CSS frameworks that apply blur at multiple levels
|
|
69
|
+
|
|
70
|
+
## Tech Stack
|
|
71
|
+
- CSS (any framework)
|
|
72
|
+
- Tailwind CSS (when using `backdrop-blur-*` utilities)
|
|
73
|
+
- Dark mode / theme switching
|
|
74
|
+
|
|
75
|
+
## Tags
|
|
76
|
+
`css` `backdrop-filter` `blur` `glassmorphism` `dark-mode` `visual-artifact` `stacking-context`
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ordered-detector-pipeline-graceful-fallback
|
|
3
|
+
category: patterns-standards
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
contributed: 2026-02-17
|
|
6
|
+
contributor: my-other-project
|
|
7
|
+
last_updated: 2026-02-17
|
|
8
|
+
contributors:
|
|
9
|
+
- my-other-project
|
|
10
|
+
tags: [detection, pipeline, graceful-degradation, postgresql, try-catch, incremental-rollout, milestone, feature-flags]
|
|
11
|
+
difficulty: medium
|
|
12
|
+
usage_count: 1
|
|
13
|
+
success_rate: 100
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Ordered Detector Pipeline with Graceful Fallback
|
|
17
|
+
|
|
18
|
+
## Problem
|
|
19
|
+
|
|
20
|
+
You need to detect multiple conditions (milestones, achievements, alerts, etc.) by querying **different database tables** — but some tables may not exist yet because they belong to future phases that haven't shipped. A single missing table would crash the entire detection system.
|
|
21
|
+
|
|
22
|
+
### Why It Was Hard
|
|
23
|
+
|
|
24
|
+
- Standard approaches (one big JOIN, CTE chain) fail if **any** table is missing
|
|
25
|
+
- Feature-flag systems add complexity and state management overhead
|
|
26
|
+
- Incremental rollouts mean tables arrive over time (Phase 18 ships before Phase 19)
|
|
27
|
+
- Detectors have **different priorities** — the most impressive milestone should surface first
|
|
28
|
+
- Need cooldown, deduplication, and conversion tracking alongside detection
|
|
29
|
+
- Must work with zero configuration changes when new tables appear later
|
|
30
|
+
|
|
31
|
+
### Impact
|
|
32
|
+
|
|
33
|
+
Without this pattern, adding a milestone detector that references a not-yet-created table (`user_progress`) would crash the entire `/api/milestones/check` endpoint, preventing all milestone celebrations — even for tables that DO exist.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Solution Pattern
|
|
38
|
+
|
|
39
|
+
**Ordered Detector Array** — define detectors as an array of `{ type, detect }` objects sorted by priority. Each `detect` function runs its own SQL query inside its own `try/catch`. If the table doesn't exist or the query fails, it returns `null` gracefully. The pipeline iterates until it finds a match.
|
|
40
|
+
|
|
41
|
+
### Root Cause
|
|
42
|
+
|
|
43
|
+
The problem occurs because:
|
|
44
|
+
1. SQL JOINs across non-existent tables throw fatal errors
|
|
45
|
+
2. A single `try/catch` around multiple queries loses granularity
|
|
46
|
+
3. Priority ordering requires sequential evaluation (can't parallelize)
|
|
47
|
+
|
|
48
|
+
### Architecture
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
checkMilestones(userId)
|
|
52
|
+
│
|
|
53
|
+
┌──────▼──────┐
|
|
54
|
+
│ canShow? │ ← 24h cooldown check
|
|
55
|
+
│ (cooldown) │
|
|
56
|
+
└──────┬──────┘
|
|
57
|
+
│ yes
|
|
58
|
+
┌────────────▼────────────────┐
|
|
59
|
+
│ MILESTONE_DETECTORS array │
|
|
60
|
+
│ (ordered by impressiveness) │
|
|
61
|
+
└────────────┬────────────────┘
|
|
62
|
+
│
|
|
63
|
+
┌──────────────────┼──────────────────┐
|
|
64
|
+
▼ ▼ ▼
|
|
65
|
+
┌───────────┐ ┌───────────┐ ┌───────────┐
|
|
66
|
+
│ Detector 1│ │ Detector 2│ ... │ Detector N│
|
|
67
|
+
│ try/catch │ │ try/catch │ │ try/catch │
|
|
68
|
+
│ → null ok │ │ → null ok │ │ → null ok │
|
|
69
|
+
└─────┬─────┘ └─────┬─────┘ └─────┬─────┘
|
|
70
|
+
│ │ │
|
|
71
|
+
▼ ▼ ▼
|
|
72
|
+
{data,context} null {data,context}
|
|
73
|
+
│ │
|
|
74
|
+
▼ │
|
|
75
|
+
alreadyCelebrated? ─── yes ─── skip ────────┘
|
|
76
|
+
│ no │
|
|
77
|
+
▼ ▼
|
|
78
|
+
getCelebrationConfig ──── inactive ─── continue
|
|
79
|
+
│ active
|
|
80
|
+
▼
|
|
81
|
+
recordCelebration → return milestone
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### How to Fix / Implement
|
|
85
|
+
|
|
86
|
+
**Step 1: Define the detector array with priority ordering**
|
|
87
|
+
|
|
88
|
+
```javascript
|
|
89
|
+
// Ordered by "impressiveness" — most meaningful surfaces first
|
|
90
|
+
const MILESTONE_DETECTORS = [
|
|
91
|
+
{ type: 'learning_path_complete', detect: detectLearningPathComplete },
|
|
92
|
+
{ type: 'lesson_100', detect: detectLesson100 },
|
|
93
|
+
{ type: 'certificate_earned', detect: detectCertificateEarned },
|
|
94
|
+
{ type: 'first_course_complete', detect: detectFirstCourseComplete },
|
|
95
|
+
{ type: 'streak_7_days', detect: detectStreak7 }, // table from Phase 19
|
|
96
|
+
];
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Step 2: Each detector is an independent function with its own try/catch**
|
|
100
|
+
|
|
101
|
+
```javascript
|
|
102
|
+
// This table exists now (Phase 15) — works immediately
|
|
103
|
+
async function detectFirstCourseComplete(userId) {
|
|
104
|
+
try {
|
|
105
|
+
const [row] = await sql`
|
|
106
|
+
SELECT ep.course_id, c.title AS course_title
|
|
107
|
+
FROM enrollment_progress ep
|
|
108
|
+
JOIN courses c ON c.id = ep.course_id
|
|
109
|
+
WHERE ep.user_id = ${userId}
|
|
110
|
+
AND (ep.progress_percentage >= 100 OR ep.status = 'completed')
|
|
111
|
+
ORDER BY ep.updated_at ASC
|
|
112
|
+
LIMIT 1
|
|
113
|
+
`;
|
|
114
|
+
if (!row) return null;
|
|
115
|
+
return {
|
|
116
|
+
data: { course_id: row.course_id }, // for deduplication
|
|
117
|
+
context: row.course_title, // human-readable
|
|
118
|
+
};
|
|
119
|
+
} catch { return null; } // table missing or query error → skip
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// This table doesn't exist yet (Phase 19) — gracefully returns null
|
|
123
|
+
async function detectStreak7(userId) {
|
|
124
|
+
try {
|
|
125
|
+
const [row] = await sql`
|
|
126
|
+
SELECT current_streak FROM user_progress
|
|
127
|
+
WHERE user_id = ${userId} AND current_streak >= 7
|
|
128
|
+
`;
|
|
129
|
+
if (!row) return null;
|
|
130
|
+
return {
|
|
131
|
+
data: { streak: row.current_streak },
|
|
132
|
+
context: `${row.current_streak}-day streak`,
|
|
133
|
+
};
|
|
134
|
+
} catch {
|
|
135
|
+
// user_progress table may not exist yet (Phase 19 creates it)
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**Step 3: Pipeline iterates, deduplicates, and respects cooldown**
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
static async checkMilestones(userId) {
|
|
145
|
+
// Cooldown: max 1 celebration per 24 hours
|
|
146
|
+
const canShow = await canShowCelebration(userId);
|
|
147
|
+
if (!canShow) return null;
|
|
148
|
+
|
|
149
|
+
for (const { type, detect } of MILESTONE_DETECTORS) {
|
|
150
|
+
const result = await detect(userId);
|
|
151
|
+
if (result) {
|
|
152
|
+
// Check if already celebrated this exact achievement
|
|
153
|
+
const alreadyShown = await alreadyCelebrated(userId, type, result.data);
|
|
154
|
+
if (!alreadyShown) {
|
|
155
|
+
// Check if this milestone type is active (admin toggle)
|
|
156
|
+
const config = await getCelebrationConfig(type);
|
|
157
|
+
if (!config || !config.is_active) continue;
|
|
158
|
+
|
|
159
|
+
// Record and return
|
|
160
|
+
const celebration = await recordCelebration(userId, type, result.data);
|
|
161
|
+
return {
|
|
162
|
+
id: celebration.id,
|
|
163
|
+
milestoneType: type,
|
|
164
|
+
config,
|
|
165
|
+
context: result.context,
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Step 4: Deduplication via JSONB comparison**
|
|
175
|
+
|
|
176
|
+
```sql
|
|
177
|
+
-- Each detector returns { data } which becomes milestone_data
|
|
178
|
+
-- UNIQUE constraint prevents duplicate celebrations
|
|
179
|
+
UNIQUE(user_id, milestone_type, milestone_data)
|
|
180
|
+
|
|
181
|
+
-- Check uses JSONB cast for exact comparison
|
|
182
|
+
SELECT 1 FROM milestone_celebrations
|
|
183
|
+
WHERE user_id = $1
|
|
184
|
+
AND milestone_type = $2
|
|
185
|
+
AND milestone_data = $3::jsonb
|
|
186
|
+
LIMIT 1
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Step 5: Cooldown via SQL interval**
|
|
190
|
+
|
|
191
|
+
```sql
|
|
192
|
+
-- No celebration shown in last 24 hours
|
|
193
|
+
SELECT 1 FROM milestone_celebrations
|
|
194
|
+
WHERE user_id = $1
|
|
195
|
+
AND shown_at > now() - interval '24 hours'
|
|
196
|
+
LIMIT 1
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Key Design Decisions
|
|
202
|
+
|
|
203
|
+
| Decision | Why |
|
|
204
|
+
|----------|-----|
|
|
205
|
+
| Per-detector try/catch (not global) | Missing table X doesn't block table Y detection |
|
|
206
|
+
| Priority ordering (array, not parallel) | Most impressive milestone surfaces first |
|
|
207
|
+
| Each detector returns `{ data, context }` | `data` for dedup, `context` for UI display |
|
|
208
|
+
| Cooldown at pipeline level (not detector) | One celebration per 24h regardless of type |
|
|
209
|
+
| Config-driven messages | Admin can customize per milestone type without code changes |
|
|
210
|
+
| ON CONFLICT upsert for recording | Idempotent — re-showing updates `shown_at` |
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Database Schema (Supporting Infrastructure)
|
|
215
|
+
|
|
216
|
+
```sql
|
|
217
|
+
-- Admin-configurable celebration messages
|
|
218
|
+
CREATE TABLE milestone_configs (
|
|
219
|
+
milestone_type VARCHAR(50) PRIMARY KEY,
|
|
220
|
+
title TEXT NOT NULL,
|
|
221
|
+
message TEXT NOT NULL,
|
|
222
|
+
emoji VARCHAR(10) DEFAULT '🎉',
|
|
223
|
+
suggested_amounts JSONB DEFAULT '[10, 25, 50]',
|
|
224
|
+
is_active BOOLEAN DEFAULT true,
|
|
225
|
+
updated_at TIMESTAMPTZ DEFAULT now()
|
|
226
|
+
);
|
|
227
|
+
|
|
228
|
+
-- Tracks shown/dismissed/converted celebrations per user
|
|
229
|
+
CREATE TABLE milestone_celebrations (
|
|
230
|
+
id SERIAL PRIMARY KEY,
|
|
231
|
+
user_id INTEGER REFERENCES profiles(id),
|
|
232
|
+
milestone_type VARCHAR(50) REFERENCES milestone_configs(milestone_type),
|
|
233
|
+
milestone_data JSONB DEFAULT '{}',
|
|
234
|
+
shown_at TIMESTAMPTZ DEFAULT now(),
|
|
235
|
+
dismissed_at TIMESTAMPTZ,
|
|
236
|
+
converted BOOLEAN DEFAULT false,
|
|
237
|
+
converted_at TIMESTAMPTZ,
|
|
238
|
+
donation_amount NUMERIC(10,2) DEFAULT 0,
|
|
239
|
+
UNIQUE(user_id, milestone_type, milestone_data)
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
-- Partial index for analytics queries
|
|
243
|
+
CREATE INDEX idx_celebrations_converted
|
|
244
|
+
ON milestone_celebrations(milestone_type) WHERE converted = true;
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
---
|
|
248
|
+
|
|
249
|
+
## Testing the Pattern
|
|
250
|
+
|
|
251
|
+
### Verify Graceful Fallback
|
|
252
|
+
```sql
|
|
253
|
+
-- Drop a table that a detector references
|
|
254
|
+
DROP TABLE IF EXISTS user_progress;
|
|
255
|
+
|
|
256
|
+
-- Call the endpoint — should NOT crash, just skip that detector
|
|
257
|
+
GET /api/milestones/check
|
|
258
|
+
-- Expected: returns milestone from another detector or null
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
### Verify Priority Ordering
|
|
262
|
+
```sql
|
|
263
|
+
-- Give user both a completed course AND a certificate
|
|
264
|
+
-- The certificate detector has higher priority
|
|
265
|
+
-- Expected: certificate milestone returned, not course completion
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Verify Cooldown
|
|
269
|
+
```sql
|
|
270
|
+
-- Trigger a celebration, then call check again within 24h
|
|
271
|
+
-- Expected: null (cooldown active)
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
### Verify Deduplication
|
|
275
|
+
```sql
|
|
276
|
+
-- Complete the same course twice
|
|
277
|
+
-- Expected: celebration shown only once (UNIQUE constraint)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
---
|
|
281
|
+
|
|
282
|
+
## When to Use
|
|
283
|
+
|
|
284
|
+
- Building achievement/milestone detection across multiple feature phases
|
|
285
|
+
- Any detection pipeline where data sources ship incrementally
|
|
286
|
+
- Multi-table aggregation where some tables are optional
|
|
287
|
+
- Feature rollouts where backend tables appear in different sprints
|
|
288
|
+
- Gamification systems (badges, streaks, levels) built across phases
|
|
289
|
+
- Alert/notification systems checking diverse conditions
|
|
290
|
+
|
|
291
|
+
## When NOT to Use
|
|
292
|
+
|
|
293
|
+
- All data sources exist and are guaranteed present (just use a JOIN)
|
|
294
|
+
- Single-table detection (overkill — just write a simple query)
|
|
295
|
+
- Real-time streaming events (use an event bus, not polling)
|
|
296
|
+
- Detection order doesn't matter (use `Promise.allSettled` instead)
|
|
297
|
+
|
|
298
|
+
## Common Mistakes
|
|
299
|
+
|
|
300
|
+
- Wrapping ALL detectors in one `try/catch` — defeats the purpose, one failure kills all
|
|
301
|
+
- Running detectors in parallel — breaks priority ordering (highest first matters)
|
|
302
|
+
- Forgetting to return `null` in the catch — undefined bubbles up as truthy
|
|
303
|
+
- Using `SELECT *` in detectors — return only what's needed for dedup and display
|
|
304
|
+
- Skipping cooldown — users get spammed with celebrations on every page load
|
|
305
|
+
- Hardcoding celebration messages — use a config table so admins can customize
|
|
306
|
+
|
|
307
|
+
---
|
|
308
|
+
|
|
309
|
+
## Related Skills
|
|
310
|
+
|
|
311
|
+
- [ERROR_RESILIENCE_IMPLEMENTATION.md](./ERROR_RESILIENCE_IMPLEMENTATION.md) - Database trigger error handling
|
|
312
|
+
- [CONDITIONAL_SQL_MIGRATION_PATTERN.md](../database-solutions/CONDITIONAL_SQL_MIGRATION_PATTERN.md) - Idempotent migrations
|
|
313
|
+
- [GAMIFICATION_SYSTEM.md](../advanced-features/GAMIFICATION_SYSTEM.md) - Points, badges, achievements
|
|
314
|
+
|
|
315
|
+
## References
|
|
316
|
+
|
|
317
|
+
- Phase 18 — Milestone Giving (Harvest Offering) implementation
|
|
318
|
+
- postgres.js tagged template literals: https://github.com/porsager/postgres
|
|
319
|
+
- PostgreSQL JSONB comparison: https://www.postgresql.org/docs/current/datatype-json.html
|
|
320
|
+
|
|
321
|
+
## Time to Implement
|
|
322
|
+
|
|
323
|
+
**2-3 hours** for full pipeline (detectors + config table + cooldown + deduplication + conversion tracking)
|
|
324
|
+
**30 minutes** to add a new detector to an existing pipeline
|
|
325
|
+
|
|
326
|
+
## Difficulty Level
|
|
327
|
+
|
|
328
|
+
⭐⭐⭐ (3/5) - Conceptually simple, but requires discipline: every detector MUST be isolated, return format MUST be consistent, and the pipeline MUST handle all edge cases (missing tables, cooldown, dedup).
|
|
329
|
+
|
|
330
|
+
---
|
|
331
|
+
|
|
332
|
+
**Author Notes:**
|
|
333
|
+
The key insight is treating each detector as a **completely independent unit** that can fail without affecting others. This is the database equivalent of microservice isolation — but within a single service. The pattern scales beautifully: adding Phase 19's streak detector required zero changes to existing code, just appending to the array. When the `user_progress` table appears, the detector automatically starts working.
|