Scaling to 100K MAU
Optimizing two Vue.js and Nuxt websites at Business-in-a-Box
I optimized two Business-in-a-Box websites built with Vue.js and Nuxt, growing monthly active users from 20K to 100K. By implementing code splitting, webpack optimization, and improving Core Web Vitals1, I reduced load times by 40%, improved search rankings, and drove measurable revenue growth.
The performance regression
When I joined Business-in-a-Box as a full-stack developer, the two production websites I inherited were struggling. Technical debt had accumulated, and it showed in the metrics: Core Web Vitals were in poor shape and user engagement was declining.
I ran my first Lighthouse audit and the results were rough. Average performance scores hovered around 55, with some pages dipping as low as 40. First Contentful Paint2 was taking over 4 seconds and Time to First Byte3 was around 1.8 seconds. When I ran the build with the --analyze flag, I discovered JavaScript chunks exceeding 1MB.
Environment and constraints
The tech stack was Vue.js 2, Nuxt.js (running in both SSR and SSG modes), Webpack 4, and Node.js. I was working with two sites: the main business-in-a-box.com site (server-side rendered) and the templates subdirectory (statically generated with over 10,000 pages).
With less than a year of development experience, I had to learn Vue and Nuxt on the fly while simultaneously diagnosing performance issues. The statically generated templates site presented a different challenge entirely. Static generation meant I couldn't optimize at runtime. Every improvement had to happen at build time, deep in Nuxt's compilation pipeline and Webpack configuration.
Diagnosis and remediation
I needed a systematic approach: learn the framework, measure everything, form hypotheses, make targeted fixes, validate with data, and repeat.
Establishing baseline knowledge
I went through the Vue and Nuxt documentation thoroughly, supplemented by Maximilian Schwarzmuller's Vue.js course. This covered directives, components, the reactivity system, and Vuex state management. I built practice projects to internalize Vue's component lifecycle and inter-component communication patterns.
Establishing performance baselines
Without measurement infrastructure in place, I had no way to prove whether changes were actually helping or making things worse.
I set up a testing workflow using Chrome DevTools Performance panel, Lighthouse, and PageSpeed Insights. During development, I ran Lighthouse in Chrome for quick lab results. Once things looked promising, I deployed to staging and ran field tests through PageSpeed Insights.
Webpack bundle optimization
I ran webpack-bundle-analyzer4 to visualize the bundle composition. The problem became immediately clear: vendor chunks over 600KB, zero code splitting, and duplicate dependencies across bundles.
I configured chunk size limits, set up Terser for aggressive dead code elimination, implemented content hashing for cache invalidation, tuned SplitChunksPlugin for optimal vendor bundling, and added dynamic imports for route-based code splitting.
Root cause analysis
Even after the bundle optimizations, something wasn't right. I checked the network waterfall and found the real culprit: every template page was synchronously loading all modules, regardless of whether the page actually needed them.
I built a custom Nuxt plugin that hooked into the static generation process, implementing dynamic module resolution with lazy loading. During the build, routes would only pull in the modules they actually referenced rather than bundling everything upfront.
Results
Performance improvements
The transformation was significant. Lighthouse scores went from predominantly red and yellow to mostly green. Key metrics like Largest Contentful Paint5, Time to Interactive6, and First Contentful Paint all saw major improvements. Bundle size was substantially reduced and build time dropped from 40 minutes to 10 minutes.
Business impact
Monthly Active Users grew from 20K to 100K over 6 months, a 400% increase. This was primarily driven by the performance optimizations, though implementing the i18n module for 5 additional languages also contributed. Search rankings for popular document templates improved from position 10+ to top 5.
Revenue impact
With a $215 annual subscription model and 5x growth in MAU, even modest conversion improvements translate to significant additional annual revenue.
Lessons learned
This project demonstrated how directly technical performance connects to business outcomes. The experience reinforced the value of a systematic approach: identify bottlenecks through data, make targeted fixes, measure results, and iterate.
Performance optimization is not a nice-to-have. Faster load times led directly to 400% user growth and measurable revenue increases.
- Core Web Vitals — Google's unified guidance on quality signals for delivering a great user experience on the web.
- First Contentful Paint (FCP) — Measures the time from page load to when the first piece of content renders on screen.
- Time to First Byte (TTFB) — Measures the time between the request for a resource and when the first byte of a response begins to arrive.
- webpack-bundle-analyzer — A webpack plugin and CLI utility that visualizes the size of output files with an interactive treemap.
- Largest Contentful Paint (LCP) — Measures the time from page load to when the largest content element becomes visible in the viewport.
- Time to Interactive (TTI) — Measures the time from page load to when the page becomes fully interactive and can reliably respond to user input.