# Mukesh Bishnoi > Frontend Engineer specialising in React.js, Next.js, TypeScript, Node.js and AWS. Founding Engineer at Foosh AI, building a scalable AI workflow platform. Previously Software Engineer at Unolo and Step Security, and open source developer at Coasts.dev (YC '25), Nightwatch.js and Empirical. Founding Engineer based in Pune, India. Website: https://www.mukeshbishnoi.com Founding Engineer building AI-powered products end-to-end. From React dashboards to LLM agents, I ship fast and break nothing. ## Contact and Profiles - Email: mukeshb.work@gmail.com - GitHub: https://github.com/mukeshblackhat - LinkedIn: https://www.linkedin.com/in/mukesh-bishnoi/ - X: https://x.com/01Mukesh29 - Résumé (PDF): https://www.mukeshbishnoi.com/resume.pdf These profiles all belong to Mukesh Bishnoi. The GitHub account mukeshblackhat is the source of the open source work and personal projects listed below; the public contribution history is on that profile. ## Work Experience ### Foosh AI — Founding Engineer April 2025 – Present · Remote · https://foosh.ai Building end-to-end AI-powered products as the founding engineer. Architecting full-stack solutions using Next.js and TypeScript, integrating LLM agents and AI pipelines to solve complex business problems from ideation to production. - Architected a scalable AI workflow platform using React Flow, TypeScript, React Query, and AWS Step Functions with Lambda orchestration, enabling users to visually compose and execute workflows across 10+ AI models for image and video generation while supporting robust state management and asynchronous API execution. - Engineered a high-performance media library handling thousands of images and videos by implementing CDN delivery, multi-layer caching, lazy loading, virtualization, and paginated fetching, reducing initial load time by 60%+ and significantly improving rendering performance for large datasets. - Optimized backend performance by restructuring AWS resource usage (Lambda, Step Functions, S3) and streamlining API orchestration across multiple third-party AI platforms, reducing execution latency and improving reliability of asynchronous workflow processing at scale. Technologies: React Flow, TypeScript, React Query, AWS Step Functions, AWS Lambda, Amazon S3, Next.js, CDN ### Unolo — Software Engineer Nov 2023 – April 2025 · Remote · https://unolo.com Built internal dashboards to track company performance and sales metrics. Optimized frontend performance through virtualization techniques and led a major initiative to create customizable client-facing dashboards, improving user experience across the platform. - Built an internal analytics dashboard surfacing at-risk customer signals, driving a 50% reduction in churn and significantly strengthening annual revenue retention. - Optimized website rendering and data handling to improve performance by 40% while scaling map capacity from 4,000 to 40,000+ points, boosting user engagement by 25%. - Led frontend development using Next.js, TypeScript, and MUI to deliver key product features, driving a 30% increase in adoption among enterprise clients including Flipkart, Adani, and Tata. Technologies: Next.js, TypeScript, Material-UI, React ### Step Security — Software Engineer August 2023 – Nov 2023 · Remote · https://www.stepsecurity.io/ Led migration of the product from React to Next.js, significantly improving performance and SEO. Set up the deployment pipeline on AWS and optimized the application for faster load times and better search engine visibility. - Migrated codebase from React.js to Next.js, reducing page load times by 40% and increasing SEO rankings by 25%. - Optimized AWS deployment, cutting infrastructure costs by 30% while maintaining 99.9% uptime. - Contributed to product growth, reaching over 3,500 open-source repositories and securing partnerships with Google, Microsoft, Node.js, and Datadog. Technologies: React.js, Next.js, AWS ## Open Source ### coasts.dev — Coasts (YC'25) March 2026 · https://coasts.dev Refactored core modules of coasts.dev (YC'25), reducing code complexity by breaking monolithic logic into small, reusable, and independently testable functions, improving codebase maintainability and test coverage. - Refactored core modules of coasts.dev (YC'25), reducing code complexity by breaking monolithic logic into small, reusable, and independently testable functions. - Improved codebase maintainability and test coverage. Impact: Improved codebase maintainability and test coverage ### Nightwatch.js — BrowserStack April 2024 · https://nightwatchjs.org Contributed features to Nightwatch.js, an open-source test automation framework. - Contributed features to Nightwatch.js, an open-source test automation framework. ### Empirical-Run CLI — Empirical May 2023 · https://www.empirical.run/ Enhanced the Empirical-Run CLI, streamlining configuration and setup for AI prompt testing workflows and reducing setup time by 30%. - Enhanced the Empirical-Run CLI, streamlining configuration and setup for AI prompt testing workflows. - Reduced setup time by 30%. Impact: 30% reduction in setup time ### Stakwork & Sphinx — Stakwork Dec 2023 · https://stakwork.com Resolved 3 critical bugs in the LeetCode Helper Chrome Extension, improving stability for 20,000+ users and increasing user satisfaction by 25%. - Resolved 3 critical bugs in the LeetCode Helper Chrome Extension. - Improved stability for 20,000+ users and increased user satisfaction by 25%. - Feature enhancement and bug fixing. Impact: Stability for 20,000+ users, 25% higher satisfaction ## GitHub Activity Public contribution history: https://github.com/mukeshblackhat The site renders a contribution calendar for mukeshblackhat on the home page. It is drawn client-side from GitHub's own data, so the counts are not in this file — read them from the GitHub profile itself, which is the authoritative source. ## Skills **Frontend:** React.js, Next.js, TypeScript, JavaScript, React Flow, React Query, Redux Toolkit, Zustand, Redux, Material UI, Tailwind CSS, Styled-Components, SCSS, SASS, Bootstrap, HTML5, CSS3 **Backend:** Node.js, Express.js, Python, FastAPI, MongoDB, RESTful APIs, C++ **DevOps & Tools:** AWS, AWS Lambda, AWS Step Functions, AWS DynamoDB, Vercel, Railway, Heroku, Git, GitHub, Performance Optimization, Agile Methodologies, Figma, VS Code, Chrome Web Store ## Projects ### Video Editor AI (2025) AI-powered video background replacement pipeline using Meta's SAM 2 model. Automatically segments subjects and replaces backgrounds in real-time video streams. Technologies: Python, SAM 2, OpenCV, ffmpeg, MatAnyone Source: https://github.com/mukeshblackhat/video-editor ### Browser Bridge MCP (2025) MCP server that bridges Claude Code with browser DevTools for real-time debugging. Enables AI-assisted development by connecting Claude directly to your browser. Technologies: JavaScript, Node.js, MCP, WebSocket, Chrome DevTools Source: https://github.com/mukeshblackhat/browser-bridge-mcp ### PR Analyser (2024) Automated pull request analysis tool that reviews code changes, identifies potential issues, and provides actionable feedback for better code quality. Technologies: JavaScript, Node.js, GitHub API ### Extension Creator CLI (2024) CLI tool to scaffold and generate browser extensions quickly. Streamlines the development workflow for building Chrome and Firefox extensions. Technologies: JavaScript, Node.js, CLI ## Education ### Army Institute of Technology (AIT) Pune, India · Oct 2020 – Jul 2024 ## Achievements - **PMSS Scholarship Holder** (2020-2024) — PMSS Scholarship Holder (2020-2024), awarded to top 1% of engineering students. - **Technical Head, Open Source Software Club** — Technical Head at Open Source Software Club, AIT Pune, leading 20+ successful projects. - **Technical Writing** — Published 15+ technical articles on Medium, garnering 50,000+ views. - **Information Security and Digital Forensics (ISDF)** — Active member of Information Security and Digital Forensics (ISDF), contributing to 3 major security projects. - **Freelance Web Development** — Completed 10+ freelance web development projects with 100% client satisfaction rate. ## FAQ **Who is Mukesh Bishnoi?** Mukesh Bishnoi is a Founding Engineer based in Pune, India. He is a Frontend Engineer specialising in React.js, Next.js, TypeScript, Node.js and AWS. Founding Engineer at Foosh AI, building a scalable AI workflow platform. Previously Software Engineer at Unolo and Step Security, and open source developer at Coasts.dev (YC '25), Nightwatch.js and Empirical. **What does Mukesh Bishnoi do now?** He is Founding Engineer at Foosh AI (April 2025 – Present). Building end-to-end AI-powered products as the founding engineer. Architecting full-stack solutions using Next.js and TypeScript, integrating LLM agents and AI pipelines to solve complex business problems from ideation to production. **Where has Mukesh Bishnoi worked?** Founding Engineer at Foosh AI (April 2025 – Present), Software Engineer at Unolo (Nov 2023 – April 2025) and Software Engineer at Step Security (August 2023 – Nov 2023). **What technologies does Mukesh Bishnoi specialise in?** Frontend — React.js, Next.js, TypeScript, JavaScript, React Flow, React Query, Redux Toolkit, Zustand, Redux, Material UI, Tailwind CSS, Styled-Components, SCSS, SASS, Bootstrap, HTML5, CSS3. Backend — Node.js, Express.js, Python, FastAPI, MongoDB, RESTful APIs, C++. DevOps & Tools — AWS, AWS Lambda, AWS Step Functions, AWS DynamoDB, Vercel, Railway, Heroku, Git, GitHub, Performance Optimization, Agile Methodologies, Figma, VS Code, Chrome Web Store. **What open source has Mukesh Bishnoi contributed to?** coasts.dev (Coasts (YC'25)) in March 2026, Nightwatch.js (BrowserStack) in April 2024, Empirical-Run CLI (Empirical) in May 2023 and Stakwork & Sphinx (Stakwork) in Dec 2023. Refactored core modules of coasts.dev (YC'25), reducing code complexity by breaking monolithic logic into small, reusable, and independently testable functions, improving codebase maintainability and test coverage. Contributed features to Nightwatch.js, an open-source test automation framework. Enhanced the Empirical-Run CLI, streamlining configuration and setup for AI prompt testing workflows and reducing setup time by 30%. Resolved 3 critical bugs in the LeetCode Helper Chrome Extension, improving stability for 20,000+ users and increasing user satisfaction by 25%. **What projects has Mukesh Bishnoi built?** Video Editor AI (2025), Browser Bridge MCP (2025), PR Analyser (2024) and Extension Creator CLI (2024). Video Editor AI: AI-powered video background replacement pipeline using Meta's SAM 2 model. Automatically segments subjects and replaces backgrounds in real-time video streams. Browser Bridge MCP: MCP server that bridges Claude Code with browser DevTools for real-time debugging. Enables AI-assisted development by connecting Claude directly to your browser. PR Analyser: Automated pull request analysis tool that reviews code changes, identifies potential issues, and provides actionable feedback for better code quality. Extension Creator CLI: CLI tool to scaffold and generate browser extensions quickly. Streamlines the development workflow for building Chrome and Firefox extensions. **Where did Mukesh Bishnoi study?** Army Institute of Technology (AIT), Pune, India, Oct 2020 – Jul 2024. **How can I contact Mukesh Bishnoi?** By email at mukeshb.work@gmail.com. He is also on GitHub at https://github.com/mukeshblackhat, LinkedIn at https://www.linkedin.com/in/mukesh-bishnoi/ and X at https://x.com/01Mukesh29. **Where is Mukesh Bishnoi based?** Pune, India. His recent roles have been remote. ## Writing - [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration) — Our AI workflow canvas got laggy at 30 nodes. Splitting the React Context did not fix it, and memo did not either. This is why we moved to Zustand, why Redux lost, and why React Flow already made the decision for us. (2026-08-30) - Why use Zustand with React Flow instead of React Context? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-1-why-use-zustand-with-react-flow-instead-of-react-context - Why does a React Flow canvas get slow when you add more nodes? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-2-why-does-a-react-flow-canvas-get-slow-when-you-add-more-nodes - How do you update one node's data in React Flow without re-rendering every node? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-3-how-do-you-update-one-nodes-data-in-react-flow-without-re-rendering-every-node - Is React Context bad for state that changes often? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-4-is-react-context-bad-for-state-that-changes-often - Does splitting React Context into smaller providers fix re-render problems? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-5-does-splitting-react-context-into-smaller-providers-fix-re-render-problems - Zustand or Redux for a node editor or canvas app? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-6-zustand-or-redux-for-a-node-editor-or-canvas-app - Should editing state and execution state be in the same store? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-7-should-editing-state-and-execution-state-be-in-the-same-store - What state does React Flow keep internally, and can you read it? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-8-what-state-does-react-flow-keep-internally-and-can-you-read-it - How many nodes can React Flow handle before performance becomes a problem? → https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-9-how-many-nodes-can-react-flow-handle-before-performance-becomes-a-problem - [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience) — Building an AI workflow platform end to end. Why React Context could not keep up with React Flow, how run state moved from memory to DynamoDB to S3, why we started at five parallel rows, and what happened when an LLM started doing the QA. (2026-08-27) - How do you run a node-graph workflow on AWS? → https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-1-how-do-you-run-a-node-graph-workflow-on-aws - Why does a DynamoDB write fail on a large workflow run, and how do you fix it? → https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-2-why-does-a-dynamodb-write-fail-on-a-large-workflow-run-and-how-do-you-fix-it - Why would two parallel nodes lose each other's output in a workflow run? → https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-3-why-would-two-parallel-nodes-lose-each-others-output-in-a-workflow-run - Should you use polling or websockets for long-running AI generations? → https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-4-should-you-use-polling-or-websockets-for-long-running-ai-generations - How do you make an image gallery with thousands of AI-generated images fast? → https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-5-how-do-you-make-an-image-gallery-with-thousands-of-ai-generated-images-fast - [A Year and a Half at Unolo: Four Problems Worth Writing Down](https://www.mukeshbishnoi.com/blog/unolo-engineering-experience) — Churn caught a month early, a landing page cut from 2.5s to 0.5s, a dashboard the customer assembles themselves, and a map that went from crashing at 4,000 points to smooth at 100,000. (2026-08-24) - How do you render 100,000 points on a map without the browser freezing? → https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-1-how-do-you-render-100000-points-on-a-map-without-the-browser-freezing - Why is a map still janky after virtualizing the list of points? → https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-2-why-is-a-map-still-janky-after-virtualizing-the-list-of-points - How do you cut a landing page load time from 2.5 seconds to under a second? → https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-3-how-do-you-cut-a-landing-page-load-time-from-25-seconds-to-under-a-second ## Questions These Posts Answer **Why use Zustand with React Flow instead of React Context?** Because React Flow already stores its own graph state in Zustand. Node positions, viewport, drag state, selection and connections all live in a Zustand store inside the library. If you keep your node data in React Context as well, two systems own the same data in two different shapes and you have to write a transform and a sync layer between them. Putting your state in Zustand removes that layer: React Flow's change handler becomes an action on your own store, both shapes are updated in the same call, and components subscribe per node instead of per provider. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-1-why-use-zustand-with-react-flow-instead-of-react-context) **Why does a React Flow canvas get slow when you add more nodes?** Usually it is not React Flow, it is how the node data is subscribed to. If every custom node reads from one React Context, or from the whole nodes array, then changing one node re-renders all of them plus the sidebar and any panel reading the same value. On our AI workflow builder that showed up at around 30 to 40 nodes as sticky dragging and stuttering zoom, and profiling showed 20 to 50 re-renders for a single node being moved. The fix is granular subscriptions, so a component only re-renders when the specific slice it reads actually changes. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-2-why-does-a-react-flow-canvas-get-slow-when-you-add-more-nodes) **How do you update one node's data in React Flow without re-rendering every node?** Keep the per-node data in a Zustand store keyed by node id, and have each custom node component select only its own key. The default approach — call setNodes on the whole array to change one node's data — makes React Flow reconcile the entire array, and any node component reading that array re-renders with it. With a store, updating node 12's config or execution status touches node 12's component only; nodes 1 to 11 never subscribed to it. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-3-how-do-you-update-one-nodes-data-in-react-flow-without-re-rendering-every-node) **Is React Context bad for state that changes often?** It is the wrong tool for it. React Context has no concept of a partial subscription: any component that consumes a context re-renders whenever any value in that context changes, even if it only reads one field of it. That is fine for state that rarely changes — theme, auth, locale, feature flags — and it falls apart for state written many times a second, like a canvas being dragged. For that you need a store with selector-based subscriptions, such as Zustand, Redux with React-Redux, or Jotai. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-4-is-react-context-bad-for-state-that-changes-often) **Does splitting React Context into smaller providers fix re-render problems?** Not on its own. We tried it before switching libraries — one provider per node, with memoised consumers — and changing one node still re-rendered the other nodes and their internals. Slicing providers thinner does not change the rule that everything reading a provider re-renders when that provider's value changes, and React.memo cannot help when the value a component is subscribed to is a new object on every update. It is worth trying because it is cheap, but do not plan around it working. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-5-does-splitting-react-context-into-smaller-providers-fix-re-render-problems) **Zustand or Redux for a node editor or canvas app?** Both can solve the re-render problem, because both support selector-based subscriptions. We chose Zustand for three reasons: creating a store is a few lines with no provider or reducer wiring, selector subscriptions are the default rather than something you have to be disciplined about, and React Flow's own internal store is Zustand, so there is one state model in the app instead of two. Redux earns its boilerplate on larger apps with many teams and strict action logging; for fixing a canvas re-render storm it was a slower, heavier route to the same place. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-6-zustand-or-redux-for-a-node-editor-or-canvas-app) **Should editing state and execution state be in the same store?** Keep them separate if the user can edit while something is running. We use one Zustand store for editing — nodes, edges, positions, configs — and a second for execution — status, progress and output per node, kept fresh by polling. The reason is a product requirement: you can edit, and even delete, a node while it is still executing. With separate stores the editor drops a deleted node immediately and the execution store just ignores results for nodes that no longer exist. In one store, every polled update would be writing to the object the editor is writing to. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-7-should-editing-state-and-execution-state-be-in-the-same-store) **What state does React Flow keep internally, and can you read it?** React Flow keeps node positions, the viewport and zoom, drag state, selection and in-progress connections in an internal Zustand store. You can read it directly with its useStore hook for reactive access, or useStoreApi when you need the current value without subscribing. That is one of the practical advantages of using Zustand for your own state too: the library's state and your state are the same kind of thing, rather than one being a black box behind a Context you cannot select into. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-8-what-state-does-react-flow-keep-internally-and-can-you-read-it) **How many nodes can React Flow handle before performance becomes a problem?** There is no fixed number, because the ceiling is set by how your node components subscribe to data rather than by the library. With every node reading one React Context we felt it at 30 to 40 nodes, especially with an execution running at the same time. After moving the same graph to Zustand with per-node selectors, that lag disappeared and the 300ms position debounce we had added to hide it was deleted. Fix subscriptions first before reaching for virtualisation or node culling. Source: [Why We Use Zustand with React Flow to Manage State](https://www.mukeshbishnoi.com/blog/context-to-zustand-migration#faq-9-how-many-nodes-can-react-flow-handle-before-performance-becomes-a-problem) **How do you run a node-graph workflow on AWS?** We use one generic AWS Step Functions state machine with Lambda doing the work, rather than generating a state machine per workflow. The machine reads the graph, works out which nodes can run now, prepares each node's inputs, invokes the right Lambda, writes the output back and repeats. The graph is data; the machine that walks it never changes, so saving a new canvas does not deploy anything. Source: [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-1-how-do-you-run-a-node-graph-workflow-on-aws) **Why does a DynamoDB write fail on a large workflow run, and how do you fix it?** A DynamoDB item cannot exceed 400KB, and a run record holding every node's output passes that more easily than you would expect. The failure is abrupt — the run does not slow down, it refuses to write. The fix is to put oversized node data in S3 and keep a small pointer in the item, then make every path that reads node data resolve that pointer first, so nothing downstream needs to know where the data actually lives. Source: [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-2-why-does-a-dynamodb-write-fail-on-a-large-workflow-run-and-how-do-you-fix-it) **Why would two parallel nodes lose each other's output in a workflow run?** Because both write to the same execution record and one silently overwrites the other. Nothing errors, and the run reports success with an output missing. The fix is ordinary optimistic locking: keep a version on the record and write on the condition that the version is still what you read, re-reading and retrying if someone got there first. Source: [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-3-why-would-two-parallel-nodes-lose-each-others-output-in-a-workflow-run) **Should you use polling or websockets for long-running AI generations?** We have polled from the beginning and would again on this architecture. On Lambda, holding a socket open means paying for a function that sits doing nothing, and keeping that connection alive across a deliberately stateless system is work. Generations take thirty seconds to five minutes, so nobody can tell the difference between a socket and a poll — the model is what is slow, and a socket would not make it faster. Source: [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-4-should-you-use-polling-or-websockets-for-long-running-ai-generations) **How do you make an image gallery with thousands of AI-generated images fast?** Two ordinary fixes did it. Page the data — we fetch 20 at a time and load the next page about 1000 pixels from the bottom, so the whole workspace is never in the page. And stop sending full-size images to a grid: a CDN in front of the bucket returns a 300px thumbnail at around 50KB instead of a 4MB original the browser then shrinks. One warning — a CDN compresses whether you ask it to or not, so downloads have to bypass it or users get a compressed file they think is the original. Source: [Foosh: From One Prompt Box to Ten Thousand Rows](https://www.mukeshbishnoi.com/blog/foosh-engineering-experience#faq-5-how-do-you-make-an-image-gallery-with-thousands-of-ai-generated-images-fast) **How do you render 100,000 points on a map without the browser freezing?** Never hand the map 100,000 markers. We took a map that crashed past roughly 4,000 points to a smooth 100,000 by building a zoom-based cluster hierarchy: fully zoomed out the map is handed a single country roll-up, then state-level clusters, then district-level, and only when you are close in does it get individual points. At every zoom level the map draws a small number of things, and the points that are not legible at that zoom are never sent. Clusters, individual points and sites also live in separate layers, which is what makes the per-zoom rules expressible at all. Source: [A Year and a Half at Unolo: Four Problems Worth Writing Down](https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-1-how-do-you-render-100000-points-on-a-map-without-the-browser-freezing) **Why is a map still janky after virtualizing the list of points?** Because there were two bottlenecks stacked on each other, and virtualizing only removed one. Windowing the React components stopped the page crashing and made it faster, but zooming still dragged. The test that located the real one was to stop passing points to the map at all — the drag vanished, which proved the remaining cost was the number of markers handed to the map itself, not React. Fixing one of two stacked bottlenecks feels like progress and still feels broken; that is the signal to keep digging rather than conclude the library is just slow. Source: [A Year and a Half at Unolo: Four Problems Worth Writing Down](https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-2-why-is-a-map-still-janky-after-virtualizing-the-list-of-points) **How do you cut a landing page load time from 2.5 seconds to under a second?** Four things, and they compound rather than add. Get image sizes down and stop serving the wrong-sized image per breakpoint, which is what was causing the layout shift and the slow paint. Lazy-import the components that are not on screen at first load instead of bundling them into the initial payload. Put assets on a CDN, which matters as soon as your clients are in different regions from your origin. And tree-shake the unused CSS and JS, because a smaller file served from a nearer edge wins twice. Image and bundle work was the LCP and FCP work — they were not separate tasks. Source: [A Year and a Half at Unolo: Four Problems Worth Writing Down](https://www.mukeshbishnoi.com/blog/unolo-engineering-experience#faq-3-how-do-you-cut-a-landing-page-load-time-from-25-seconds-to-under-a-second) ## Pages - [Home](https://www.mukeshbishnoi.com) — profile, experience, open source, skills, projects - [Résumé](https://www.mukeshbishnoi.com/resume) — the same history in résumé form - [FAQ](https://www.mukeshbishnoi.com/faq) — common questions, answered - [Blog](https://www.mukeshbishnoi.com/blog) — long-form engineering write-ups - [RSS](https://www.mukeshbishnoi.com/blog/rss.xml) - [llms-full.txt](https://www.mukeshbishnoi.com/llms-full.txt) — this file plus every post in full