Files
crdc-demo/HANDOFF.md
T
jared 6c8e1e8409 docs: refresh AGENTS.md, HANDOFF.md, and README with recent work
- Create AGENTS.md: comprehensive agent guide covering architecture,
  data flow, error bar convention (90% intervals), D3 usage patterns,
  null safety pitfalls, deployment checklist, and related repos
- Update HANDOFF.md: mark CORS as resolved, document chart improvements
  (Chart 5 ridgeline rewrite with synthetic draws + smooth rendering)
- Refresh README.md: accurate tech stack (D3 v7), updated file structure
  with new chart files, corrected API endpoint table
2026-08-10 17:10:35 -04:00

3.6 KiB

Handoff: Fix CORS for CRDC Arrests API Demo App

Current Status

RESOLVED: The demo app at https://pages.civilytics.org/crdc-demo/ is fully functional. All charts render correctly and there are no blocking errors in the console.

The original CORS issue was resolved by deploying updated plumber.R with CORS headers to the running API server (crdc-api.civilytics.org).

Historical Context (resolved)

Original Problem

The demo app loaded HTML correctly but showed a blank white screen because browser-based fetch requests to the CRDC API were blocked by CORS (the API didn't send Access-Control-Allow-Origin headers).

Resolution

The CORS issue was fixed at the API source:

  • Updated crdc-arrests/api/plumber.R with CORS headers (Access-Control-Allow-Origin: *) in the existing cacheHeaders filter and OPTIONS preflight handling.
  • Deployed to the running API server so it took effect at https://crdc-api.civilytics.org/.

The app now calls the public read-only API directly from the browser without requiring a proxy.

Current Work (completed)

Since resolving CORS, additional improvements were made:

What's Done

  1. ✅ CORS resolved: API server (crdc-api.civilytics.org) now sends Access-Control-Allow-Origin: * headers — deployed via updated plumber.R
  2. ✅ App code: React + Vite app fully built with 6 charts, Civilytics visual identity (wordmark from civilyticsR package), loading animation, district search
  3. ✅ Git Pages deployment: Gitea Actions workflow (.gitea/workflows/pages.yml) successfully builds dist/ and deploys to a pages branch on Civilytics/crdc-demo repo at gitea.civilytics.org
  4. ✅ Chart 5 rewrite: Replaced interval-proxy ridgeline with proper D3 density ridges (RateDensityRidgeline.jsx) using synthetic draws from normal approximation of posterior intervals, smooth curveBasis rendering, and diamond markers for observed rates
  5. ✅ Chart 4 enhancement: Added D3-based quadrant visualization in ModelDrawsComparison.jsx showing error bars with proper null safety

Remaining Proxy Code (optional)

The CORS proxy fallback code (proxy.php, nginx reverse proxy config, VITE_PROXY_URL support) was added but is not needed since the API now sends CORS headers. It remains as a safety net for environments where the API can't be modified.

What Needs to Be Done Next

Future Enhancements

  • Raw posterior draws: The /api/v1/draws?... endpoint returns Parquet shard URLs for bulk processing, not browser-friendly draw data. If actual posterior distributions are needed in Chart 5 (instead of synthetic normal approximation), a new API endpoint would be required.
  • Automated testing: No test suite exists; consider adding basic tests for chart rendering and API error handling.

Key Files

  • API fix: /home/jared/Nextcloud/Civilytics/Code/Civilytics/crdc-arrests/api/plumber.R (CORS headers added to cacheHeaders filter)
  • App code: /home/jared/Nextcloud/Civilytics/Code/Civilytics/crdc-demo/src/ — fully built, deployed to pages branch
  • Proxy fallback: proxy.php, nginx.conf with reverse proxy config

Verification Steps After Fix

  1. Visit https://pages.civilytics.org/crdc-demo/
  2. Select a state → search for "Denver" → should see district results
  3. Click a district → loading animation runs, then 6 charts appear
  4. Check browser dev tools → no CORS errors in console

Git Status

  • crdc-arrests repo: plumber.R modified (CORS headers added), not yet committed/pushed to API deployment
  • crdc-demo repo: All fixes pushed and deployed via Gitea Actions, awaiting CORS resolution at API or server level