Helping maintain the frontend of a clothing e-commerce platform in USA

Role: Senior frontend developerYear: 2025
Jiffy Shirts e-commerce storefront
Client
Jiffy
Country
United States of America
Services provided
Frontend development
Industry
E-commerce
Tech stack
TypeScript, Vue, Ruby on Rails, SCSS, Webpack

About the product

Jiffy is a U.S. e-commerce platform for blank apparel and custom printing. The catalog covers DTF transfers, stickers, and on-demand printed goods for creators, small businesses, and enterprise clients. Customers browse, customize, and check out with prices and delivery timelines shown up front.

I worked on the Rails storefront frontend: catalogs, customizations, cart, checkout-adjacent flows, accounts, and print workflows. It is a live production site, and the native apps load the same pages in a WebView.

Jiffy DTF design tool
The DTF product flow, where customers upload art and preview transfers.

The storefront I worked on

Pages already render on the server in Rails. Webpack packs and Vue islands add behavior after that. Desktop gets US or CA store packs. The mobile browser uses the same pages. The apps load those pages in a WebView with mobile packs and a JS bridge.

Engineering decisions

1. Rails SSR and client-specific packs

I worked on a multi-page Rails storefront. HTML comes from the server. JS and CSS arrive as Webpack packs. Which pack you get depends on the page (default, product, account, checkout) and on the client (US store, CA store, or the mobile app).

Product pages are expensive to render, and deploys change asset filenames. Cached HTML cannot keep old pack URLs.

A single bundle for every client would ship a lot of unused code. Product detail pages use full-page HTML caching because they are expensive to render. The cached HTML keeps a placeholder for pack tags. When the page is served, those tags are filled from the current manifest, on a cache hit and on a miss, so the browser always gets the right files after a deploy.

The head loads page CSS first, then polyfills, deferred vendors, Vue vendors when the page needs them, analytics, the page pack, and a separate Tailwind pack. Checkout still loads webpack packs next to a leftover Angular runtime.

What the storefront does
  • US / CA / mobile packs stay separate
  • PDP HTML can be cached without stale asset URLs
  • Pack tags are filled from the current manifest
  • Fits a live catalog with more than one client
One universal pack
  • Fewer entry points to manage
  • Easier to reason about at first
  • Ships unused code to every client
  • Fights locale and WebView differences

If I changed UI on a product page, I also had to think about the cache key and how pack tags get attached on the way out.

2. Critical CSS vs deferred packs

The storefront has a lot of Sass and Tailwind. If every feature stylesheet loaded with the first paint, listing and product pages would download CSS they do not need yet. A lot of the frontend work was deciding what belonged in the main pack and what could wait.

Feature CSS should not block first paint on a live catalog.

There is no critical-CSS extractor in the build. The main application or PDP pack CSS stays blocking. Secondary packs such as footer, payment logos, deliver-to, and cookie consent load as print media and switch to all once they arrive. On cached PDPs, deliver-to CSS uses a preload-as-style path instead. A few masthead styles have to look right immediately, so those SCSS files are imported into the main pack on purpose.

Critical path
Main pack CSSRender-blocking for first paint
Critical masthead SCSSSynced into the main path
Deferred path
Feature CSS packsmedia=print → onload → all
Preload on cached PDPpreload as style → stylesheet
Defer secondary packs
  • Control per component pack
  • Little extra build tooling
  • Fits the existing Sass packs
  • Easy to miss a pack and get a flash of unstyled UI
Put it all in the main pack
  • One request to reason about
  • Blocks first paint with unused styles
  • Ties Tailwind and Sass together
  • Worse fit for route-specific UI

On a given ticket I would ask whether a style belonged in the main pack or could ship later with its feature. Layout shift and first paint already mattered on those pages.

3. WebView client, shared commerce

The iOS and Android apps embed the same Rails storefront in a WebView. I worked on the frontend in both places: mobile packs, app chrome, and a bridge back to native features.

A storefront change also has to work inside the app WebView.

The server sees the app from headers, stores a device cookie, and switches to mobile packs and a mobile-app layout class. Version gates turn native features on or off, including Apple Pay, filters, and PayPal. The page talks to the app with React Native WebView postMessage for experiments, cart quantity, payments, filters, and when the page is ready.

Pack choice, cache variation, and bridge events were part of shipping UI that still worked in the app.

Jiffy cart page
Cart UI that had to stay correct on web and in the app WebView.
4. Vue islands over Rails HTML

Cart and some product-detail flows are islands. Rails still renders the shell and the props. A deferred pack mounts Vue on a DOM node. I worked in that pattern. The catalog stayed on Rails HTML.

Cart and DTF need a real client app. The catalog still needs server HTML.

An ERB template defines the mount node. Props come through JSON attributes, window config, or slotted server HTML. Shared Vue vendors load when needed, then the island pack calls createApp and mount. Catalog pages stay server-rendered. Vue only mounts on the flows that need it.

Vue islands on the catalog
  • Fits the live Rails storefront
  • Keeps server HTML and PDP cache
  • Shares one Vue runtime via vendors
  • Means living with both ERB and Vue
React on Design Lab
  • Used for the customization lab, not the catalog
  • Own routing and a much larger client app
  • Leaves cart and DTF PDP on Vue
  • Covered in the Design Lab case study

Classic checkout can still load Angular next to webpack packs. Shipping there meant living with a mixed runtime.

Outcome

Catalog pages stay server-rendered and cacheable. Cart and the heavier product flows stay interactive through Vue. Web and the apps share one storefront, with different packs and a bridge when native behavior is required.

Day to day I traced pricing mismatches from the product page through checkout, cut layout shift on product pages, removed old A/B code from the PDP, and shipped cookie consent and analytics without blocking browse or checkout. Those tickets had to work with packs, cache keys, WebView gates, and island boundaries.

Testimonials

Luka Sakun
Luka SakunTeam lead @ Jiffy

I worked with Parmeet for half a year, and I can highly recommend him as an experienced front-end developer and a responsible team member. He can quickly understand an issue or a new codebase and provide a solution.

Yogesh Kumar
Yogesh KumarSenior frontend developer @ Jiffy

I worked with Parmeet at Jiffy, and he is a dependable frontend developer who delivers high-quality work. He writes clean and easy-to-maintain code and always focuses on good user experience and performance. Parmeet is skilled in JavaScript, TypeScript, React, and modern CSS (SCSS, Tailwind). He works well with the team, takes ownership of his tasks, and can be trusted to deliver. He would be a strong addition to any frontend team.

Rohit Gulati
Rohit GulatiLead frontend engineer @ Jiffy

Parmeet is an all-star frontend developer and a great teammate. I've worked with him on multiple features, and he consistently delivers thoughtful ideas, timely solutions, and pixel-perfect, scalable UI. I'd gladly work with him again!

Let's bring your nextbig idea to life

Whether you're brainstorming ideas, looking to bolster capabilities, rapidly expanding your team, or delegating projects, count on us to meet your needs effectively any or every step of the way

Available for new engagements