← Back to blog
ShopifyProductEngineering

Introducing Fitly: solving the returns problem at the source

Ripelix4 min read

Ripelix is an early-stage software studio. We build a small number of focused products and give each one real attention. Our first is Fitly, a Shopify app for size charts and size guides. This post explains the problem it solves and a couple of the engineering decisions behind it.

The problem: returns start with the wrong size

For online fashion and apparel stores, the single most common reason a customer returns clothing is that it did not fit — not quality, not appearance, not shipping. Sizing uncertainty hurts twice. Some shoppers leave the product page without buying because they are not sure which size fits. Others guess, get it wrong, and return the item. One is a lost sale; the other is reverse shipping, inspection, and restocking.

A clear size guide, shown at the moment of decision, removes that hesitation. That is the whole idea behind Fitly: help the customer know their size before they buy.

Design goal: no code, no theme edits

Plenty of size-chart tools ask merchants to paste code into their theme or hire a developer. We wanted setup to be something any merchant can do alone. In Fitly the entire flow lives in the app admin plus a single toggle in the Shopify theme editor, reached through a direct deep link. Build a chart from a template, assign it to products, and the storefront button appears.

Serving charts through metafields

A size guide should never slow down a product page. Instead of loading chart data from an external server at render time, Fitly stores each chart in Shopify metafields. The storefront widget reads the chart that ships with the page, so there is no extra network request blocking the product view — and the chart stays in sync automatically whenever a merchant edits it or changes an assignment.

Assignment that scales

A store with hundreds of products should not require hundreds of manual setups. Charts can be assigned by product, collection, vendor, or tag, and they inherit down that hierarchy: a product with no direct chart resolves one from its collection, then its vendor, then its tag. One thoughtful assignment can cover an entire catalogue.

Measuring whether it actually helps

We think a tool should be able to show its own value. Fitly includes an analytics dashboard that tracks how often guides are seen and opened, the store's return-rate trend, per-chart performance, and a per-product confusion score that highlights where shoppers hesitate between sizes. It keeps the product honest — and gives merchants a reason to keep it installed.

How it's built

Fitly is four moving parts, each picked for the job it does rather than for consistency across the stack. They all share one PostgreSQL database.

The admin — what a merchant actually uses — is a React and TypeScript app built with Vite, on top of Shopify's Polaris design system and App Bridge, so it looks and behaves like a native part of the Shopify admin rather than a page embedded in it. The chart builder's drag-and-drop blocks use dnd-kit, server state runs through TanStack Query, and the analytics charts are Polaris Viz. Rich-text blocks use Jodit, and the Pro plan's custom CSS field is a Monaco editor — the same one that powers VS Code.

The backend is Laravel on PHP 8.4. Anything slow runs as a queued job through Laravel Horizon on Redis: webhook handling, metafield writes, and catalogue syncs. Those syncs use Shopify's bulk operations API rather than paging through products one request at a time, so a large catalogue arrives as a single job instead of thousands of separate calls.

The storefront widget is deliberately the least fashionable part: plain JavaScript with no framework and no dependencies, shipped as a Shopify theme app extension. It is the only code that runs on a shopper's product page, so every kilobyte is one the store pays for on every page view. It reads the chart straight from the metafields Liquid has already rendered, builds the button and the modal, and is done.

The event pipeline is a small NestJS service. Widget events arrive through Shopify's app proxy, where the request's HMAC signature is verified before anything is trusted. The service then hands the event to Kafka without waiting on it and answers immediately; a consumer picks the events up in batches and writes them to PostgreSQL. Nothing about recording analytics is allowed to make a storefront wait.

The split is not for its own sake. The admin is a rich, stateful interface and React is good at that. The backend does queued, scheduled, transactional work and Laravel is good at that. Event ingestion is a narrow, high-volume path that wants to do one thing quickly. Keeping them apart means none of them has to compromise for the others.

What's next

Fitly is live on the Shopify App Store, and we are continuing to refine it based on how merchants actually use it. If you are building on Shopify and want a sizing solution — or want to talk about custom work — we would love to hear from you.


Building on Shopify or need custom software?

Get in touch