Overview
NYC Permit Pulse uses Vite to create an optimized production build with TypeScript compilation, tree-shaking, code splitting, and minification. The output is a set of static assets ready for deployment on any static hosting platform.Building for Production
Run the build command
From This executes:You’ll see output similar to:
package.json:8, the build script runs TypeScript compilation followed by Vite bundling:package.json
Build Process Breakdown
TypeScript Compilation
The first step (tsc -b) performs a project build using TypeScript’s build mode:
- Validates all types across
src/**/*.tsandsrc/**/*.tsxfiles - Uses strict type-checking from
tsconfig.app.json:21-26:tsconfig.app.json - Does not emit JavaScript (
noEmit: true) — Vite handles transpilation - Checks both app and config code via project references in
tsconfig.json:3-6
The
-b flag enables TypeScript’s incremental build mode, which caches compilation info in node_modules/.tmp/tsconfig.*.tsbuildinfo for faster subsequent builds.Vite Build Optimization
The second step (vite build) bundles and optimizes the application:
Code Splitting
Vite automatically splits code into chunks:- Main bundle (
index-[hash].js) — app logic, React, state management - Vendor chunks — large dependencies (OpenSeadragon, MapLibre GL)
- Dynamic imports — lazy-loaded components (if any)
Minification
All JavaScript and CSS are minified:- Terser minifies JS (removes whitespace, mangles variable names)
- Lightning CSS minifies CSS (via Tailwind)
- Gzip compression is shown in build output (handled by hosting platform)
Asset Optimization
- CSS extracted into separate files with content hashes
- Content hashing on all assets (
[hash]) for cache busting - Public files copied to
dist/root (if any exist inpublic/)
Tree Shaking
Unused code is eliminated:- ESM imports allow Vite to detect unused exports
- Dead code from dependencies is removed
- React production build removes development-only checks
Target Environment
Fromtsconfig.app.json:4-6, the app targets modern browsers:
tsconfig.app.json
async/await, optional chaining, nullish coalescing, etc.). If you need to support older browsers, configure build.target in vite.config.ts.
Static Asset Handling
Public Directory
Files inpublic/ are copied to dist/ without processing. This includes:
screenshot.jpg(shown in README)- Any other static assets that don’t need bundling
Built-in Assets
Assets imported in code are bundled with content hashes:External Assets
The app fetches these resources at runtime (not bundled):- Isometric NYC tiles — Deep-zoom DZI images from
https://isometric-nyc-tiles.cannoneyed.com - NYC Open Data — Permit and job data from
https://data.cityofnewyork.us - ADS-B Exchange — Helicopter tracking from
https://api.adsb.lol
Preview the Production Build
Vite includes a preview server to test the production build locally:dist/ folder on http://localhost:4173.
CORS Considerations
The dev server’s proxy configuration invite.config.ts:12-34 only works in development. For production:
Why CORS is an Issue
The app runs on your domain (e.g.,permitpulse.nyc) but needs to fetch data from:
data.cityofnewyork.us(no CORS headers for arbitrary origins)isometric-nyc-tiles.cannoneyed.com(same issue)api.adsb.lol(same issue)
Access-Control-Allow-Origin headers.
Solution: Server-Side Rewrites
Your hosting platform must rewrite paths on the server before they reach the browser:Platform-Specific Configuration
Environment Variables
NYC Permit Pulse does not use environment variables. All configuration is hard-coded:- API endpoints are rewritten by the hosting platform (see above)
- No API keys required — NYC Open Data is fully public
- No build-time secrets — everything is client-side
import.meta.env:
.env:
.env
Build Output Analysis
To analyze bundle size and dependencies:dist/assets/*.js.map to bundle-buddy or use vite-bundle-visualizer.
Current Bundle Size
As of the latest build:- Main JS: ~512 KB (uncompressed) / ~157 KB (gzipped)
- Main CSS: ~45 KB (uncompressed) / ~13 KB (gzipped)
react+react-dom: ~150 KBopenseadragon: ~200 KBmaplibre-gl: ~100 KB
Next Steps
- Deploy to Vercel — Configure rewrites and deploy to production
- Architecture — Learn how the system works
- Data Sources — Understand NYC Open Data integration