Interactive Report Generator
by vamseeachanta
Generate interactive HTML reports with Plotly visualizations from data analysis results. Supports dashboards, charts, and professional styling.
Skill Details
Repository Files
1 file in this skill directory
name: interactive-report-generator description: Generate interactive HTML reports with Plotly visualizations from data analysis results. Supports dashboards, charts, and professional styling. version: 1.0.0 category: workspace-hub type: skill trigger: manual auto_execute: false capabilities:
- plotly_visualization
- html_report_generation
- dashboard_creation
- csv_data_integration
- responsive_design tools:
- Write
- Read
- Bash related_skills:
- data-validation-reporter
- yaml-workflow-executor
Interactive Report Generator
Create professional, interactive HTML reports with Plotly visualizations.
Quick Start
# Generate report from data
/interactive-report-generator --data results.csv --output report.html
# Create dashboard
/interactive-report-generator --type dashboard --config dashboard.yaml
# Generate from analysis results
/interactive-report-generator --source analysis_output/
When to Use
USE when:
- Creating analysis reports
- Generating data visualizations
- Building dashboards
- Presenting results to stakeholders
DON'T USE when:
- Static images are required
- PDF export is primary format
- Real-time streaming data
Prerequisites
- Python 3.9+
- plotly>=5.15.0
- pandas>=2.0.0
- Data in CSV/DataFrame format
Overview
Generates interactive HTML reports compliant with workspace-hub HTML_REPORTING_STANDARDS.md:
- Interactive plots only - No static matplotlib
- CSV data import - Relative paths
- Responsive design - Works on all devices
- Professional styling - Consistent theming
- Export options - PNG, SVG from plots
Core Templates
1. Basic Report Template
"""
ABOUTME: Interactive HTML report generator
ABOUTME: Creates Plotly-based reports from analysis data
"""
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from pathlib import Path
from datetime import datetime
from typing import Dict, List, Any, Optional
def generate_report(
data: pd.DataFrame,
output_path: Path,
title: str = "Analysis Report",
config: Optional[Dict[str, Any]] = None
) -> Path:
"""
Generate interactive HTML report from data.
Args:
data: DataFrame with analysis results
output_path: Path to save HTML report
title: Report title
config: Optional configuration dictionary
Returns:
Path to generated report
"""
config = config or {}
# Create HTML structure
html_content = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<style>
* {{
margin: 0;
padding: 0;
box-sizing: border-box;
}}
body {{
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
background-color: #f5f5f5;
color: #333;
line-height: 1.6;
}}
.report-header {{
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px;
text-align: center;
}}
.report-header h1 {{
font-size: 2.5em;
margin-bottom: 10px;
}}
.report-header .metadata {{
opacity: 0.9;
font-size: 0.9em;
}}
.container {{
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}}
.summary-cards {{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 20px;
margin: 30px 0;
}}
.card {{
background: white;
border-radius: 12px;
padding: 25px;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
text-align: center;
}}
.card .label {{
font-size: 0.85em;
color: #666;
text-transform: uppercase;
letter-spacing: 1px;
}}
.card .value {{
font-size: 2.5em;
font-weight: bold;
color: #667eea;
margin: 10px 0;
}}
.plot-container {{
background: white;
border-radius: 12px;
padding: 25px;
margin: 20px 0;
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
}}
.plot-container h2 {{
margin-bottom: 20px;
color: #333;
border-bottom: 2px solid #667eea;
padding-bottom: 10px;
}}
.footer {{
text-align: center;
padding: 30px;
color: #666;
font-size: 0.85em;
}}
@media (max-width: 768px) {{
.report-header h1 {{
font-size: 1.8em;
}}
.card .value {{
font-size: 2em;
}}
}}
</style>
</head>
<body>
<div class="report-header">
<h1>{title}</h1>
<div class="metadata">
Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} |
Records: {len(data):,}
</div>
</div>
<div class="container">
<!-- Summary Cards -->
<div class="summary-cards" id="summary-cards">
<!-- Generated by JavaScript -->
</div>
<!-- Plots -->
<div id="plots-container">
<!-- Generated dynamically -->
</div>
</div>
<div class="footer">
Generated with Interactive Report Generator | workspace-hub
</div>
</body>
</html>
"""
# Write HTML
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(html_content)
return output_path
def create_time_series_plot(
data: pd.DataFrame,
x_col: str,
y_cols: List[str],
title: str = "Time Series"
) -> go.Figure:
"""
Create interactive time series plot.
Args:
data: DataFrame with time series data
x_col: Column for x-axis (typically datetime)
y_cols: Columns for y-axis values
title: Plot title
Returns:
Plotly Figure object
"""
fig = go.Figure()
for col in y_cols:
fig.add_trace(go.Scatter(
x=data[x_col],
y=data[col],
mode='lines+markers',
name=col,
hovertemplate='%{x}<br>%{y:.2f}<extra></extra>'
))
fig.update_layout(
title=title,
xaxis_title=x_col,
yaxis_title="Value",
hovermode='x unified',
template='plotly_white',
height=500
)
return fig
def create_distribution_plot(
data: pd.DataFrame,
column: str,
title: str = "Distribution"
) -> go.Figure:
"""
Create interactive histogram/distribution plot.
Args:
data: DataFrame with data
column: Column to plot distribution
title: Plot title
Returns:
Plotly Figure object
"""
fig = px.histogram(
data,
x=column,
title=title,
template='plotly_white',
nbins=50
)
fig.update_layout(
xaxis_title=column,
yaxis_title="Count",
height=400
)
return fig
def create_correlation_heatmap(
data: pd.DataFrame,
columns: Optional[List[str]] = None,
title: str = "Correlation Matrix"
) -> go.Figure:
"""
Create interactive correlation heatmap.
Args:
data: DataFrame with numeric data
columns: Optional list of columns to include
title: Plot title
Returns:
Plotly Figure object
"""
if columns:
corr_data = data[columns].corr()
else:
corr_data = data.select_dtypes(include='number').corr()
fig = px.imshow(
corr_data,
title=title,
template='plotly_white',
color_continuous_scale='RdBu_r',
zmin=-1,
zmax=1
)
fig.update_layout(height=500)
return fig
def create_dashboard(
data: pd.DataFrame,
output_path: Path,
config: Dict[str, Any]
) -> Path:
"""
Create multi-panel dashboard.
Args:
data: DataFrame with analysis data
output_path: Path to save dashboard HTML
config: Dashboard configuration
Returns:
Path to generated dashboard
"""
# Create subplots
fig = make_subplots(
rows=2, cols=2,
subplot_titles=(
"Time Series",
"Distribution",
"Scatter Plot",
"Summary Statistics"
),
specs=[
[{"type": "scatter"}, {"type": "histogram"}],
[{"type": "scatter"}, {"type": "table"}]
]
)
# Add plots based on config
numeric_cols = data.select_dtypes(include='number').columns.tolist()
if len(numeric_cols) >= 2:
# Time series or line plot
fig.add_trace(
go.Scatter(
x=data.index,
y=data[numeric_cols[0]],
mode='lines',
name=numeric_cols[0]
),
row=1, col=1
)
# Distribution
fig.add_trace(
go.Histogram(x=data[numeric_cols[0]], name="Distribution"),
row=1, col=2
)
# Scatter
fig.add_trace(
go.Scatter(
x=data[numeric_cols[0]],
y=data[numeric_cols[1]],
mode='markers',
name="Correlation"
),
row=2, col=1
)
# Summary statistics table
stats = data.describe().reset_index()
fig.add_trace(
go.Table(
header=dict(values=list(stats.columns)),
cells=dict(values=[stats[col].round(2) for col in stats.columns])
),
row=2, col=2
)
fig.update_layout(
height=800,
showlegend=True,
title_text="Analysis Dashboard"
)
# Save
fig.write_html(output_path, include_plotlyjs='cdn')
return output_path
2. Report Generator Class
"""
ABOUTME: Full-featured report generator class
ABOUTME: Supports multiple plot types and configurations
"""
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
from pathlib import Path
from typing import Dict, List, Any, Optional
from datetime import datetime
import json
class InteractiveReportGenerator:
"""Generate interactive HTML reports with Plotly."""
def __init__(self, config: Optional[Dict[str, Any]] = None):
"""
Initialize report generator.
Args:
config: Optional configuration dictionary
"""
self.config = config or {}
self.plots: List[go.Figure] = []
self.summary_stats: Dict[str, Any] = {}
# Default styling
self.theme = self.config.get('theme', {
'primary_color': '#667eea',
'secondary_color': '#764ba2',
'background': '#f5f5f5',
'card_bg': '#ffffff',
'text_color': '#333333'
})
def add_data(self, data: pd.DataFrame, name: str = "data"):
"""Add data source to report."""
self.data = data
self.data_name = name
self._calculate_summary()
def _calculate_summary(self):
"""Calculate summary statistics."""
if hasattr(self, 'data'):
self.summary_stats = {
'total_records': len(self.data),
'columns': len(self.data.columns),
'numeric_cols': len(self.data.select_dtypes(include='number').columns),
'missing_values': self.data.isnull().sum().sum()
}
def add_time_series(
self,
x_col: str,
y_cols: List[str],
title: str = "Time Series Analysis"
):
"""Add time series plot."""
fig = go.Figure()
for col in y_cols:
fig.add_trace(go.Scatter(
x=self.data[x_col],
y=self.data[col],
mode='lines+markers',
name=col
))
fig.update_layout(
title=title,
template='plotly_white',
height=500
)
self.plots.append(('time_series', fig, title))
def add_bar_chart(
self,
x_col: str,
y_col: str,
title: str = "Bar Chart"
):
"""Add bar chart."""
fig = px.bar(
self.data,
x=x_col,
y=y_col,
title=title,
template='plotly_white'
)
self.plots.append(('bar', fig, title))
def add_scatter_plot(
self,
x_col: str,
y_col: str,
color_col: Optional[str] = None,
title: str = "Scatter Plot"
):
"""Add scatter plot."""
fig = px.scatter(
self.data,
x=x_col,
y=y_col,
color=color_col,
title=title,
template='plotly_white'
)
self.plots.append(('scatter', fig, title))
def add_histogram(
self,
column: str,
title: str = "Distribution"
):
"""Add histogram."""
fig = px.histogram(
self.data,
x=column,
title=title,
template='plotly_white'
)
self.plots.append(('histogram', fig, title))
def add_heatmap(
self,
columns: Optional[List[str]] = None,
title: str = "Correlation Heatmap"
):
"""Add correlation heatmap."""
if columns:
corr = self.data[columns].corr()
else:
corr = self.data.select_dtypes(include='number').corr()
fig = px.imshow(
corr,
title=title,
template='plotly_white',
color_continuous_scale='RdBu_r'
)
self.plots.append(('heatmap', fig, title))
def generate(
self,
output_path: Path,
title: str = "Analysis Report"
) -> Path:
"""
Generate the HTML report.
Args:
output_path: Path to save report
title: Report title
Returns:
Path to generated report
"""
# Build HTML
html_parts = [self._generate_header(title)]
html_parts.append(self._generate_summary_cards())
for plot_type, fig, plot_title in self.plots:
html_parts.append(self._wrap_plot(fig, plot_title))
html_parts.append(self._generate_footer())
# Combine and save
html_content = self._get_html_template(
title,
'\n'.join(html_parts)
)
output_path.parent.mkdir(parents=True, exist_ok=True)
output_path.write_text(html_content)
return output_path
def _get_html_template(self, title: str, body: str) -> str:
"""Get complete HTML template."""
return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{title}</title>
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<style>
{self._get_styles()}
</style>
</head>
<body>
{body}
</body>
</html>"""
def _get_styles(self) -> str:
"""Get CSS styles."""
return """
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
background: #f5f5f5;
color: #333;
}
.header {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
padding: 40px;
text-align: center;
}
.container { max-width: 1400px; margin: 0 auto; padding: 20px; }
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 20px; margin: 30px 0; }
.card { background: white; border-radius: 12px; padding: 25px; box-shadow: 0 4px 6px rgba(0,0,0,0.1); text-align: center; }
.card-value { font-size: 2.5em; font-weight: bold; color: #667eea; }
.card-label { color: #666; text-transform: uppercase; font-size: 0.85em; }
.plot-section { background: white; border-radius: 12px; padding: 25px; margin: 20px 0; box-shadow: 0 4px 6px rgba(0,0,0,0.1); }
.footer { text-align: center; padding: 30px; color: #666; }
"""
def _generate_header(self, title: str) -> str:
"""Generate header HTML."""
return f"""
<div class="header">
<h1>{title}</h1>
<p>Generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}</p>
</div>
<div class="container">
"""
def _generate_summary_cards(self) -> str:
"""Generate summary cards HTML."""
cards = ""
for key, value in self.summary_stats.items():
label = key.replace('_', ' ').title()
cards += f"""
<div class="card">
<div class="card-value">{value:,}</div>
<div class="card-label">{label}</div>
</div>
"""
return f'<div class="cards">{cards}</div>'
def _wrap_plot(self, fig: go.Figure, title: str) -> str:
"""Wrap plot in HTML container."""
plot_html = fig.to_html(full_html=False, include_plotlyjs=False)
return f"""
<div class="plot-section">
<h2>{title}</h2>
{plot_html}
</div>
"""
def _generate_footer(self) -> str:
"""Generate footer HTML."""
return """
</div>
<div class="footer">
Generated with Interactive Report Generator | workspace-hub
</div>
"""
Usage Examples
Example 1: Simple Report
import pandas as pd
from pathlib import Path
from report_generator import InteractiveReportGenerator
# Load data
df = pd.read_csv('data/analysis_results.csv')
# Create report
report = InteractiveReportGenerator()
report.add_data(df)
report.add_time_series('date', ['value1', 'value2'])
report.add_histogram('value1')
report.add_heatmap()
# Generate
output = report.generate(
Path('reports/analysis_report.html'),
title='Analysis Results'
)
print(f"Report saved: {output}")
Example 2: Dashboard Creation
# Create dashboard with multiple views
report = InteractiveReportGenerator()
report.add_data(df)
# Add various plots
report.add_time_series('timestamp', ['metric_a', 'metric_b'])
report.add_scatter_plot('x_value', 'y_value', color_col='category')
report.add_bar_chart('category', 'total')
report.add_histogram('distribution_col')
# Generate dashboard
report.generate(
Path('reports/dashboard.html'),
title='Project Dashboard'
)
Example 3: From CLI
# Generate report from command line
python -m report_generator \
--data results.csv \
--output report.html \
--title "Analysis Results" \
--plots time_series histogram heatmap
Execution Checklist
Data Preparation:
- Data loaded as DataFrame
- Column names are clean
- Date columns parsed
- Missing values handled
Report Creation:
- Add data to generator
- Select appropriate plot types
- Configure titles and labels
- Generate HTML output
Validation:
- Open report in browser
- Verify interactivity works
- Check responsive design
- Test export options
Best Practices
- Use descriptive titles - Help users understand each visualization
- Limit plots per page - 5-7 plots maximum for clarity
- Use consistent colors - Match organizational branding
- Include summary stats - Provide context for data
- Test on mobile - Verify responsive design works
Error Handling
Missing Columns
Error: Column 'value' not found in data
Check:
1. Column names in DataFrame
2. Spelling and case sensitivity
3. Data was loaded correctly
Empty Data
Error: No data to plot
Check:
1. DataFrame is not empty
2. Filters not too restrictive
3. Data loading succeeded
Related Skills
- data-validation-reporter - Data quality reports
- yaml-workflow-executor - Configuration-driven reports
References
Version History
- 1.0.0 (2026-01-14): Initial release - Plotly-based interactive HTML report generator with dashboards, multiple plot types, and responsive design
Related Skills
Xlsx
Comprehensive spreadsheet creation, editing, and analysis with support for formulas, formatting, data analysis, and visualization. When Claude needs to work with spreadsheets (.xlsx, .xlsm, .csv, .tsv, etc) for: (1) Creating new spreadsheets with formulas and formatting, (2) Reading or analyzing data, (3) Modify existing spreadsheets while preserving formulas, (4) Data analysis and visualization in spreadsheets, or (5) Recalculating formulas
Clickhouse Io
ClickHouse database patterns, query optimization, analytics, and data engineering best practices for high-performance analytical workloads.
Clickhouse Io
ClickHouse database patterns, query optimization, analytics, and data engineering best practices for high-performance analytical workloads.
Analyzing Financial Statements
This skill calculates key financial ratios and metrics from financial statement data for investment analysis
Data Storytelling
Transform data into compelling narratives using visualization, context, and persuasive structure. Use when presenting analytics to stakeholders, creating data reports, or building executive presentations.
Team Composition Analysis
This skill should be used when the user asks to "plan team structure", "determine hiring needs", "design org chart", "calculate compensation", "plan equity allocation", or requests organizational design and headcount planning for a startup.
Startup Financial Modeling
This skill should be used when the user asks to "create financial projections", "build a financial model", "forecast revenue", "calculate burn rate", "estimate runway", "model cash flow", or requests 3-5 year financial planning for a startup.
Kpi Dashboard Design
Design effective KPI dashboards with metrics selection, visualization best practices, and real-time monitoring patterns. Use when building business dashboards, selecting metrics, or designing data visualization layouts.
Dbt Transformation Patterns
Master dbt (data build tool) for analytics engineering with model organization, testing, documentation, and incremental strategies. Use when building data transformations, creating data models, or implementing analytics engineering best practices.
Startup Metrics Framework
This skill should be used when the user asks about "key startup metrics", "SaaS metrics", "CAC and LTV", "unit economics", "burn multiple", "rule of 40", "marketplace metrics", or requests guidance on tracking and optimizing business performance metrics.
