Software architecture
Written by Elena David, SEO, ORM, and AI Visibility Consultant.
Reputation Monitor uses a small pipeline architecture shared by Streamlit and the CLI. Data moves from CSV or supported public HTML into validated records, through current metrics and optional snapshot comparison, and into on-screen or downloadable output.
Component responsibilities
| Component | Public responsibility | Principal objects or functions |
|---|---|---|
cli.py |
Parse arguments, handle expected top-level errors, coordinate the run, and print results. | build_parser(), run(), main() |
dashboard.py |
Accept uploads or a URL, display metrics and messages, and provide downloads. | load_uploaded_csv(), main() |
loader.py |
Validate CSV streams or normalized rows, convert values, and collect row-level issues. | Review, ValidationIssue, LoadResult, load_reviews(), load_reviews_stream() |
analyzer.py |
Compare identifiers and apply the numerical rating rule. | AnalysisResult, find_new_reviews(), find_low_rating_reviews(), analyze_reviews() |
workflow.py |
Calculate current metrics and run comparison only when a previous snapshot exists. | MonitoringRun, run_monitoring() |
web_importer.py |
Enforce URL/network limits, detect JSON-LD, Microdata, CSS-selector, or article.review records, and normalize them. |
SelectorConfig, WebsiteImportResult, validate_public_url(), fetch_reviews(), parse_reviews_html() |
reporter.py |
Serialize selected alerts to CSV and render a safe standalone HTML report. | render_alerts_csv(), render_html_report(), write functions |
__init__.py provides __version__ = "1.0.0". pyproject.toml maps the reputation-monitor executable to reputation_monitor.cli:main; streamlit_app.py invokes the dashboard.
Data flow diagram
flowchart LR
A[Optional previous CSV] --> L1[loader]
B[Current CSV] --> L2[loader]
W[Authorized public HTML] --> I[web_importer]
I --> C
L1 --> P[Previous LoadResult]
L2 --> C[Current LoadResult]
P --> N[analyzer.analyze_reviews]
C --> N
N --> R[MonitoringRun]
R --> CSV[reporter.write_alerts_csv]
R --> HTML[reporter.write_html_report]
P --> HTML
C --> HTML
CSV --> O1[alerts.csv]
HTML --> O2[monitoring_report.html]
P --> T[CLI terminal summary]
C --> T
R --> T
Accessible text equivalent
- The loader validates uploaded or file-based CSV rows. The importer detects a supported website format, normalizes extracted fields into the same row schema, and returns the format, records, issues, and identifier notices for preview.
- The workflow always calculates current count, average rating, and rating distribution.
- When a previous snapshot exists, the analyzer returns new reviews and threshold-qualified new alerts. Without one, comparison fields remain unavailable.
- The dashboard renders metrics and provides in-memory downloads; the CLI writes files and prints counts.
- Reporters escape dynamic HTML text and serialize alert rows with threshold-consistent labels.
Core data structures
The three domain result types are frozen dataclasses:
Review: one validated input record;ValidationIssue: a CSV row number and message;LoadResult: valid reviews plus issues;AnalysisResult: three categorized review lists.MonitoringRun: current inputs, optional previous inputs and analysis, threshold, average, and distribution.
Frozen dataclasses prevent reassignment of their fields after creation. The lists inside result objects remain mutable, but the application does not modify them after construction.
Failure boundaries
Structural loading problems—such as a missing file, permission failure, invalid UTF-8, or missing columns—stop the workflow before analysis. Invalid individual rows remain inside the LoadResult.issues list and do not stop other valid rows.
Report generation starts only after required inputs load. The CSV is written before the HTML report in CLI mode. If HTML writing fails after CSV writing succeeds, the CLI returns status 1 but the CSV may remain on disk. Version 1.0 does not provide transactional rollback.
Design consequences
The separation makes each stage directly testable. The analyzer does not know about input formats, and the reporter does not perform matching. Valid records are held in memory. Streamlit session state can retain a website import during the current app session, but no database or telemetry is used.
For code-level explanations, continue to Python implementation explained. For schemas, use the input and output data reference.