All work

Freshworks · Senior software engineer · 2021 → 2024

Freshworks Marketplace

One codebase, two very different experiences, and a quarter to move both onto Vue 3, while shipping a revamp on top of it. My first full project on the team, with our lead and an architect in my corner. This is the short version.

Role
Frontend · the Marketplace monorepo
Team
3 engineers · I did the hands-on work, our lead and an architect guided and reviewed
Status
Shipped, live
Link
freshworks.com/apps

At a glance

The problem

One monorepo powers the Marketplace in two places: a gallery inside every Freshworks product, and a public website. Vue 2 was reaching end of life, a full UI revamp was due on top, and all of it had to ship in stages. This was before LLMs, so the plan had to carry the confidence.

My part

  • The pitch and the plan. I shared early Vite experiments at Panchatantra Tales, our weekly knowledge-sharing session, and that got us trying it on the platform. Then I wrote up Vue 3 and Vite, audited our npm packages, and drew up a phased release plan with our lead and architect.
  • The POC and the migration. I ran the POC, then did the migration hands-on, engine first: the same UI on Vue 3, well before Vue 2’s end of life.
  • The revamp, page by page. I built the designer’s Figma in phases (home and listings first, then details), so a half-shipped revamp never felt odd. A few details I cared about along the way: smooth page transitions, and a fuzzy search that loads without jerks.
  • Crayons and accessibility. I checked that Freshworks’ Crayons could replace Element UI, and contributed the one missing piece: timing control for popover transitions. I also made sure the Marketplace was covered by the WCAG 2.1 AA accessibility report.

Shipped

On Vue 3 before Vue 2’s end of life, then the revamp in phases. 85 of 90 audit vulnerabilities went with the old stack, and dev servers start 8 to 10 times faster.

The revamped Freshworks Marketplace: a search bar, product filters on the left, and a grid of popular apps.

The setup

One codebase, two experiences

  • The Marketplace lives in two places: a gallery inside every Freshworks product, and a public website.
  • One monorepo powers both, so they share components and look like one product.
The catch: shared components can only speak one Vue. Move one app and the other has to follow.

Why now

The clock on Vue 2

  • Vue 3 became the default in 2022, and Vue 2 support was ending in December 2023. Staying put meant a toolset slowly going stale.
  • Vite, Pinia and Vitest were becoming the new defaults, and a UI revamp was already on the roadmap with marketing dates attached.
Vue 3 is faster, smaller, more maintainable and it’s easier to target native.— Evan You

Plan first

Six upgrades, one quarter

  • Vue 3, Nuxt 3, Vite, the Composition API, Pinia, and Crayons in place of Element UI. Each one weighed, estimated and written up for the team to review.
  • The checklist paid off early: non-critical UI could wait, and backend asks went out ahead so that work ran in parallel.

Prove it

A POC before rocking the boat

  • A thousand-plus apps live on the Marketplace, so we rebuilt just the homepage on Vue 3 first: real APIs, real store, no blockers.
  • Nuxt 3 was still a release candidate. Waiting meant keeping a Vue 2 copy of every shared component, so we took the RC instead.

Rollout

No big bang

  • Code first, UI after, one app at a time, so nothing broke in production along the way.
  • The gallery went first. By the website’s turn we knew the road, so its two phases ran in parallel.

Design call · details

Fix it upstream

  • Smooth, even under load. Page transitions on the Nuxt website, and a fuzzy search over a large catalogue: a clear loading state, results that surface without jerks, and focus that stays where you’d expect.
  • Fixed where it lived. Crayons popovers had no control over when they opened and closed, so menus on the Marketplace felt glitchy. So I added delay props to Crayons, modelled on the Element popover we’d used before. Merged in December 2022, so every team on Crayons got it.
The Crayons popover in Freshworks’ design system docs: a Premier Accounts button opens a menu to sort customers by account type and order, over the component’s code sample.
The Crayons popover, now with open and close delays. See the pull request.

The other side

Faster loops, fewer holes

  • We paid down debt on the way: a single trunk branch with tags per environment, and a Volar-based editor setup.
  • The upgrade took 85 of 90 audit vulnerabilities with it, and the dev loop got a lot quicker.
Before → after
 BeforeAfter
Gallery dev server start~8.6 s~0.8 s
Gallery build~36.7 s~9.5 s
Website dev server start~40.4 s~5 s
Packages audited24451645
Vulnerabilities905

Takeaways

What I’d carry into the next one

  • Weigh every item

    List the upgrades, then ask what each one buys you. Some can wait a release.

  • Prove it on one page

    A POC on a real page, with real APIs and store, answers what a doc can’t.

  • Ship in stages

    Code first, UI after, one app at a time. No big bang for users or the pipeline.

  • Write it down

    Document and audit each stage, so the next person starts where you stopped.

Deep dive · ~10 min read How we migrated Freshworks’ critical monorepo tackling tech debts The analysis, the POC outcomes, every stage, and the full numbers. Read the full story

Back to all work