Skip to main content

01 Case study Live in production

Turning a WhatsApp sales process into a digital catalogue.

A digital catalogue and WhatsApp enquiry system built for ReturnSpark, a premium return-gifting business serving customers across India.

Client
ReturnSpark
Scope
Digital catalogue
WhatsApp enquiry
Client admin
Stack
Next.js
Supabase
Cloudflare
Live
returnspark.in (opens in a new tab) catalogue.returnspark.in (opens in a new tab)

The starting point

ReturnSpark already had a business. Customers found products, asked questions, discussed quantities and pricing, and placed orders through WhatsApp.

The problem was what happened before the conversation.

Return gifts are highly visual. Customers might choose between dozens of similar brass, silver and decorative products, often for weddings, naming ceremonies, housewarmings and other occasions.

Before the catalogue, showing that range meant sending photographs through WhatsApp one at a time. That works for a few products. It does not scale to a catalogue of more than a hundred.

The brief was simple: give customers somewhere to browse the range. But the real problem was slightly different.

Customers needed a way to move from discovering a product to enquiring about it.

We didn't build a store

The obvious solution would have been an e-commerce website. We deliberately didn't build one.

ReturnSpark already sold through WhatsApp. Pricing could vary by quantity, minimums could change, and retail and bulk customers could have different conversations. Adding carts, checkout, accounts and fixed pricing would have meant replacing a sales workflow that already worked.

So we designed around it. The catalogue became the discovery layer. WhatsApp remained the sales layer.

Every product has an Enquire Now action that opens a WhatsApp conversation with the product already identified. The customer doesn't have to remember a product name, copy a code or explain which photograph they were looking at.

The system connects browsing to the business process that already exists.

What we built

The system is split into two surfaces.

The brand site

returnspark.in (opens in a new tab) is a lightweight brand presence explaining who ReturnSpark is, what it offers and how to reach the business. Because the content changes rarely and does not need application infrastructure, it was built as static HTML rather than introducing a framework without a reason.

The catalogue

catalogue.returnspark.in (opens in a new tab) is the application where customers actually browse. It includes:

  • Product discovery
  • Category browsing
  • Search
  • Paginated product listings
  • Product detail pages
  • Product codes
  • Multi-category products
  • WhatsApp enquiry handoff
  • Product-specific link previews

The catalogue currently contains roughly 115 published products, with products able to belong to multiple categories.

That last part matters. A brass product might legitimately be relevant to a housewarming, a pooja and a wedding. Instead of forcing one product into one category, the catalogue models those relationships properly.

The small detail that makes the enquiry flow work

WhatsApp deep links can carry text, but they cannot directly attach a product image. So we used the product page itself.

When someone enquires, the message identifies the product and includes its URL. WhatsApp then generates a preview from the product page's Open Graph metadata. That meant the product's image could appear inside the conversation without building a separate media-sharing system.

It also created an important engineering requirement: every product page needed correct, product-specific metadata.

The technical implementation followed the customer journey rather than treating SEO metadata as an afterthought.

A catalogue the client can run

A catalogue that requires the developer every time a product changes isn't really a finished system.

We built a custom admin interface allowing ReturnSpark to:

  • Add products
  • Upload product images
  • Assign categories
  • Prepare products as drafts
  • Publish products
  • Manage the catalogue independently

Images can be uploaded individually, with up to ten images per product. The upload pipeline validates the actual file contents, checks dimensions and size, re-encodes the image and removes metadata before the image becomes durable.

The goal wasn't simply to make the admin work. It was to make sure the business could continue operating the system without us.

Then production found something we hadn't

The most interesting part of the project happened after the system was already being used. Product images began intermittently failing in production.

Field note Image pipeline · Production

When “image upload is broken” wasn't actually an upload problem.

The obvious diagnosis was that image upload was broken. It wasn't. We traced the image through the entire system.

  1. Upload
  2. Validation
  3. Processing
  4. Storage
  5. Delivery
  6. Browser

Boundaries where guarantees were failing

The failures turned out to involve different layers.

  • 05 — Delivery boundary

    Some public image requests were exhausting the Cloudflare Workers CPU budget during transformation.

  • 03 — Processing boundary

    Separately, testing the deployed processing path revealed that two assumptions made by the original upload pipeline did not hold consistently: that same-format transformations could preserve EXIF metadata, and that truncated images could be handled less strictly by the deployed processor than expected.

That distinction mattered. The system wasn't simply “broken.” Different guarantees were failing at different boundaries.

The fix wasn't the obvious one

The fastest way to make the image problem disappear would have been to stop processing uploads and store the original files. We rejected that.

The processing layer existed partly as a security and privacy boundary. Phone photographs can contain EXIF metadata, including GPS information. Removing that protection just to eliminate an image-processing failure would have solved one problem by creating another.

Instead, uploads were normalised to WebP. That forces a format change, which reliably takes the image through the cross-format processing path where metadata stripping was confirmed.

We then tested the actual invariants rather than trusting the implementation:

  • Malformed images
  • Truncated images
  • EXIF-bearing images
  • Polyglot files
  • Dimension handling
  • Re-encoding behaviour

A guarantee written in code isn't necessarily a guarantee in production until it has been tested against the runtime actually running the application.

Architecture

Frontend / application
Next.js
Backend data
Supabase
Deployment
Cloudflare Workers
Storage
Supabase Storage
Public image delivery
Cloudflare Images
Brand site
Static HTML on Cloudflare Pages

The catalogue uses OpenNext to run Next.js on Cloudflare Workers. That introduced a constraint: Workers is not a Node runtime, so dependencies and database access couldn't simply be assumed to behave like a conventional Node deployment.

Rather than fighting that constraint throughout the codebase, runtime-specific behaviour was moved to the composition boundary.

The architecture reflects the platform instead of pretending the platform isn't there.

What we didn't build

This is part of the case study too. We didn't build:

  • A shopping cart
  • Checkout
  • Customer accounts
  • Fixed product pricing
  • Inventory management
  • Order management
  • A second sales channel
  • A separate storage system

Not because we couldn't. Because the business didn't need those things yet.

The system contains what the current workflow requires and leaves room for commerce if future order volume justifies it.

What ReturnSpark got

Browsable
Customers can explore a large visual product range themselves.
Searchable
Customers don't have to manually scroll through WhatsApp conversations.
Connected to sales
Every product can move directly into a WhatsApp enquiry.
Maintainable
ReturnSpark can manage its own catalogue.
Deployable at scale
The architecture separates the lightweight brand surface from the application surface.
Live
The system is deployed on the client's domain and has generated customer enquiries.

We are intentionally not publishing traffic, conversion or revenue figures.

What this project taught us

  1. The brief is rarely the whole problem

    “Build a catalogue” sounded like a website requirement. The actual problem was connecting product discovery to an existing sales workflow. Understanding the business changed the product.

  2. Don't replace a workflow just because you can

    A checkout would have made the system look more like e-commerce. It wouldn't necessarily have made the business work better.

  3. Production is where assumptions get tested

    The image pipeline behaved differently across runtimes. The only reliable way to find that was to test the actual guarantees against the deployed system.

  4. Security controls shouldn't become optional under pressure

    The easy fix was to remove image processing. The correct fix was to understand why the processing existed and repair the failing layer without removing the protection.

  5. A client system has to belong to the client

    Deployment isn't the finish line. If the business still needs the developer to add a product, organise a category or publish an item, the system isn't truly handed over.

The result

ReturnSpark started with a simple problem: “We need somewhere customers can see our products.”

What shipped was more deliberate. A catalogue for discovery. A WhatsApp bridge for sales. An admin system for the business. And an image pipeline designed around the constraints of the production platform.

That is the kind of system we want to build at CraftYourSystems: not software that merely satisfies a brief, but software that fits the business using it.

ReturnSpark · Built through CraftYourSystems Source code is private. Published with the client's knowledge.