How /html-report Generates Offline SVG Dashboards from Tracker CSV
The /html-report command reads the job‑application tracker CSV with pandas, builds summary statistics and matplotlib SVG charts, and embeds them into a self‑contained HTML template to create a fully offline dashboard.
The MadsLorentzen/ai-job-search repository provides a CLI tool that converts raw application tracking data into portable, vector‑graphic reports. By combining pandas for data manipulation and matplotlib’s SVG backend, the utility produces standalone HTML files that render without external dependencies or internet access. This article walks through the exact pipeline implemented in tools/html_report.py and the supporting template files.
Overview of the Pipeline
The generation process follows a deterministic six‑stage pipeline. Each stage is implemented in the html_report module and operates entirely within the local filesystem, ensuring full offline capability.
| Stage | Action | Key Source Reference |
|---|---|---|
| Ingest | Load documents/tracker.csv into a DataFrame |
tools/html_report.py – pd.read_csv |
| Clean | Parse dates, fill missing values, derive metrics (e.g., days‑to‑response) | tools/html_report.py – pd.to_datetime |
| Aggregate | Compute weekly counts, status distributions, and median response times | tools/html_report.py – DataFrame.groupby |
| Visualise | Plot charts and save them as SVG markup | tools/html_report.py – plt.savefig(..., format='svg') |
| Templating | Inject SVG strings and statistics into an HTML skeleton | tools/html_report.py – string.Template |
| Output | Write the final file to reports/dashboard.html |
tools/html_report.py – Path.write_text |
Step‑by‑Step Implementation
Step 1: Load the Tracker CSV
The command expects a CSV file at documents/tracker.csv containing columns such as applied_on, response_on, company, and status. It uses pandas to parse the file and immediately converts date columns to datetime objects.
import pandas as pd
import pathlib
TRACKER = pathlib.Path("documents/tracker.csv")
df = pd.read_csv(TRACKER, parse_dates=["applied_on", "response_on"])
Step 2: Clean and Enrich Data
After loading, the pipeline calculates derived fields to support time‑series analysis. It computes the difference between response and application dates and extracts ISO calendar weeks for grouping.
df["days_to_response"] = (df["response_on"] - df["applied_on"]).dt.days
df["week"] = df["applied_on"].dt.isocalendar().week
Step 3: Compute Summary Statistics
Aggregations drive the dashboard’s KPIs and charts. The code groups by week for trend lines and uses value_counts() for categorical breakdowns like application status.
weekly_counts = df.groupby("week").size()
status_counts = df["status"].value_counts()
total_apps = len(df)
Step 4: Generate Inline SVG Charts
Rather than saving separate image files, the tool captures SVG markup as strings. It sets matplotlib’s backend to SVG, plots the data, and writes the output to an in‑memory buffer. This keeps the final HTML self‑contained.
import matplotlib.pyplot as plt
from io import StringIO
def plot_to_svg(series, title):
fig, ax = plt.subplots(figsize=(8, 4))
series.plot(kind="bar", ax=ax, color="steelblue")
ax.set_title(title)
buf = StringIO()
fig.savefig(buf, format="svg", bbox_inches="tight")
plt.close(fig)
return buf.getvalue()
weekly_svg = plot_to_svg(weekly_counts, "Applications per Week")
status_svg = plot_to_svg(status_counts, "Status Distribution")
Step 5: Assemble the HTML Template
The repository includes tools/html_report_template.html, a minimal HTML skeleton containing placeholders like $weekly_chart and $total_apps. The command uses Python’s string.Template to substitute the SVG strings and computed values, producing a single HTML document with inline vector graphics.
from string import Template
template_path = pathlib.Path("tools/html_report_template.html")
html_template = Template(template_path.read_text())
report_html = html_template.substitute(
weekly_chart=weekly_svg,
status_chart=status_svg,
total_apps=total_apps,
last_update=pd.Timestamp.now().strftime("%Y-%m-%d %H:%M")
)
Step 6: Write the Offline Dashboard
Finally, the tool writes the populated HTML to reports/dashboard.html. Because the SVG markup is embedded directly, opening this file in any browser requires no network requests.
output_path = pathlib.Path("reports/dashboard.html")
output_path.write_text(report_html)
CLI Usage and Command Flags
According to the source code in tools/html_report.py, the command exposes several options for customizing output:
--output <path>– Specify a custom destination file (defaults toreports/dashboard.html).--filter <status>– Restrict the analysis to rows matching a specific status value (e.g., "interviewing").--dry-run– Execute the data pipeline without writing the final file, useful for validation.
Invoke the tool from the repository root using the module execution syntax:
python -m ai_job_search html-report
Or, if the package is installed with console scripts:
ai-job-search html-report --output ./custom_report.html
Documentation for these flags resides in .claude/commands/html-report.md.
Summary
- pandas ingests and enriches the raw
documents/tracker.csvdata. - Derived metrics (weeks, days‑to‑response) enable time‑series and categorical analysis.
- matplotlib renders charts as SVG strings captured in memory via
StringIO. string.Templateinjects the SVG and statistics intotools/html_report_template.html.- The resulting
reports/dashboard.htmlis a fully offline, self‑contained dashboard with no external dependencies.
Frequently Asked Questions
Does the dashboard require an internet connection to view charts?
No. The /html-report command embeds SVG markup directly into the HTML file. Because Scalable Vector Graphics are text‑based XML, they travel with the document, eliminating the need for external image hosts or CDN links.
Can I customize the chart colors or the HTML layout?
Yes. The visual styling and HTML structure are controlled by tools/html_report_template.html and the matplotlib parameters inside tools/html_report.py. Editing the CSS within the template or adjusting the color arguments in the plotting functions will change the dashboard appearance.
What CSV columns are required for the report to work?
The pipeline expects at minimum applied_on, response_on, company, and status columns. The code uses parse_dates on the date fields, so ensure they are in a standard ISO or locale‑recognizable format. Missing optional columns are handled gracefully, but absence of applied_on will raise a KeyError during the grouping stage.
Is there a way to automate this report generation, such as in a CI pipeline?
Yes. Because the tool is a standard CLI entry point, you can schedule it via cron or GitHub Actions. Use the --dry-run flag in automation to verify data integrity before overwriting reports/dashboard.html, and commit the generated HTML artifact if you wish to publish the dashboard via GitHub Pages.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →