When I joined Ninja Van in 2015, the operations dashboard was a server-rendered monolith. Every UI change required a full backend deployment. Static assets were served from the origin server, adding latency across the countries we operate in Southeast Asia. And there was no staging environment to catch issues before production.
I led the modernization effort: migrating to an AngularJS single-page application with Material Design, setting up a Grunt + Webpack build pipeline, and hosting the static frontend on S3 behind CloudFront CDN. This decoupled frontend releases from the backend, cut deployment costs, and established a multi-environment pipeline (dev, qa, sandbox, prod) that became the foundation for other teams to build on.
The dashboard was jQuery with inline styles on top of downloaded template files — no component architecture and no visual consistency across the six countries. Every request funneled through a single server, and deploying a UI change meant SSH-ing into the box for a full backend redeployment.
An AngularJS SPA with a unified Material Design system replaced the jQuery spaghetti. The client talks to the backend purely via REST APIs, while static assets serve from CloudFront edge locations across six countries. An automated Grunt + Webpack pipeline deploys the frontend independently — from commit to production in minutes, with zero downtime.
Engineers push frontend changes to the Git repository. The backend remains untouched — a key advantage of the decoupled architecture.
Grunt orchestrates the build pipeline: selecting the target environment's configuration (API URLs, analytics IDs, feature flags) and invoking Webpack for asset bundling.
Webpack bundles AngularJS modules, SCSS stylesheets, and HTML templates into optimized, fingerprinted assets. Tree-shaking and minification reduce payload size for faster load times.
Built assets are uploaded to the target environment's S3 bucket (e.g. nv-ops-prod). Versioned deployments ensure instant rollback capability.
A cache invalidation is issued to CloudFront, pushing new assets to edge locations across Singapore, Malaysia, Indonesia, Thailand, Vietnam, and the Philippines.
Within seconds, the updated dashboard is served from the nearest edge location. No server restart, no downtime, no backend coordination required.
Each environment has its own S3 bucket, CloudFront distribution, and API configuration. Changes promote through the pipeline before reaching production.
nv-ops-dev
ops-dev.ninjavan.co
nv-ops-qa
ops-qa.ninjavan.co
nv-ops-sbox
ops-sbox.ninjavan.co
nv-ops-prod
ops.ninjavan.co
Hosting Cost Reduction
Faster Deployments
Four isolated environments (dev, qa, sandbox, prod) each with dedicated S3 buckets, CloudFront distributions, and per-env configuration for API URLs, feature flags, and analytics IDs.
Static SPA served from CloudFront edge locations across Southeast Asia, reducing time-to-first-byte from hundreds of milliseconds to under 50ms for operators in all six countries.
Frontend ships independently of the backend on its own release cycle. UI changes go from commit to production in minutes, without server restarts or backend coordination.
Introduced Angular Material components as the standard UI framework, bringing visual consistency across six country-specific dashboards and accelerating feature development.