open-navigator / docs /FRONTEND_INTEGRATION_GUIDE.md
jcbowyer's picture
Deploy: Consolidated gold tables, fixed nginx docs routing
896453f verified

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/open-navigator",
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build"
  }
}

# Deploy
npm run deploy

Option 3: Netlify/Vercel

  1. Connect repository
  2. Set build command: npm run build
  3. Set publish directory: build
  4. 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:

  1. Add NCES data query to Python analysis
  2. Calculate per-student averages by party affiliation
  3. Update export_for_frontend() function

See: "Update Benchmark Data" section above

Testing

Manual Testing Checklist

  • Python analysis runs without errors
  • dashboardData.js file 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

Support

For issues:

  1. Check this guide
  2. Review frontend/policy-dashboards/README.md
  3. Check Python logs: logs/
  4. Open GitHub issue

Integration Complete βœ… Python analysis β†’ JavaScript export β†’ React visualization