Frontend Integration Guide
Complete guide for integrating the React Policy Accountability Dashboards with the Python backend.
Quick Start
# 1. Generate data from Python analysis
cd /home/developer/projects/open-navigator
source .venv/bin/activate
python examples/tuscaloosa_accountability_report.py
# 2. Start frontend
cd frontend/policy-dashboards
npm install
npm start
Architecture
Python Backend (Data Generation)
↓
├── Scrape meetings (agents/scraper.py)
├── Extract decisions (extraction/decision_analyzer.py)
├── Calculate accountability metrics (extraction/accountability_dashboards.py)
├── Generate dashboards (examples/tuscaloosa_accountability_report.py)
↓
Output Files
├── output/tuscaloosa_accountability_dashboards.json (Python format)
└── frontend/policy-dashboards/src/data/dashboardData.js (React format)
↓
React Frontend (Visualization)
├── Load dashboardData.js
├── Render 4 dashboards + summary
└── Display at http://localhost:3000
Data Flow
1. Python Analysis
# examples/tuscaloosa_accountability_report.py
# Generate all accountability dashboards
dashboards = generate_all_accountability_dashboards(
jurisdiction="Tuscaloosa, AL",
meeting_documents=documents,
decisions=all_decisions,
budget_items=all_budget_items
)
# Export for frontend (automatically called)
export_for_frontend(dashboards)
2. JavaScript Data Format
The export function converts Python dataclasses to JavaScript modules:
Python:
@dataclass
class RhetoricGapMetrics:
sentiment_density: float = 92.0
budget_change_dollars: float = -120000
JavaScript:
export const rhetoricGapData = {
sentimentScore: 92,
budgetDelta: -120000,
// ... more fields
};
3. React Components
// src/components/WordsVsDollars.jsx
import { rhetoricGapData as d } from '../data/dashboardData';
export default function WordsVsDollars() {
return (
<MetricCard
value={`${d.sentimentScore}%`}
label="Positive sentiment"
/>
);
}
Component Structure
frontend/policy-dashboards/src/
├── components/
│ ├── shared/ # Reusable UI components
│ │ ├── BarMeter.jsx # Horizontal bar charts
│ │ ├── MetricCard.jsx # Key metric display
│ │ ├── Compare.jsx # 4-column benchmark comparison
│ │ └── InsightBox.jsx # Summary/logic boxes
│ ├── Summary.jsx # Summary dashboard (tab 0)
│ ├── WordsVsDollars.jsx # Dashboard 1: Rhetoric Gap
│ ├── EndlessStudyLoop.jsx # Dashboard 2: Deferral Pattern
│ ├── WhereMoneyWent.jsx # Dashboard 3: Displacement Matrix
│ └── WhoIsInCharge.jsx # Dashboard 4: Influence Radar
├── data/
│ └── dashboardData.js # ⚠️ AUTO-GENERATED FROM PYTHON
├── App.jsx # Main app shell with tabs
└── index.js # React entry point
Customization
Change Dashboard Titles
Edit src/App.jsx:
const tabs = [
{ id: 0, label: 'Summary', component: Summary },
{ id: 1, label: 'Your Custom Title', component: WordsVsDollars },
// ...
];
Update Benchmark Data
Currently benchmarks use placeholder values. To add real data:
Option 1: Update Python Export
# In examples/tuscaloosa_accountability_report.py
def calculate_real_benchmarks(jurisdiction):
"""Query NCES data for real benchmarks."""
# Query NCES Common Core of Data
republican_districts = nces_api.query(party="R")
democratic_districts = nces_api.query(party="D")
return {
"republicanAvg": np.mean([d.per_student for d in republican_districts]),
"democraticAvg": np.mean([d.per_student for d in democratic_districts]),
# ...
}
# In export_for_frontend()
benchmarks = calculate_real_benchmarks(jurisdiction)
Option 2: Update JavaScript Directly
// src/data/dashboardData.js
benchmarks: {
thisDistrict: { perStudent: 41, label: "This District" },
republicanAvg: { perStudent: 74, label: "Republican Districts" },
// Update these values ↑
}
Add New Metrics
1. Python Analysis
# extraction/accountability_dashboards.py
@dataclass
class RhetoricGapMetrics:
new_metric: float # Add field
2. Python Export
# examples/tuscaloosa_accountability_report.py
js_content += f"""
newMetric: {gap.new_metric},
"""
3. React Component
// src/components/WordsVsDollars.jsx
<MetricCard
value={d.newMetric}
label="New Metric Description"
/>
Change Colors
// In any component
const colors = {
positive: "#1D9E75", // Green - change this
negative: "#D85A30", // Red/orange - change this
neutral: "#222" // Dark gray
};
Deployment
Option 1: Static Site
cd frontend/policy-dashboards
# Build for production
npm run build
# Serve the build folder
# Upload build/* to your web server
Option 2: GitHub Pages
# Install gh-pages
npm install --save-dev gh-pages
# Add to package.json:
{
"homepage": "https://yourusername.github.io/oral-health-policy-pulse",
"scripts": {
"predeploy": "npm run build",
"deploy": "gh-pages -d build"
}
}
# Deploy
npm run deploy
Option 3: Netlify/Vercel
- Connect repository
- Set build command:
npm run build - Set publish directory:
build - Deploy
Option 4: Integrate with Python API
# api/app.py (FastAPI example)
from fastapi.staticfiles import StaticFiles
app.mount(
"/dashboards",
StaticFiles(directory="frontend/policy-dashboards/build", html=True),
name="dashboards"
)
Access at: http://localhost:8000/dashboards
Workflow
Regular Updates
# 1. Scrape new data
python main.py scrape --state AL --municipality Tuscaloosa \
--url https://tuscaloosaal.suiteonemedia.com \
--platform suiteonemedia --max-events 0
# 2. Run accountability analysis (auto-exports to frontend)
python examples/tuscaloosa_accountability_report.py
# 3. Frontend auto-refreshes if dev server is running
# OR rebuild for production:
cd frontend/policy-dashboards && npm run build
Data Update Frequency
- Monthly: Run analysis after each board meeting
- Quarterly: Full benchmark recalculation
- Annual: Major methodology updates
Advanced Features
PDF Export
npm install html2canvas jspdf
// src/App.jsx
import html2canvas from 'html2canvas';
import jsPDF from 'jspdf';
function downloadPDF() {
const element = document.getElementById('dashboard-container');
html2canvas(element).then(canvas => {
const pdf = new jsPDF();
pdf.addImage(canvas.toDataURL('image/png'), 'PNG', 0, 0);
pdf.save('tuscaloosa-accountability.pdf');
});
}
// Add button:
<button onClick={downloadPDF}>Download PDF</button>
Presentation Mode
Stack all dashboards for scrollable handout:
// src/App.jsx
const searchParams = new URLSearchParams(window.location.search);
const presentMode = searchParams.get('mode') === 'present';
// Render differently based on mode
Visit: http://localhost:3000?mode=present
Real-Time API Integration
// src/App.jsx
import { useState, useEffect } from 'react';
function App() {
const [data, setData] = useState(null);
useEffect(() => {
fetch('/api/accountability/latest')
.then(res => res.json())
.then(data => setData(data));
}, []);
// ...
}
Troubleshooting
Issue: Data Not Updating
Solution:
# Verify Python export ran
ls -la frontend/policy-dashboards/src/data/dashboardData.js
# Check file timestamp
stat frontend/policy-dashboards/src/data/dashboardData.js
# Restart dev server
cd frontend/policy-dashboards
npm start
Issue: Build Errors
Solution:
# Clear cache
rm -rf node_modules package-lock.json
# Reinstall
npm install
# Try again
npm start
Issue: Wrong Data Showing
Solution:
# Check which data file React is loading
grep -r "dashboardData" frontend/policy-dashboards/src/
# Verify export path in Python
grep "export_for_frontend" examples/tuscaloosa_accountability_report.py
Issue: Benchmarks Are Placeholders
Expected - Benchmark data currently uses illustrative values.
To Fix:
- Add NCES data query to Python analysis
- Calculate per-student averages by party affiliation
- Update
export_for_frontend()function
See: "Update Benchmark Data" section above
Testing
Manual Testing Checklist
- Python analysis runs without errors
-
dashboardData.jsfile is generated - File timestamp is recent
- React dev server starts
- All 5 tabs load correctly
- Data matches Python output
- Benchmarks display (even if placeholder)
- "Ask them" boxes show correct questions
Automated Testing
cd frontend/policy-dashboards
# Run tests
npm test
# Coverage report
npm test -- --coverage
Resources
- React Docs: https://react.dev/
- Create React App: https://create-react-app.dev/
- Python Backend:
extraction/accountability_dashboards.py - Strategy Guide:
docs/ACCOUNTABILITY_DASHBOARD_STRATEGY.md - NCES Data: https://nces.ed.gov/ccd/
Support
For issues:
- Check this guide
- Review
frontend/policy-dashboards/README.md - Check Python logs:
logs/ - Open GitHub issue
Integration Complete ✅ Python analysis → JavaScript export → React visualization