# 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**~~ — Done (2026-08-11). Charts 2 and 3 now fetch real posterior draws client-side via `@duckdb/duckdb-wasm` against the public Hugging Face parquet dataset. See `docs/superpowers/specs/2026-08-11-empirical-draws-wasm-design.md`. - **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