Rooh is more than a shop — it’s a story stitched into cotton: small-batch block-printed garments, homewares and accessories rooted in Indian craft and made for everyday life. We wanted the website to feel like that: warm, tactile, honest, and easy to use — a place where the handmade details of Jaipur meet the clarity of a modern online shop. You can explore our collections, including our luxury quilted cotton dressing gowns, on the site.
This article is a full, behind-the-scenes look at how we created the Rooh London website: the design thinking, the stack choices (yes — Python, C++, Java and more), the problems that made us grind our teeth, the engineering and editorial tradeoffs we made, and the roadmap we’re building toward. If you’re a maker, a founder, or just curious about what goes into building a modern artisan e-commerce site, welcome — pull up a chair.
- Starting with why: design goals and brand fit From the first conversations, our brief was simple but demanding: translate the soul of Rooh — its block prints, handcraft, and sustainable ethos — into an online experience that feels authentic and effortless.
Key goals we set:
Let products breathe: large photography, generous white space, true-to-life colours, so the irregularities of hand-block printing read as character rather than “imperfection.”
Make shopping simple: clear product information, easy sizing, straightforward returns and shipping copy.
Support storytelling: pages for “Our Story”, the magic of block printing, and journal posts so customers can connect to craft and provenance.
Performance & accessibility: fast pages (mobile-first), and accessible markup so everyone can navigate, read, and buy.
Operational reliability: robust inventory, simple order management and clean analytics so the business can scale without breaking processes.
These goals shaped every decision we made — from the information architecture to how we handled images and product metadata.
- Choosing the technical approach: pragmatic, scalable, and craft-friendly There’s always a tension between “ship fast” and “build right.” Early on we committed to an approach that would allow the design to feel bespoke while keeping operations manageable.
High-level choices we made:
A modular architecture: split responsibilities into front-end presentation, product/catalog management, and backend services (payments, email, analytics, image pipeline).
Use Python for server-side services and automation: order processing scripts, reporting, image processing orchestration, export/import tools for product data, and the custom tooling around content and inventory sync. Python’s ecosystem (requests, Pillow, Pandas, etc.) made it efficient for these tasks.
Use C++ for heavy-duty image processing tasks: where we needed optimized native routines (e.g., batch color-correction, perceptual hashing for duplicate image detection, or performance-critical parts of an image-resize pipeline), C++ delivered the performance we needed.
Use Java where mobile or JVM integration was helpful: we used Java for a couple of internal microservices that needed JVM stability or to reuse some existing Java libraries for payments / secure token handling in our ops tooling.
Front-end: modern HTML/CSS and JavaScript with responsive, accessible components. We optimized images, lazy-loaded non-critical assets, and made sure the markup degrades gracefully.
Hosted and managed services: we relied on proven third-party systems for payments, email, and international shipping rates to keep the compliance and operational complexity low.
Why this mix? Because the site is both editorial and transactional. Python gave us developer velocity and scripting power; C++ let us handle compute-heavy image tasks efficiently; Java provided stable back-end components where we needed them. In practice, most of the visible “site” is HTML/CSS/JS with server-side glue and background workers in Python and C++ binaries for heavy lifting.
Note: a site’s visible stack and its behind-the-scenes tooling aren’t always the same. We deliberately used a hybrid approach so designers and editors could publish content quickly while engineers kept the system robust and fast under load.
- Designing for craft: visuals, imagery, and colour accuracy Rooh’s products are built on colour and print. If colours are off, the whole brand promise breaks. That forced us to treat imagery and visual fidelity as first-class engineering problems.
Challenges:
Colour consistency across devices — phone screens, laptops, tablets — all render colours slightly differently. We created a workflow to calibrate product photography and to process images in a controlled pipeline so prints looked consistent.
Large, tactile imagery vs performance — we wanted billboard-worthy product photography without penalizing mobile users. Solution: multiple responsive image sizes, modern image formats, and careful lazy-loading strategies.
Representing handcrafted variation — block-printed garments vary: a print may not be perfectly symmetrical and that’s part of the story. We designed product pages to highlight close-ups and process shots so customers understood the authenticity.
Technical implementations:
Shot metadata flows into a Python-powered image pipeline that produces multiple sizes (srcset), strips EXIF for privacy, and produces perceptual hashes (using optimized binaries) to ensure no accidental duplicates are uploaded.
We built a simple internal “visual QA” page that allowed editors to preview images at real device widths and flagged obvious colour drift so we could catch problems before publish.
This attention to imagery is a big part of why product pages feel tactile and trustworthy.
- Product data modeling and content strategy A great product page is more than photos. It’s accurate sizing, clear materials, provenance, washing instructions, and a small story — the “why” behind the piece.
How we modeled product data:
Canonical SKU for inventory control.
Attributes: fabric, block-print pattern name, origin, dimensions, care instructions, and any handmade notes (e.g., "small irregularity near hem — part of artisanal charm").
Variant system: sizes, colours, and limited editions.
Structured SEO fields: meta title, meta description, canonical URL, and JSON-LD product schema for search engines.
Content workflow:
Editors use a lightweight CMS interface to populate collaborative product descriptions. We wrote content guidelines to keep voice consistent (warm, informative, craft-first).
The copy emphasizes sustainability and provenance where appropriate — that’s central to Rooh’s identity.
- The checkout & payments conundrum — security, UX, and trust An elegant checkout is one where the customer barely thinks about the technology. Achieving that requires balancing UX, local payment methods, and compliance.
Core issues we solved:
Payment trust indicators — trust icons, clear return/shipping info, and friendly microcopy reduce friction.
Mobile-first payments — most traffic is mobile; the checkout flow is single-column, with the most important inputs (address, shipping) prioritized.
Fraud and chargebacks — we integrated fraud-detection signals (address mismatch flags, velocity checks) in the backend. Python workers handle asynchronous fraud scoring and alerts for manual review.
Implementation details:
The checkout is split into a public flow and a secure tokenized payment flow that never stores raw card data on our infrastructure. Where possible, we used payment providers’ hosted fields or tokenization to shift PCI burden away from our servers.
We built confirmation emails and order status pages that update in near-real-time from the order processing backend.
- Performance and SEO — making content discoverable and fast E-commerce sites live and die by performance and discoverability. We built optimizations at every layer.
Performance playbook:
Critical CSS & server-side rendered HTML for first paint: we prioritized above-the-fold content and deferred non-essential scripts.
Responsive images and modern formats: multiple sizes via srcset and WebP/AVIF generation in the image pipeline.
Caching: CDN for static assets and short, cache-friendly headers for frequently updated assets; amortize dynamic calls with edge caching where possible.
Lazy loading: non-critical blocks (reviews, extra carousels) load after the initial render.
SEO and structured data:
Semantic HTML, clean URL structure, and product schema (JSON-LD) for rich search result snippets.
Editorial blog and product story pages to capture long-tail keywords around block printing, sustainable textiles, and product care.
- Accessibility — not optional, but essential We followed WCAG principles from the start:
Proper headings and landmarks for screen readers.
Alt text for all imagery (descriptive and helpful).
Keyboard-accessible interactive components (menus, product selectors).
High-contrast options for essential UI elements.
Accessibility fixes were iterative: early rounds of user testing uncovered keyboard traps and inconsistent focus outlines; we prioritized these bugs and ran automated a11y scans alongside manual audits.
- Inventory, fulfilment, and operational glue For artisan brands with small-batch inventory, the operational model must be flexible.
Problems encountered:
Limited stock & oversell risk — some products are one-off or limited runs. We built soft-reservation on checkout to reduce oversells and alert systems for low-stock thresholds.
International shipping complexity — duty and shipping rules vary. We implemented tiered shipping rules and clear shipping timelines so customers know when to expect orders.
Tools & automation:
Python scripts to sync supplier spreadsheets with the product database and nightly reconciliation jobs to detect mismatches.
A simple pick-and-pack dashboard for fulfilment staff that shows prioritized orders and prints packing slips.
- The dev-ops pain points (and how we survived them) Getting a site live is part engineering, part logistics and part patience.
Notable hiccups:
Deploy rollbacks — early on a deployment that changed the product-variant model caused a partial outage. We introduced feature flags and automated schema migrations to make rollouts safer.
Third-party outages — when an external payment/email provider had downtime, we had fallbacks and graceful degradation so customers could still browse and save carts.
Image pipeline bottlenecks — processing a large shoot caused our image pipeline to saturate. We moved heavy work to asynchronous job queues and introduced rate limits on ingestion.
We set up CI/CD with automated tests: unit tests for services, smoke tests for the checkout, and visual regression checks for the main pages. These tests helped us catch regressions before they hit customers.
- Data, analytics, and learning from customers We treat data as the compass that tells us where to go next.
What we track:
Basic funnel metrics: sessions → product view → add-to-cart → checkout → purchase.
Product-level metrics: conversion rate, returns, repeat buy rate.
Email campaign performance and LTV (lifetime value) per cohort.
We use the analytics feedback loop to prioritize work: if a product page has strong traffic but low conversion, we test different approaches (copy, photography, shipping callouts) until we improve performance.
- Customer service and trust-building features Small brands win on service.
Features we built:
Clear contact page and a ticketing flow for customer queries; order history and simple refund workflows on the backend.
Trust signals: testimonials and editorial features. These help show the human side of Rooh and are visible across the site.
We made sure our post-purchase experience — confirmation emails, dispatch updates, and returns instructions — is calm, informative and on-brand.
- Real problems we faced (and the stories behind them) This is the juicy part — the things that broke, embarrassed us, or taught us something.
Problem: A hero image looked “off” on iOS
We shipped a big hero banner and a user reported the colours looked oversaturated on iPhone X. After checking, we realized the original photograph had been edited in a colour profile that some browsers handled differently. Fix: we standardized every image to sRGB, re-exported using our image pipeline, and added automated profile validation to the CI process.
Problem: A sales spike crashed a worker
A weekend email drove unexpected traffic to a limited-edition item. A race condition in our soft-reservation code allowed a small number of double-reservations. Fix: we hardened the reservation code with atomic DB transactions, added a circuit breaker, and set a queue limit to keep workers from being overwhelmed.
Problem: The product story didn’t convert
One collection had beautiful photography but poor conversions. We discovered customers wanted additional fit information and honest, specific care details. Fix: we rewrote product copy with micro-FAQs, added a fit guide, and added “closer” imagery — all of which helped conversion.
Problem: Managing artisan lead times
Some block-printed items take longer to reproduce. We needed to be transparent without scaring customers off. Fix: publish accurate lead times on product pages, allow pre-orders with expected dispatch dates, and ensure customer support can proactively communicate delays.
Each of these problems taught us a lesson: prioritise reproducible processes, make tooling that surfaces human error quickly, and never assume a beautiful design will work without operational support behind it.
- The role of code — a closer look at Python, C++ and Java in our stack You asked about the languages — here’s how each one earned its place.
Python — the glue and the speed of iteration
Admin tooling and small backend services (inventory sync, CSV import/export, scheduled reports).
Image pipeline orchestration and integration with performance binaries.
Prototyping new features quickly (A/B tests, small analytics jobs).
Example: a Python worker parses vendor CSVs, normalizes measurements, and creates a diff report for editors to accept or reject.
C++ — when performance matters
Native image-processing components (fast resize loops, perceptual hash calculation, batch manipulation).
We wrapped C++ binaries and exposed them to Python via command-line interfaces or light bindings so editors didn’t have to touch low-level code.
Example: generating a perceptual hash (pHash) at scale for many images would be slow in pure Python; a C++ routine cut runtime significantly.
Java — stability & integration
A couple of JVM-based microservices handled longer-running transactional workflows where we could reuse stable Java libraries (for secure tokenization, message parsing, or integrations with legacy systems).
Example: an order-archival service that writes immutable ledgers to a document store was implemented in Java for reliability.
This hybrid approach kept development efficient while giving us performance where we needed it. Importantly, we kept clear interfaces between components so we could replace parts later without a full rewrite.
- Testing, monitoring, and error recovery We baked reliability into our release cadence.
Testing strategy:
Unit tests for business logic.
Integration tests for critical flows (cart to checkout).
End-to-end smoke tests that run against staging for each release.
Visual regression tests for key landing and product pages.
Monitoring:
Real-time logs and alerts for errors, slow transactions, and checkout failures.
Uptime and latency dashboards, plus a daily summary emailed to the team.
Incident response:
Playbook for common incidents (payment provider outage, image pipeline failure, high error rate).
Post-mortems after significant incidents to improve systems and processes.
- Marketing, SEO and community building (the business side of the site) Technical work only matters if customers can find the brand and feel connected.
Marketing tasks we built into the product roadmap:
A content-first SEO strategy — blogs about block printing, artisan profiles, and care guides.
Email capture & lifecycle emails (welcome series, abandoned cart, replenishment reminders).
Pop-ups and on-site banners carefully timed to avoid disrupting the shopping experience — the homepage uses a subtle newsletter callout rather than interruptive modals.
Community & offline:
Rooh participates in fairs and pop-ups — we built an “Events” page so customers can meet the brand in person. This cross-channel approach supports retention and brand trust.
- How we measured success (KPIs that matter) The metrics we watched closely:
Conversion rate by channel and by product.
Average order value (AOV) and LTV of cohorts.
Product return rates and reasons.
Time from order to dispatch (operational efficiency).
Organic traffic growth to the editorial journal pages.
We used these metrics to prioritize features: if editorial content drove high-intent traffic, we invested more in long-form articles and artisan stories.
- Security and privacy We implemented industry-best practices:
No raw card data stored on our servers (tokenization).
HTTPS site-wide with HSTS.
Regular security scans and dependency updates.
Privacy-first analytics where possible and clear, simple cookie/privacy notices.
Transparency with customers was a priority: clear shipping and returns, and a simple privacy policy.
- Internationalization and localisation Rooh ships internationally and our interface had to handle that gracefully.
Considerations:
Currency display, shipping pre-checks, and localized shipping copy.
Local SEO for key markets.
Language needs: we prioritized English (UK) first and built the content model so translations could be introduced later with minimal structural changes.
- The editorial process: how product stories get written We treat copy like craft.
Editorial workflow:
Product brief (materials, story, photographer notes).
Draft copy by a content editor, with mandatory fields: fabric, fit, care, origin, and sustainability note.
QA pass for accuracy and SEO optimization.
Publishing with canonical URLs, meta tags, and internal linking (to related products and editorial posts).
This process ensures that product pages are useful, honest, and discoverable.
- Launch day & immediate learnings Launch day was part exhilaration, part tension.
What worked:
The editorial voice landed well; early feedback praised the product imagery and storytelling.
What we improved right after launch:
Loading time on some image-heavy pages — we tightened our CDN rules and adjusted prefetching.
Checkout micro-copy to reduce input errors during address entry.
Additional payment options for a few local markets.
- Roadmap and future goals We built something solid, but we’re far from finished. Our future roadmap focuses on product and people.
Short-term priorities (next 6–12 months):
Enhanced personalization — smarter product recommendations on the homepage and product pages based on browsing and past purchases.
Inventory visibility improvements — clearer lead times on limited-run items and pre-order UX.
Better international UX — localized currency and shipping experiences for core markets.
Accessibility improvements — continuous audits to reach higher WCAG conformance.
Faster imagery — investing in AVIF generation and finer-grained responsive images.
Medium-term goals (12–24 months):
Community features — user-generated content, a “wear it your way” gallery, and artisan Q&As to deepen trust.
Sustainability reporting — public pages showing the brand’s environmental and social impact, supplier stories and traceability for certain collections.
A bespoke mobile app — to support loyalty, early access drops, and an offline-enabled lookbook.
Long-term vision (24+ months):
Tighter artisan partnerships — collaborative capsule collections co-designed with artisan groups with transparent revenue shares.
A richer craft archive — editorial and multimedia features that preserve block-print techniques and artisan histories.
Global wholesale & stockist tools — an integrated portal for stockists and wholesale partners.
All of these are guided by the same principle we started with: protect craft, be honest about provenance, and build delightful, reliable online experiences that help customers connect with the maker.
- Practical takeaways for teams building similar sites If you’re building an artisan e-commerce site, a few practical lessons we learned:
Treat imagery as infrastructure — invest in a pipeline, colour profiles, and responsive variants from the start.
Build robust product metadata — good product data saves customer support time and reduces returns.
Start with the customer journey — map the whole experience from discovery to post-purchase and instrument it with analytics.
Design operational processes as code — syncing spreadsheets, onboarding new SKUs, and returns handling should be automatable.
Prioritise trust signals — clear shipping, returns, customer stories, and proof of craft make a big difference.
Iterate fast, but test deployments — feature flags and migration plans avoid painful rollbacks.
- A final note on craft, care, and the road ahead Creating the Rooh website was an exercise in translating texture into pixels — keeping the warmth of hand-block-printed cotton visible in a medium that can feel cold. The story of this site is one of many small decisions that together produce a human experience: the choice to include close-up photography, to explain a garment’s provenance, to avoid overselling limited runs, and to make the checkout calm and predictable.
We used a hybrid technical stack — Python for agile services and tooling, C++ for performance-critical image tasks, and Java in places where JVM stability helped us — but the stack is only a means to an end. The real purpose is to serve customers and artisan partners well.
Top comments (0)