Use a prompt to generate standalone HTML dashboards from your database
A prompt template that instructs Ana to query your database and generate an interactive HTML report with filters.
Prompt
HTML Report Generation Prompt
# ============================================================================# PLAYBOOK CONSTRUCTION SKELETON - BEST PRACTICES (GENERALIZED)# ============================================================================# A comprehensive guide for building data-driven HTML reports with interactivity# ============================================================================## OVERALL STRUCTURE1. CONFIGURATION & SETUP2. DATA LOADING (External Files)3. DATA QUERYING (Primary Data)4. DATA QUERYING (Detail/Subcategory Data)5. HELPER FUNCTIONS6. DATA PROCESSING & TRANSFORMATION7. METRIC DEFINITIONS8. TABLE/REPORT BUILDING9. DATA SERIALIZATION (to JavaScript)10. HTML GENERATION11. FILE OUTPUT# ============================================================================# STEP 1: CONFIGURATION & SETUP# ============================================================================Purpose: Define constants, parameters, and report scope- Organization/entity identifier- Data segment combinations (e.g., categories, regions, products)- Date ranges- Business logic constantsBest Practices:- Use descriptive constant names in UPPER_CASE- Group related configurations together- Document any non-obvious business rules- Make it easy to add/remove segments# ============================================================================# STEP 2: LOAD EXTERNAL DATA (Excel/CSV files)# ============================================================================Purpose: Load reference data from uploaded files (budgets, targets, benchmarks)- Use try/except for error handling- Create mappings between file data and database values- Filter to relevant scope (organization, year, etc.)- Handle missing files gracefullyBest Practices:- Always use try/except when loading external files- Create empty DataFrames as fallback- Print clear success/error messages- Validate data after loading (check for required columns)- Map file names to database names explicitly# ============================================================================# STEP 3: QUERY PRIMARY DATA# ============================================================================Purpose: Pull main metrics from database- Loop through each data segment combination- Store results in dictionary keyed by combination- Print progress for transparency- Handle empty results gracefullyBest Practices:- Use enumerate() for progress tracking- Store in dictionary with tuple keys for multi-dimensional grouping- Skip empty results but log them- Print row counts for validation- Use consistent filter structure across all queries# ============================================================================# STEP 4: QUERY DETAIL/SUBCATEGORY DATA# ============================================================================Purpose: Pull granular breakdowns (subcategories, line items, etc.)- Similar loop structure as primary query- Include additional dimensions for granularity- CRITICAL: Include parent category dimension to prevent duplicationBest Practices:- Only query details for segments with primary data- Always include parent category to prevent row duplication- Use consistent filter structure across queries- Log when detail data is missing- Verify no duplicate rows in results# ============================================================================# STEP 5: DEFINE HELPER FUNCTIONS# ============================================================================Purpose: Reusable functions for calculations and formattingKey functions to include:- format_value() - Format numbers as currency, percent, decimal, etc.- get_value() - Extract single period value- get_annual_value() - Calculate annual aggregate (weighted if needed)- get_ytd_value() - Calculate year-to-date aggregate (weighted if needed)- get_detail_value() - Extract subcategory values- get_reference_value() - Lookup from external file (targets, benchmarks)Best Practices:- Add docstrings to all functions- Handle None/NaN values gracefully- Use consistent parameter names- Include type hints for clarity- Test edge cases (empty data, division by zero)- Return None for missing data, not 0# ============================================================================# STEP 6: PROCESS & TRANSFORM DATA# ============================================================================Purpose: Clean, calculate derived metrics, merge datasets- Convert date columns to datetime- Calculate derived metrics (ratios, normalized values)- Merge detail data with primary data- Store in organized dictionary structureBest Practices:- Convert dates early in the process- Handle division by zero explicitly- Use .copy() to avoid SettingWithCopyWarning- Store related datasets together in nested dictionaries- Validate calculations with spot checks- Create all derived metrics before building tables# ============================================================================# STEP 7: DEFINE COMPREHENSIVE METRICS LIST# ============================================================================Purpose: Create master list of all metrics to displayStructure: (display_name, column_name, format_type, is_indent, data_source, filter)This creates a single source of truth for report structure.Best Practices:- Extract subcategories from actual data (don't hardcode)- Use consistent naming conventions- Group related metrics together- Use indentation for hierarchical metrics- Document any special calculation requirements- Keep list in logical display order# ============================================================================# STEP 8: BUILD TABLES WITH DATA POPULATION# ============================================================================Purpose: Create final data tables for each segment combination- Determine available time periods dynamically- Loop through metrics list- Populate each column (years, months, YTD, targets)- Apply conditional formatting logic- Store as DataFrameBest Practices:- Determine time periods dynamically from data- Use consistent column naming patterns- Handle parsing errors gracefully- Consider metric directionality for conditional formatting- Validate table structure before proceeding- Apply conditional formatting after all data is populated# ============================================================================# STEP 9: CONVERT TO JAVASCRIPT DATA STRUCTURE# ============================================================================Purpose: Serialize Python data to JSON for HTML interactivity- Organize by hierarchical structure (Category → Segment)- Convert DataFrames to column-oriented dictionaries- Serialize to JSON string for embeddingBest Practices:- Use column-oriented format for efficient rendering- Indent JSON for readability during debugging- Validate JSON structure before embedding- Consider data size (compress if needed)- Test with special characters in data# ============================================================================# STEP 10: GENERATE HTML REPORT# ============================================================================Purpose: Create interactive HTML with embedded data and stylingKey Components:1. Version/Timestamp generation2. CSS styling (colors, layout, responsive design)3. HTML structure (header, filters, tables, footer)4. JavaScript for interactivity5. Embedded dataBest Practices:- Use semantic HTML5 elements- Include meta tags for caching and viewport- Embed CSS and JavaScript for portability- Use CSS custom properties for theming- Make responsive with media queries- Add accessibility features (ARIA labels)- Include version in multiple places# ============================================================================# STEP 11: FILE OUTPUT# ============================================================================Purpose: Save HTML file with proper naming conventionBest Practices:- Use descriptive filenames with version- Include UTF-8 encoding for special characters- Log file size and key statistics- Provide clear completion message- Include next steps or usage instructions# ============================================================================# KEY DESIGN PATTERNS# ============================================================================1. Separation of Concerns - Data acquisition (Steps 2-4) - Data processing (Steps 5-6) - Presentation (Steps 9-10) - Each step has a single responsibility2. Error Handling - Try/except for external dependencies - Check for empty results before proceeding - Graceful degradation (continue without optional data) - Clear error messages for debugging3. Progress Tracking - Print statements at each major step - Row counts and success indicators - Enumeration for loop progress - Final summary with statistics4. Reusability - Helper functions for common operations - Parameterized queries - Modular HTML/CSS/JS components - Configuration at the top5. Maintainability - Clear section headers with separators - Inline comments for complex logic - Consistent naming conventions - Version tracking throughout6. Performance - Batch queries by segment - Store results in dictionaries (O(1) lookup) - Minimize redundant calculations - Efficient data structures (column-oriented for JS)7. Data Integrity - Include parent categories to prevent duplication - Use weighted averages for rates - Validate calculations with spot checks - Handle division by zero explicitly# ============================================================================# COMMON PITFALLS TO AVOID# ============================================================================## 1. DATA DUPLICATIONProblem: Querying subcategories without parent category causes duplicate rowsSolution: Always include parent_category dimension in detail queriesProblem: Using simple averages for rates/ratiosSolution: Use weighted averages by volume/member months## 2. DATE HANDLINGProblem: Assuming dates are datetime objectsSolution: Convert to datetime early with pd.to_datetime()Problem: Hardcoding month rangesSolution: Determine dynamically from data (df['date'].max())## 3. FORMATTINGProblem: Not checking for None/NaN before formattingSolution: Always check: if value is None or pd.isna(value): return '-'Problem: Inconsistent decimal placesSolution: Use format_type parameter consistently## 4. CALCULATIONSProblem: Division by zero errorsSolution: Check denominator > 0 before dividingProblem: Wrong aggregation method for ratesSolution: Weighted average by volume, not simple average## 5. HTML/JAVASCRIPTProblem: Not escaping special characters in stringsSolution: Use json.dumps() for safe serializationProblem: Hardcoding column names in JavaScriptSolution: Iterate through data keys dynamically## 6. CONDITIONAL FORMATTINGProblem: Assuming lower is always betterSolution: Consider metric directionality (cost vs revenue)Problem: Applying formatting to wrong columnSolution: Target specific columns (e.g., Current YTD only)# ============================================================================# QUICK REFERENCE# ============================================================================Step 1: Configure (constants, segments)Step 2: Load external files (budgets, targets)Step 3: Query primary data (main metrics)Step 4: Query detail data (subcategories with parent category)Step 5: Define helpers (format, calculate, lookup)Step 6: Process data (transform, derive, merge)Step 7: Define metrics (master list with formatting)Step 8: Build tables (populate, format, conditionally style)Step 9: Serialize to JS (column-oriented JSON)Step 10: Generate HTML (embed data, CSS, JavaScript)Step 11: Output file (save with version)Critical Success Factors:- Include parent category in detail queries (prevents duplication)- Use weighted averages for rates (not simple averages)- Handle None/NaN before formatting (prevents errors)- Test with multiple segments (ensures flexibility)- Version everything (enables tracking)
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"TextQL Docs","colors":{"primary":"#0D9373","light":"#07C983","dark":"#0D9373"},"logo":{"light":"https://mintcdn.com/textql/9RDmZW4lVU96oHnJ/logo-textql/light.svg?fit=max\u0026auto=format\u0026n=9RDmZW4lVU96oHnJ\u0026q=85\u0026s=069d276e4ee2f256e061f8e2db9860a3","dark":"https://mintcdn.com/textql/9RDmZW4lVU96oHnJ/logo-textql/dark.svg?fit=max\u0026auto=format\u0026n=9RDmZW4lVU96oHnJ\u0026q=85\u0026s=1a728bc3acfd6eda203c49a45eac0355"},"favicon":"https://mintcdn.com/textql/jK3bTwZd_T-GaQ4j/favicon.svg?fit=max\u0026auto=format\u0026n=jK3bTwZd_T-GaQ4j\u0026q=85\u0026s=4f7feffa45a51a795a1b929f05a772bf","api":{"openapi":["api-reference/platform/chat.openapi.yaml","api-reference/platform/playbooks.openapi.yaml","api-reference/platform/agents.openapi.yaml","api-reference/platform/connectors.openapi.yaml","api-reference/platform/api_access_key.openapi.yaml","api-reference/platform/sandbox.openapi.yaml","api-reference/platform/v2.openapi.yaml","api-reference/speakeasy/textql-api-with-code-samples.yaml"],"mdx":{"auth":{"method":"bearer"},"server":"https://app.textql.com"}},"appearance":{"default":"light","strict":false},"navbar":{"links":[{"href":"mailto:support@textql.com","label":"Support"}],"primary":{"type":"button","label":"Dashboard","href":"https://app.textql.com"}},"footer":{"socials":{"x":"https://x.com/TextQL","github":"https://github.com/textqllabs","linkedin":"https://www.linkedin.com/company/textql"}},"styling":{"latex":true},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"textql","hasAudioNarration":false,"actualSubdomain":"textql","customDomains":["docs.textql.com"],"gitSource":{"type":"github","owner":"textqllabs","repo":"demo2","deployBranch":"main","contentDirectory":"docs/public","isPrivate":true,"mountPath":"","label":""},"entitlements":{},"buildId":"6af603b7aecf0202e5cba9fa","clientVersion":"0.0.4128","searchFilterCounts":[{"language":"default","tag":"v3 API (SDK)","count":454},{"language":"default","tag":"Workshops","count":202},{"language":"default","tag":"Documentation","count":164},{"language":"default","tag":"Ontology Management Service","count":70},{"language":"default","tag":"v2 API","count":56},{"language":"default","tag":"Set Up Your Data","count":56},{"language":"default","tag":"RBAC Service","count":41},{"language":"default","tag":"Chat Service","count":39},{"language":"default","tag":"Playbook Service","count":39},{"language":"default","tag":"How It Works","count":32}]},"assistantConfig":{},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-rbac-roles","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[{"filePath":"style.css","content":"table{width:100%;border-collapse:collapse;margin:1rem 0}th,td{border:1px solid #e5e7eb;padding:0.6rem 0.85rem;text-align:left;vertical-align:top;line-height:1.45}th{background:#f9fafb;font-weight:600}th:first-child,td:first-child{white-space:nowrap}.dark th,.dark td{border-color:#2b2b2b}.dark th{background:#18181b}"}],"page":{"pagePath":"core/guides/interactive-html-reports","slug":"/core/guides/interactive-html-reports","pageMetadata":{"title":"Interactive HTML Reports","description":"Use a prompt to generate standalone HTML dashboards from your database","icon":"file-code","href":"/core/guides/interactive-html-reports"},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsx(_components.p, {\n children: \"Use a prompt to generate standalone HTML dashboards from your database\"\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx,jsxs:_jsxs}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){const _components={code:`code`,p:`p`,pre:`pre`,span:`span`,..._provideComponents(),...props.components},{Accordion,CodeBlock,Heading}=_components;if(!Accordion)_missingMdxReference(`Accordion`,true);if(!CodeBlock)_missingMdxReference(`CodeBlock`,true);if(!Heading)_missingMdxReference(`Heading`,true);return _jsxs(_Fragment,{children:[_jsx(_components.p,{children:`A prompt template that instructs Ana to query your database and generate an interactive HTML report with filters.`}),`\n`,_jsx(`video`,{controls:true,className:`mint-w-full mint-aspect-video`,src:`https://pub-8699413992d644f2b85a9b4cb11b2bc5.r2.dev/html-skeleton.mp4`}),`\n`,_jsx(Heading,{level:`2`,id:`prompt`,children:`Prompt`}),`\n`,_jsx(Accordion,{title:`HTML Report Generation Prompt`,id:`html-report-generation-prompt`,children:_jsx(CodeBlock,{filename:``,numberOfLines:`334`,language:`text`,children:_jsx(_components.pre,{className:`shiki shiki-themes github-light-default dark-plus`,style:{backgroundColor:`#ffffff`,\"--shiki-dark-bg\":`#0B0C0E`,color:`#1f2328`,\"--shiki-dark\":`#D4D4D4`},language:`text`,children:_jsxs(_components.code,{language:`text`,numberOfLines:`334`,children:[_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# PLAYBOOK CONSTRUCTION SKELETON - BEST PRACTICES (GENERALIZED)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# A comprehensive guide for building data-driven HTML reports with interactivity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## OVERALL STRUCTURE`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`1. CONFIGURATION \u0026 SETUP`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`2. DATA LOADING (External Files)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`3. DATA QUERYING (Primary Data)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`4. DATA QUERYING (Detail/Subcategory Data)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`5. HELPER FUNCTIONS`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`6. DATA PROCESSING \u0026 TRANSFORMATION`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`7. METRIC DEFINITIONS`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`8. TABLE/REPORT BUILDING`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`9. DATA SERIALIZATION (to JavaScript)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`10. HTML GENERATION`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`11. FILE OUTPUT`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 1: CONFIGURATION \u0026 SETUP`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Define constants, parameters, and report scope`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Organization/entity identifier`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Data segment combinations (e.g., categories, regions, products)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Date ranges`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Business logic constants`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use descriptive constant names in UPPER_CASE`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Group related configurations together`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Document any non-obvious business rules`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Make it easy to add/remove segments`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 2: LOAD EXTERNAL DATA (Excel/CSV files)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Load reference data from uploaded files (budgets, targets, benchmarks)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use try/except for error handling`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Create mappings between file data and database values`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Filter to relevant scope (organization, year, etc.)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle missing files gracefully`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Always use try/except when loading external files`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Create empty DataFrames as fallback`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Print clear success/error messages`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Validate data after loading (check for required columns)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Map file names to database names explicitly`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 3: QUERY PRIMARY DATA`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Pull main metrics from database`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Loop through each data segment combination`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Store results in dictionary keyed by combination`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Print progress for transparency`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle empty results gracefully`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use enumerate() for progress tracking`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Store in dictionary with tuple keys for multi-dimensional grouping`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Skip empty results but log them`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Print row counts for validation`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use consistent filter structure across all queries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 4: QUERY DETAIL/SUBCATEGORY DATA`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Pull granular breakdowns (subcategories, line items, etc.)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Similar loop structure as primary query`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include additional dimensions for granularity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- CRITICAL: Include parent category dimension to prevent duplication`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Only query details for segments with primary data`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Always include parent category to prevent row duplication`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use consistent filter structure across queries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Log when detail data is missing`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Verify no duplicate rows in results`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 5: DEFINE HELPER FUNCTIONS`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Reusable functions for calculations and formatting`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Key functions to include:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- format_value() - Format numbers as currency, percent, decimal, etc.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- get_value() - Extract single period value`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- get_annual_value() - Calculate annual aggregate (weighted if needed)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- get_ytd_value() - Calculate year-to-date aggregate (weighted if needed)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- get_detail_value() - Extract subcategory values`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- get_reference_value() - Lookup from external file (targets, benchmarks)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Add docstrings to all functions`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle None/NaN values gracefully`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use consistent parameter names`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include type hints for clarity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Test edge cases (empty data, division by zero)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Return None for missing data, not 0`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 6: PROCESS \u0026 TRANSFORM DATA`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Clean, calculate derived metrics, merge datasets`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Convert date columns to datetime`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Calculate derived metrics (ratios, normalized values)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Merge detail data with primary data`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Store in organized dictionary structure`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Convert dates early in the process`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle division by zero explicitly`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use .copy() to avoid SettingWithCopyWarning`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Store related datasets together in nested dictionaries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Validate calculations with spot checks`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Create all derived metrics before building tables`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 7: DEFINE COMPREHENSIVE METRICS LIST`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Create master list of all metrics to display`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Structure: (display_name, column_name, format_type, is_indent, data_source, filter)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`This creates a single source of truth for report structure.`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Extract subcategories from actual data (don't hardcode)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use consistent naming conventions`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Group related metrics together`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use indentation for hierarchical metrics`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Document any special calculation requirements`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Keep list in logical display order`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 8: BUILD TABLES WITH DATA POPULATION`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Create final data tables for each segment combination`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Determine available time periods dynamically`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Loop through metrics list`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Populate each column (years, months, YTD, targets)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Apply conditional formatting logic`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Store as DataFrame`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Determine time periods dynamically from data`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use consistent column naming patterns`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle parsing errors gracefully`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Consider metric directionality for conditional formatting`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Validate table structure before proceeding`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Apply conditional formatting after all data is populated`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 9: CONVERT TO JAVASCRIPT DATA STRUCTURE`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Serialize Python data to JSON for HTML interactivity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Organize by hierarchical structure (Category → Segment)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Convert DataFrames to column-oriented dictionaries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Serialize to JSON string for embedding`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use column-oriented format for efficient rendering`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Indent JSON for readability during debugging`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Validate JSON structure before embedding`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Consider data size (compress if needed)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Test with special characters in data`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 10: GENERATE HTML REPORT`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Create interactive HTML with embedded data and styling`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Key Components:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`1. Version/Timestamp generation`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`2. CSS styling (colors, layout, responsive design)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`3. HTML structure (header, filters, tables, footer)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`4. JavaScript for interactivity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`5. Embedded data`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use semantic HTML5 elements`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include meta tags for caching and viewport`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Embed CSS and JavaScript for portability`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use CSS custom properties for theming`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Make responsive with media queries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Add accessibility features (ARIA labels)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include version in multiple places`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# STEP 11: FILE OUTPUT`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Purpose: Save HTML file with proper naming convention`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Best Practices:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use descriptive filenames with version`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include UTF-8 encoding for special characters`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Log file size and key statistics`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Provide clear completion message`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include next steps or usage instructions`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# KEY DESIGN PATTERNS`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`1. Separation of Concerns`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Data acquisition (Steps 2-4)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Data processing (Steps 5-6)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Presentation (Steps 9-10)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Each step has a single responsibility`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`2. Error Handling`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Try/except for external dependencies`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Check for empty results before proceeding`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Graceful degradation (continue without optional data)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Clear error messages for debugging`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`3. Progress Tracking`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Print statements at each major step`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Row counts and success indicators`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Enumeration for loop progress`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Final summary with statistics`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`4. Reusability`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Helper functions for common operations`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Parameterized queries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Modular HTML/CSS/JS components`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Configuration at the top`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`5. Maintainability`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Clear section headers with separators`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Inline comments for complex logic`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Consistent naming conventions`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Version tracking throughout`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`6. Performance`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Batch queries by segment`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Store results in dictionaries (O(1) lookup)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Minimize redundant calculations`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Efficient data structures (column-oriented for JS)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`7. Data Integrity`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Include parent categories to prevent duplication`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Use weighted averages for rates`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Validate calculations with spot checks`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:` - Handle division by zero explicitly`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# COMMON PITFALLS TO AVOID`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 1. DATA DUPLICATION`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Querying subcategories without parent category causes duplicate rows`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Always include parent_category dimension in detail queries`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Using simple averages for rates/ratios`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Use weighted averages by volume/member months`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 2. DATE HANDLING`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Assuming dates are datetime objects`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Convert to datetime early with pd.to_datetime()`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Hardcoding month ranges`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Determine dynamically from data (df['date'].max())`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 3. FORMATTING`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Not checking for None/NaN before formatting`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Always check: if value is None or pd.isna(value): return '-'`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Inconsistent decimal places`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Use format_type parameter consistently`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 4. CALCULATIONS`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Division by zero errors`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Check denominator > 0 before dividing`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Wrong aggregation method for rates`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Weighted average by volume, not simple average`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 5. HTML/JAVASCRIPT`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Not escaping special characters in strings`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Use json.dumps() for safe serialization`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Hardcoding column names in JavaScript`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Iterate through data keys dynamically`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`## 6. CONDITIONAL FORMATTING`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Assuming lower is always better`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Consider metric directionality (cost vs revenue)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Problem: Applying formatting to wrong column`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Solution: Target specific columns (e.g., Current YTD only)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# QUICK REFERENCE`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`# ============================================================================`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 1: Configure (constants, segments)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 2: Load external files (budgets, targets)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 3: Query primary data (main metrics)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 4: Query detail data (subcategories with parent category)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 5: Define helpers (format, calculate, lookup)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 6: Process data (transform, derive, merge)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 7: Define metrics (master list with formatting)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 8: Build tables (populate, format, conditionally style)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 9: Serialize to JS (column-oriented JSON)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 10: Generate HTML (embed data, CSS, JavaScript)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Step 11: Output file (save with version)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`Critical Success Factors:`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Include parent category in detail queries (prevents duplication)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Use weighted averages for rates (not simple averages)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Handle None/NaN before formatting (prevents errors)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Test with multiple segments (ensures flexibility)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{children:`- Version everything (enables tracking)`})}),`\n`,_jsx(_components.span,{className:`line`,children:_jsx(_components.span,{})})]})})})})]})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent};function _missingMdxReference(id,component){throw new Error(`Expected `+(component?`component`:`object`)+\" `\"+id+\"` to be defined: you likely forgot to import, pass, or provide it.\")}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Interactive HTML Reports","description":"Use a prompt to generate standalone HTML dashboards from your database","icon":"file-code","href":"/core/guides/interactive-html-reports"}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[{"title":"Prompt","slug":"prompt","depth":2,"children":[]}],"codeExamples":{}},"jsLinks":[],"dynamicCss":".mint-aspect-video {\n aspect-ratio: 16 / 9\n}\n.mint-w-full {\n width: 100%\n}","subdomain":"textql","siteName":"TextQL Docs","title":"Interactive HTML Reports - TextQL Docs","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-01-24T03:22:26.825Z","originalFileLocation":"core/guides/interactive-html-reports.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"light\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"Use a prompt to generate standalone HTML dashboards from your database\">\u003cmeta data-mint-head name=\"application-name\" content=\"TextQL Docs\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/android-chrome-192x192.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/apple-touch-icon.png\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/favicon-16x16.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/favicon-32x32.png\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/favicon.ico\" media=\"(prefers-color-scheme: light)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"192x192\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon-dark/android-chrome-192x192.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon-dark/favicon-16x16.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon-dark/favicon-32x32.png\" media=\"(prefers-color-scheme: dark)\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon-dark/favicon.ico\" media=\"(prefers-color-scheme: dark)\">\u003cmeta data-mint-head property=\"og:title\" content=\"Interactive HTML Reports - TextQL Docs\">\u003cmeta data-mint-head property=\"og:description\" content=\"Use a prompt to generate standalone HTML dashboards from your database\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"TextQL Docs\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://docs.textql.com/core/guides/interactive-html-reports\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://textql.mintlify.site/_mintlify/api/og/v2?division=Get+Better+Results\u0026amp;title=Interactive+HTML+Reports\u0026amp;description=Use+a+prompt+to+generate+standalone+HTML+dashboards+from+your+database\u0026amp;theme=27d2effcabcfba3c2216aacf\u0026amp;signature=f1b0f07515f1a8074199c6e86eda120af66d1d14a541c4da9fff95e964d5a521\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Interactive HTML Reports - TextQL Docs\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"Use a prompt to generate standalone HTML dashboards from your database\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://textql.mintlify.site/_mintlify/api/og/v2?division=Get+Better+Results\u0026amp;title=Interactive+HTML+Reports\u0026amp;description=Use+a+prompt+to+generate+standalone+HTML+dashboards+from+your+database\u0026amp;theme=27d2effcabcfba3c2216aacf\u0026amp;signature=f1b0f07515f1a8074199c6e86eda120af66d1d14a541c4da9fff95e964d5a521\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"/mintlify-assets/_mintlify/favicons/textql/UPDKEixAE9_oDjsV/_generated/favicon/browserconfig.xml\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"TextQL Docs\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#0D9373\">\u003clink data-mint-head rel=\"canonical\" href=\"https://docs.textql.com/core/guides/interactive-html-reports\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/core/guides/interactive-html-reports.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://docs.textql.com/#organization\",\"name\":\"TextQL Docs\",\"url\":\"https://docs.textql.com\",\"logo\":{\"@type\":\"ImageObject\",\"url\":\"https://mintcdn.com/textql/9RDmZW4lVU96oHnJ/logo-textql/light.svg?fit=max\u0026auto=format\u0026n=9RDmZW4lVU96oHnJ\u0026q=85\u0026s=069d276e4ee2f256e061f8e2db9860a3\"}},{\"@type\":\"WebSite\",\"@id\":\"https://docs.textql.com#website\",\"name\":\"TextQL Docs\",\"url\":\"https://docs.textql.com\",\"publisher\":{\"@id\":\"https://docs.textql.com/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://docs.textql.com/core/guides/interactive-html-reports#webpage\",\"url\":\"https://docs.textql.com/core/guides/interactive-html-reports\",\"name\":\"Interactive HTML Reports\",\"description\":\"Use a prompt to generate standalone HTML dashboards from your database\",\"dateModified\":\"2026-01-24T03:22:26.825Z\",\"isPartOf\":{\"@id\":\"https://docs.textql.com#website\"},\"breadcrumb\":{\"@id\":\"https://docs.textql.com/core/guides/interactive-html-reports#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://docs.textql.com/core/guides/interactive-html-reports#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Get Better Results\",\"item\":\"https://docs.textql.com/core/get-better-results/how-ana-thinks\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Interactive HTML Reports\",\"item\":\"https://docs.textql.com/core/guides/interactive-html-reports\"}]},{\"@type\":[\"Article\",\"TechArticle\"],\"@id\":\"https://docs.textql.com/core/guides/interactive-html-reports#article\",\"headline\":\"Interactive HTML Reports\",\"name\":\"Interactive HTML Reports\",\"description\":\"Use a prompt to generate standalone HTML dashboards from your database\",\"url\":\"https://docs.textql.com/core/guides/interactive-html-reports\",\"mainEntityOfPage\":{\"@id\":\"https://docs.textql.com/core/guides/interactive-html-reports#webpage\"},\"dateModified\":\"2026-01-24T03:22:26.825Z\",\"publisher\":{\"@id\":\"https://docs.textql.com/#organization\"},\"isPartOf\":{\"@id\":\"https://docs.textql.com#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"TextQL Docs\",\"publisher\":{\"@type\":\"Organization\",\"name\":\"TextQL Docs\"},\"provider\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","agentPointerHref":"/core/guides/interactive-html-reports.md","siteName":"TextQL Docs","nav":{"global":null,"tabs":[{"tab":"Documentation","groups":[{"group":"Get Started","pages":[{"title":"What is TextQL","sidebarTitle":"Introduction","icon":"rocket","href":"/core/get-started/quickstart"},{"title":"Connect Your Data","icon":"database","href":"/core/get-started/connect-your-data"},{"title":"Example Connectors","icon":"flask","href":"/core/get-started/sample-data"},{"title":"Your First Chat","icon":"comment-dots","href":"/core/get-started/your-first-chat"}]},{"group":"How It Works","pages":[{"title":"Threads — Chat with Ana","sidebarTitle":"Threads","icon":"robot","href":"/core/how-it-works/ana/overview"},{"group":"Playbooks","icon":"play","pages":[{"title":"Build Playbooks Directly in Threads","icon":"play","href":"/core/how-it-works/playbooks/build-from-threads"},{"title":"Overview","icon":"play","href":"/core/how-it-works/playbooks"},{"title":"Slack Integration","icon":"play","href":"/core/how-it-works/playbooks/slack-integration"},{"title":"Teams Integration","icon":"microsoft","href":"/core/how-it-works/playbooks/teams-integration"},{"title":"Templates","icon":"play","href":"/core/how-it-works/playbooks/templates"},{"title":"Your First Playbook","icon":"play","href":"/core/how-it-works/playbooks/your-first-playbook"}]},{"group":"Tools","icon":"wrench","pages":[{"title":"Overview","sidebarTitle":"Overview","icon":"wrench","href":"/core/how-it-works/tools"},{"title":"Text to SQL","sidebarTitle":"Text to SQL","icon":"wrench","href":"/core/how-it-works/tools/text-to-sql"},{"title":"TQL Query","icon":"brackets-curly","href":"/core/how-it-works/tools/tql-query"},{"title":"Ana Forms","sidebarTitle":"Ana Forms","icon":"wrench","href":"/core/how-it-works/tools/ana-forms"},{"title":"Web Search","sidebarTitle":"Web Search","icon":"wrench","href":"/core/how-it-works/tools/web-search"},{"title":"Thread History Search","icon":"magnifying-glass","href":"/core/how-it-works/tools/thread-search"},{"title":"Platform API Tools","sidebarTitle":"Platform API Tools","icon":"plug","href":"/core/how-it-works/tools/platform-api"},{"title":"File Upload","sidebarTitle":"File Upload","icon":"paperclip","href":"/core/how-it-works/tools/file-upload"},{"title":"Voice Input","sidebarTitle":"Voice Input","icon":"microphone","href":"/core/how-it-works/tools/voice-input"},{"title":"Decide","sidebarTitle":"Decide","icon":"scale-balanced","href":"/core/how-it-works/tools/decide"}]},{"group":"Data Apps","icon":"window-restore","pages":[{"title":"Data Apps","icon":"window-restore","href":"/core/how-it-works/data-apps"},{"title":"The ana.* Functions","icon":"code","href":"/core/how-it-works/data-apps/ana-functions"},{"title":"Row-Level Security","icon":"shield-halved","href":"/core/how-it-works/data-apps/row-level-security"}]},{"title":"Dashboards","icon":"chart-mixed","href":"/core/how-it-works/dashboards"},{"title":"Artifacts","icon":"folder-open","href":"/core/how-it-works/artifacts"},{"title":"Citations","sidebarTitle":"Citations","icon":"quote-right","href":"/core/how-it-works/citations"},{"title":"Subagents","sidebarTitle":"Subagents","icon":"sitemap","href":"/core/how-it-works/ana/subagents"},{"title":"Agent Harnesses","sidebarTitle":"Agent Harnesses","icon":"robot","href":"/core/how-it-works/ana/harnesses"},{"group":"Feed","icon":"rss","pages":[{"title":"Agents","sidebarTitle":"Agents","icon":"robot","href":"/core/how-it-works/feed/agents"},{"title":"Build your first feed agent","sidebarTitle":"Build your first feed agent","icon":"rocket","href":"/core/how-it-works/feed/quickstart"},{"title":"Feed Overview","sidebarTitle":"Overview","icon":"rss","href":"/core/how-it-works/feed"},{"title":"Feeds and channels","sidebarTitle":"Feeds and channels","icon":"rss","href":"/core/how-it-works/feed/feeds-and-channels"},{"group":"Triggers","icon":"bolt","pages":[{"title":"Slack triggers","sidebarTitle":"Slack triggers","icon":"slack","href":"/core/how-it-works/feed/triggers/slack-triggers"}]}]},{"title":"CLI","icon":"terminal","href":"/core/admin/cli"},{"title":"Running an Agent Loop on Sandcastles","icon":"robot","href":"/core/guides/agent-loop-sandcastles"}]},{"group":"Set Up Your Data","pages":[{"title":"The Connectors Page","icon":"down-left-and-up-right-to-center","href":"/core/datasources/the-connectors-page"},{"group":"APIs","icon":"key","pages":[{"title":"Overview","icon":"globe","href":"/core/datasources/api-connectors"},{"title":"Anthropic API Connector","icon":"robot","href":"/core/datasources/apis/anthropic"},{"title":"Apollo.io Connector","icon":"address-book","href":"/core/datasources/apis/apollo"},{"title":"Attio Connector","icon":"address-book","href":"/core/datasources/apis/attio"},{"title":"AWS Connector","icon":"aws","href":"/core/datasources/apis/aws"},{"title":"Microsoft Azure Connector","icon":"microsoft","href":"/core/datasources/apis/azure"},{"title":"Cloudflare Connector","icon":"cloudflare","href":"/core/datasources/apis/cloudflare"},{"title":"Dropbox Connector","icon":"dropbox","href":"/core/datasources/apis/dropbox"},{"title":"ElevenLabs Connector","icon":"microphone","href":"/core/datasources/apis/elevenlabs"},{"title":"Gemini Connector","icon":"sparkles","href":"/core/datasources/apis/gemini"},{"title":"GitHub Connector","icon":"github","href":"/core/datasources/apis/githubapi"},{"title":"Google Cloud Connector","icon":"cloud","href":"/core/datasources/apis/googlecloud"},{"title":"Google Drive Connector","icon":"google-drive","href":"/core/datasources/google-drive"},{"title":"Google Workspace Connector","icon":"google","href":"/core/datasources/google-workspace"},{"title":"Grain Connector","icon":"video","href":"/core/datasources/apis/grain"},{"title":"HubSpot Connector","icon":"hubspot","href":"/core/datasources/apis/hubspot"},{"title":"Jira Connector","icon":"jira","href":"/core/datasources/apis/jira"},{"title":"Linear Connector","icon":"linear","href":"/core/datasources/apis/linear"},{"title":"Mercury Connector","icon":"building-columns","href":"/core/datasources/apis/mercury"},{"title":"Microsoft 365 Connector","icon":"microsoft","href":"/core/datasources/microsoft/microsoft365"},{"title":"Notion Connector","icon":"book","href":"/core/datasources/apis/notion"},{"title":"OpenAI API Connector","icon":"openai","href":"/core/datasources/apis/openai"},{"title":"Oracle Fusion Connector","icon":"cloud","href":"/core/datasources/apis/oracle"},{"title":"PowerBI Connector","icon":"chart-simple","href":"/core/datasources/business-intel/powerbi-connector"},{"title":"Pylon Connector","icon":"headset","href":"/core/datasources/apis/pylon"},{"title":"Ramp Connector","icon":"credit-card","href":"/core/datasources/apis/ramp"},{"title":"Salesforce Connector","icon":"salesforce","href":"/core/datasources/apis/salesforce"},{"title":"SendGrid Connector","icon":"envelope","href":"/core/datasources/apis/sendgrid"},{"title":"Slack API Connector","icon":"slack","href":"/core/datasources/apis/slackapi"},{"title":"Tableau Connector","icon":"t","href":"/core/datasources/business-intel/tableau-connector"},{"title":"YouTube Analytics","icon":"youtube","href":"/core/datasources/youtube"}]},{"group":"Databases","icon":"database","pages":[{"title":"Amazon Aurora Connector","icon":"aws","href":"/core/datasources/databases/aurora"},{"title":"AWS Athena Connector","icon":"aws","href":"/core/datasources/databases/athena"},{"title":"Azure Synapse Analytics Connector","icon":"microsoft","href":"/core/datasources/databases/azure-synapse"},{"title":"BigQuery Connector","icon":"google","href":"/core/datasources/databases/bigquery"},{"title":"ClickHouse Connector","icon":"chart-line","href":"/core/datasources/databases/clickhouse"},{"title":"Databricks Connector","icon":"table","href":"/core/datasources/databases/databricks"},{"title":"Dremio Connector","icon":"database","href":"/core/datasources/databases/dremio"},{"title":"Exasol Connector","icon":"database","href":"/core/datasources/databases/exasol"},{"title":"IBM Db2","icon":"database","href":"/core/datasources/databases/db2"},{"title":"Firebolt Connector","icon":"fire","href":"/core/datasources/databases/firebolt"},{"title":"kdb+ Connector","icon":"database","href":"/core/datasources/databases/kdb"},{"title":"MongoDB Connector","icon":"database","href":"/core/datasources/databases/mongodb"},{"title":"MySQL Connector","icon":"database","href":"/core/datasources/databases/mysql"},{"title":"Network Configuration","icon":"network-wired","href":"/core/datasources/databases/network-configuration"},{"title":"Per-Member Authentication","icon":"users","href":"/core/datasources/per-member-auth"},{"title":"PostgreSQL Connector","icon":"database","href":"/core/datasources/databases/postgresql"},{"title":"Prometheus Connector","icon":"chart-line","href":"/core/datasources/databases/prometheus"},{"title":"Redshift Connector","icon":"aws","href":"/core/datasources/databases/redshift"},{"title":"SAP HANA Connector","icon":"database","href":"/core/datasources/databases/sap-hana"},{"title":"Snowflake Connector","icon":"snowflake","href":"/core/datasources/databases/snowflake"},{"title":"Supabase Connector","icon":"bolt","href":"/core/datasources/databases/supabase"},{"title":"Trino Connector","icon":"triangle","href":"/core/datasources/databases/trino"}]},{"group":"MCP Servers","icon":"plug","pages":[{"title":"MCP Reference","sidebarTitle":"Reference","icon":"book","href":"/core/how-it-works/mcp/reference"},{"title":"MCP Tools: Getting Started","sidebarTitle":"Getting Started","icon":"rocket","href":"/core/how-it-works/mcp/getting-started"}]}]},{"group":"Integrations","pages":[{"group":"Desktop App","icon":"desktop","pages":[{"title":"Desktop App","icon":"desktop","href":"/core/integrations/desktop-app"},{"title":"Desktop App Rollout","icon":"desktop-arrow-down","href":"/core/admin/desktop-app"}]},{"group":"Embedding TextQL","icon":"code","pages":[{"title":"Embedding Chat","icon":"window-restore","href":"/core/guides/embedding-ana"},{"title":"Embedding Dashboards","icon":"chart-mixed","href":"/core/guides/embedding-dashboards"},{"title":"Embedding Data Apps","icon":"window-restore","href":"/core/guides/embedding-data-apps"}]},{"title":"MS Teams","icon":"microsoft","href":"/core/integrations/teams"},{"title":"Slack","icon":"slack","href":"/core/integrations/slack"}]},{"group":"Ontology","pages":[{"group":"Build Your Ontology","icon":"hammer","pages":[{"title":"Build Your Ontology: Quickstart","sidebarTitle":"Quickstart","icon":"hammer","href":"/core/ontology/build-your-ontology"},{"title":".tql Manual","icon":"code","href":"/core/ontology/tql-reference"}]},{"title":"Skills","icon":"wand-magic-sparkles","href":"/core/ontology/skills"},{"group":"Config Files","icon":"file-code","tag":"Beta","pages":[{"title":"Config Files","sidebarTitle":"Config Files","icon":"file-code","href":"/core/ontology/config-files"},{"title":"Config File Reference","sidebarTitle":"Config File Reference","icon":"code","href":"/core/ontology/config-file-reference"}]},{"title":"Branches","sidebarTitle":"Branches","icon":"code-branch","href":"/core/ontology/branches"},{"title":"Role \u0026 Access","icon":"lock","href":"/core/ontology/ontology-rbac"},{"title":"What is Ontology?","icon":"book-open","href":"/core/ontology/overview"}]},{"group":"Get Better Results","pages":[{"title":"How Ana Thinks","description":"Understanding how Ana processes questions will help you get better answers faster and know when to give her more guidance.","icon":"brain","href":"/core/get-better-results/how-ana-thinks"},{"title":"Interactive HTML Reports","icon":"file-code","href":"/core/guides/interactive-html-reports"},{"title":"Validating and Improving Ana's Answers","sidebarTitle":"Validating Ana's Answers","description":"How to read Ana's work critically, what to do when something looks off, and how to tell whether the problem is the prompt, the context, or the data.","icon":"circle-check","href":"/core/get-better-results/validating-answers"},{"title":"Writing Better Playbook Prompts","sidebarTitle":"Constructing Better Playbooks","icon":"calendar-check","href":"/core/get-better-results/constructing-better-playbooks"},{"title":"Writing Better Prompts","icon":"pen-to-square","href":"/core/get-better-results/writing-better-prompts"}]},{"group":"Admin \u0026 Security","pages":[{"group":"Settings","icon":"gear","pages":[{"title":"Settings Overview","icon":"gear","href":"/core/admin/settings"},{"title":"API Keys","icon":"key","href":"/core/admin/api-keys"},{"title":"Workload Identity Federation","icon":"id-badge","href":"/core/admin/workload-identity"}]},{"title":"Audit Log","icon":"clipboard-list","href":"/core/admin/audit-log"},{"group":"Compliance","icon":"user-shield","pages":[{"title":"Network Configuration","sidebarTitle":"Network Configuration","icon":"shield-halved","href":"/core/admin/compliance/network-configuration"},{"title":"Network Integration Options","sidebarTitle":"Network Integration","icon":"network-wired","href":"/core/admin/compliance/network-integration"},{"title":"TextQL Deployment Types","sidebarTitle":"Deployment Types","icon":"rocket","href":"/core/admin/compliance/deployment-types"},{"title":"TextQL Inference Options","sidebarTitle":"Model Options","icon":"robot","href":"/core/admin/compliance/inference-options"},{"title":"TextQL Security and Data Governance Whitepaper","sidebarTitle":"Data Governance","icon":"gavel","href":"/core/admin/compliance/security"},{"title":"TextQL-Agent (web requests)","icon":"robot","href":"/bot"}]},{"group":"Console","icon":"desktop","pages":[{"title":"Usage","icon":"chart-column","href":"/core/admin/console/usage"},{"title":"Organization Limits","icon":"database","href":"/core/admin/limits"},{"title":"Chargeback","icon":"sitemap","href":"/core/admin/console/chargeback"}]},{"title":"Deployment Configuration","icon":"gear","href":"/core/admin/deployment-config"},{"title":"Manage Workspaces","icon":"building","href":"/core/admin/manage-workspaces"},{"title":"Model Management","icon":"microchip-ai","href":"/core/admin/models"},{"group":"Observability","icon":"shield-check","pages":[{"title":"Audit Logs and Metrics via OpenTelemetry","sidebarTitle":"OpenTelemetry Export","icon":"arrow-up-from-bracket","href":"/core/admin/observability-export"},{"title":"Observability","icon":"shield-check","href":"/core/admin/observability"},{"title":"Evaluations","icon":"clipboard-check","href":"/core/admin/evaluations"}]},{"title":"Role-Based Access Control (RBAC)","icon":"user-shield","href":"/core/admin/rbac"},{"title":"SCIM Provisioning","icon":"users-gear","href":"/core/admin/scim"},{"group":"Single Sign-On (SSO)","icon":"lock","pages":[{"title":"Okta","icon":"key","href":"/core/admin/sso-okta"},{"title":"Single Sign-On (SSO)","icon":"lock","href":"/core/admin/sso"}]},{"title":"TextQL Pricing and Consumption Table","icon":"circle-question","href":"/core/admin/pricing"},{"group":"Usage \u0026 Billing APIs","icon":"chart-bar","pages":[{"title":"Get Usage via API","icon":"chart-bar","href":"/core/admin/usage-api"},{"title":"BYOK Token Usage","icon":"chart-bar","href":"/core/admin/token-usage-api"}]}]},{"group":"FAQ","pages":[{"title":"Chat Error Messages (Advanced)","icon":"triangle-exclamation","href":"/core/how-it-works/chat-errors"},{"title":"Frequently Asked Questions","icon":"circle-question","href":"/core/how-it-works/faq"},{"title":"Get Help","sidebarTitle":"Get Help","icon":"headset","href":"/core/get-started/customer-support"},{"title":"Send Us a HAR File","sidebarTitle":"HAR Files","icon":"network-wired","href":"/core/get-started/har-file"}]},{"group":"Legacy Features","pages":[{"group":"Getting Started with Context","icon":"book","pages":[{"title":"Context Scoping","icon":"layer-group","href":"/core/archived-ontology/context-library/context-scoping"},{"title":"Dynamic Context Loading","icon":"bolt","href":"/core/archived-ontology/context-library/github-dynamic-loading"},{"title":"GitHub Integration for Context","icon":"github","href":"/core/archived-ontology/context-library/github-integration"},{"title":"Using the Context Editor","icon":"pen-to-square","href":"/core/archived-ontology/context-library/context-editor"},{"title":"Version-Controlled Context Writing","icon":"code-branch","href":"/core/archived-ontology/context-library/github-version-control"},{"title":"What is Context?","icon":"book-open","href":"/core/archived-ontology/context-library/what-is-context"}]},{"group":"Getting Started with Ontology","icon":"sitemap","pages":[{"title":"What is Ontology?","icon":"book-open","href":"/core/archived-ontology/ontology-guide/what-is-ontology"},{"title":"Building Your First Ontology","icon":"hammer","href":"/core/archived-ontology/ontology-guide/building-your-first-ontology"},{"title":"Core Concepts Explained","icon":"cubes","href":"/core/archived-ontology/ontology-guide/core-concepts"},{"title":"Quick Start Ontology","icon":"bolt","href":"/core/archived-ontology/ontology-guide/quick-start-ontology"},{"title":"Sample Conglomerate Ontology","icon":"database","href":"/core/archived-ontology/ontology-guide/sample-conglomerate-ontology"},{"title":"Why Use Ontology?","icon":"lightbulb","href":"/core/archived-ontology/ontology-guide/why-use-ontology"}]},{"group":"Ontology","icon":"diagram-project","pages":[{"title":"Ontology Overview","sidebarTitle":"Overview","icon":"chalkboard-user","href":"/core/archived-ontology/ontology-how-it-works/overview"},{"title":"BI Dashboards","icon":"chart-line","href":"/core/archived-ontology/ontology-how-it-works/dashboards"},{"title":"Files and Spreadsheets","icon":"file-csv","href":"/core/archived-ontology/ontology-how-it-works/files"},{"title":"Known Missing Features","icon":"bug","href":"/core/archived-ontology/ontology-how-it-works/missing"},{"title":"Metrics","icon":"ruler","href":"/core/archived-ontology/ontology-how-it-works/metrics"},{"title":"Object Links","icon":"code-branch","href":"/core/archived-ontology/ontology-how-it-works/links"},{"title":"Objects","icon":"cube","href":"/core/archived-ontology/ontology-how-it-works/objects"},{"title":"Queries","icon":"person-circle-question","href":"/core/archived-ontology/ontology-how-it-works/queries"},{"title":"TQL Language Reference","sidebarTitle":"TQL Reference","icon":"code","href":"/core/archived-ontology/ontology-how-it-works/tql-reference"},{"title":"Why Ontology? (Advanced)","icon":"diagram-project","href":"/core/archived-ontology/ontology-how-it-works/why"}]}]}]},{"tab":"Workshops","pages":[{"title":"Workshops","href":"/workshops"}]},{"tab":"v1 API (deprecated)","pages":[{"title":"v1 API (deprecated)","href":"/api-reference/introduction"}]},{"tab":"v2 API","pages":[{"title":"v2 API","href":"/api-reference/v2/introduction"}]},{"tab":"v3 API (SDK)","pages":[{"title":"v3 API (SDK)","href":"/api-reference/sdk/changelog"}]},{"tab":"MCP Reference","pages":[{"title":"MCP Reference","href":"/core/how-it-works/mcp/ana-as-mcp-server"}]},{"tab":"Helm Charts","pages":[{"title":"Helm Charts","href":"/helm-charts/installation"}]},{"tab":"Changelog","pages":[{"title":"Changelog","href":"/product/changelog"}]}]},"basePath":"","title":"Interactive HTML Reports - TextQL Docs","buildId":"dpl_5tKr6cUUeuVJdEZ9JAEY3h4soMJ8","deploymentId":"dpl_5tKr6cUUeuVJdEZ9JAEY3h4soMJ8","dynamics":[],"chunks":[]}