Overview
NYC Permit Pulse is deployed on Vercel at permitpulse.nyc. Vercel handles:- Static hosting for the Vite build output
- Server-side rewrites to proxy external API/tile requests
- Custom domain with automatic HTTPS
- Instant deployment on every git push
Vercel Configuration
The production rewrite rules are defined invercel.json at the project root:
vercel.json
How Rewrites Work
Browser makes a request
The app requests
/api/permits?$where=... from the same origin (e.g., https://permitpulse.nyc/api/permits?$where=...).Vercel rewrites the path
Before the request reaches the static files, Vercel’s edge network checks the
rewrites rules and transforms the URL:The
:path* syntax captures all remaining path segments and query parameters, allowing dynamic URLs like /api/permits?$where=issue_date>'2026-01-01' to pass through unchanged.Rewrite Rules Breakdown
| Source Path | Destination | Purpose |
|---|---|---|
/api/permits/:path* | https://data.cityofnewyork.us/resource/rbx6-tga4.json/:path* | DOB NOW approved work permits (Socrata ID: rbx6-tga4) |
/api/jobs/:path* | https://data.cityofnewyork.us/resource/w9ak-ipjd.json/:path* | DOB NOW job filings for NB/DM (Socrata ID: w9ak-ipjd) |
/dzi/:path* | https://isometric-nyc-tiles.cannoneyed.com/dzi/:path* | OpenSeadragon DZI descriptor + tile images |
/api/adsb/:path* | https://api.adsb.lol/v2/:path* | Live helicopter tracking data |
/map | /index.html | SPA route fallback for /map path |
/(.*) | /index.html | Catch-all SPA route fallback |
SPA Fallback
The last two rules handle client-side routing:permitpulse.nyc/map) returns index.html instead of a 404, allowing the React app to handle routing.
Deployment Process
Connect your GitHub repository
- Go to vercel.com/new
- Import your GitHub repository (e.g.,
yourusername/isometric-permits) - Vercel auto-detects the Vite framework and suggests build settings
Configure build settings
Vercel should auto-detect these settings. Verify or set manually:
- Framework Preset: Vite
- Build Command:
npm run build - Output Directory:
dist - Install Command:
npm install
package.json:6-10:package.json
Add vercel.json to your repository
Ensure
vercel.json is committed to your repo root with the rewrite rules shown above.Deploy
Click Deploy. Vercel will:
- Clone your repository
- Run
npm install - Run
npm run build(TypeScript check + Vite build) - Upload the
dist/folder to Vercel’s edge network - Apply the
vercel.jsonrewrites
https://isometric-permits-abc123.vercel.appCustom Domain Setup
To deploy on a custom domain likepermitpulse.nyc:
Add domain in Vercel
- Go to your project settings → Domains
- Click Add Domain
- Enter your domain (e.g.,
permitpulse.nyc)
Configure DNS records
Vercel will show you the required DNS records. For an apex domain (Option B: CNAME (if your registrar supports apex CNAME)For a subdomain (
permitpulse.nyc):Option A: A Record (recommended)www.permitpulse.nyc):Add both apex and www (optional)
It’s common to support both
permitpulse.nyc and www.permitpulse.nyc:- Add both domains in Vercel
- Set one as the primary (Vercel will redirect the other)
Wait for DNS propagation
DNS changes can take 5 minutes to 48 hours. Check status with:You should see the Vercel IP address (76.76.19.19) in the response.
Vercel automatically renews SSL certificates and handles HTTPS redirects. No manual configuration needed.
Environment Variables
NYC Permit Pulse does not require environment variables — all external URLs are handled viavercel.json rewrites. If you fork the project and need to add secrets:
Add environment variable in Vercel dashboard
Go to Settings → Environment Variables and add your key-value pairs:
Build Logs and Debugging
View Build Logs
- Go to your Vercel project → Deployments
- Click on a deployment
- View the Build Logs tab
npm installoutput- TypeScript compilation (
tsc -b) - Vite build output
- Any errors that caused the build to fail
Common Build Errors
TypeScript errorsnpm run build locally to catch type errors before pushing.
Missing dependencies
package.json includes all dependencies. Run npm install and commit the updated package-lock.json.
Out of memory
NODE_OPTIONS=--max_old_space_size=4096 in Vercel environment variables.
Runtime Debugging
If the build succeeds but the app doesn’t work:- Check browser console for JavaScript errors
- Check Network tab for failed API/tile requests
-
Verify rewrites are applied:
Should return 200 OK with NYC Open Data headers.
- Check Vercel logs (real-time function logs): Go to Deployments → Functions tab (shows edge function errors if any)
Continuous Deployment
Vercel automatically deploys on every git push:- Main branch → Production deployment (
permitpulse.nyc) - Other branches → Preview deployments (
isometric-permits-git-feature-branch.vercel.app) - Pull requests → Preview deployments with automatic comments in the PR
Preview Deployments
Every PR gets a unique preview URL:Skip a Deployment
To push without triggering a deployment, add[skip ci] to the commit message:
Deployment Checklist
Before deploying to production:- Run
npm run buildlocally to catch TypeScript errors - Run
npm run previewand test the production build - Verify
vercel.jsonincludes all necessary rewrites - Commit and push
vercel.jsonto the repo - Test API endpoints return valid data (check Network tab)
- Test tile images load correctly (no 404s)
- Check mobile responsiveness (DevTools device emulation)
- Verify OpenSeadragon zoom and pan work smoothly
Production URL
The official deployment is live at: https://permitpulse.nyc Source code: github.com/ziggy2socks/isometric-permitsNext Steps
- Data Sources — Understand NYC Open Data integration
- Permit Types — Learn about color coding and filtering
- API Reference — Explore core functions and types