DEV Community

Josh Robertson
Josh Robertson

Posted on

Building an Intelligent Embroidery System: How We Automated Thread Color Selection for Custom Hats

This post originally appeared on AllTales.com - where we're building the future of personalized storytelling and custom merchandise.


The Problem: Manual Thread Color Configuration at Scale

When we launched our custom merchandise store at AllTales, we quickly discovered a challenge that many e-commerce platforms face: product customization at scale. Specifically, our embroidery products (hats, caps, etc.) required precise thread color selection based on the fabric color to ensure optimal contrast and readability.

Traditional approaches would require:

  • Manual configuration for each product variant
  • Customer selection during checkout (adding complexity)
  • Potential for poor color combinations
  • Increased support tickets for "unreadable embroidery"

Our Solution: AI-Powered Thread Color Intelligence

We built an intelligent system that automatically determines the optimal thread color based on product type and fabric color. Here's how it works:

1. Product Type Detection

// Check if this is an embroidery product (caps/hats)
const isEmbroideryProduct =
  validVariant.name.toLowerCase().includes("cap") ||
  validVariant.name.toLowerCase().includes("hat") ||
  validVariant.name.toLowerCase().includes("trucker");
Enter fullscreen mode Exit fullscreen mode

2. Smart Color Logic

// Determine thread color based on product type first, then hat color
if (
  productName.includes("under armour") ||
  productName.includes("under armor")
) {
  // Under Armour hat: Always white threads
  threadColor = "#FFFFFF";
} else if (productName.includes("trucker")) {
  // Trucker cap: Use closest available green (#01784E) to mint
  threadColor = "#01784E";
} else if (productName.includes("vintage") || productName.includes("twill")) {
  // Vintage Twill Cap: Always white threads
  threadColor = "#FFFFFF";
} else {
  // Fallback logic for other hat types
  if (
    hatColor.includes("black") ||
    hatColor.includes("navy") ||
    hatColor.includes("royal") ||
    hatColor.includes("red") ||
    hatColor.includes("maroon")
  ) {
    threadColor = "#FFFFFF"; // White thread for dark hats
  } else if (
    hatColor.includes("pink") ||
    hatColor.includes("grey") ||
    hatColor.includes("gray") ||
    hatColor.includes("white") ||
    hatColor.includes("charcoal") ||
    hatColor.includes("heather")
  ) {
    threadColor = "#000000"; // Black thread for light hats
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Fallback System with Retry Logic

When the initial thread color fails validation, our system automatically tries alternative colors:

// Define thread colors to try in order of preference
const threadColorsToTry = getPreferredThreadColors();

let orderCreated = false;

// Try each thread color
for (const threadColor of threadColorsToTry) {
  try {
    // Update order data with new thread color
    const retryOrderData = {
      ...printfulOrderData,
      items: printfulOrderData.items.map((item: any) => {
        if (
          item.options &&
          item.options.some((opt: any) => opt.id.startsWith("thread_colors"))
        ) {
          return {
            ...item,
            options: item.options.map((opt: any) =>
              opt.id.startsWith("thread_colors")
                ? { ...opt, value: threadColor }
                : opt,
            ),
          };
        }
        return item;
      }),
    };

    printfulOrder = await printful.createOrder(retryOrderData);
    orderCreated = true;
    break;
  } catch (retryError) {
    console.log(
      `❌ Failed with thread color ${threadColor}: ${retryError.message}`,
    );
    // Continue to next thread color
  }
}
Enter fullscreen mode Exit fullscreen mode

The Technical Architecture

Webhook Integration

This system runs within our Stripe webhook handler, ensuring that every order is processed with the correct thread color configuration:

if (event.type === "checkout.session.completed") {
  const session = event.data.object as Stripe.Checkout.Session;

  // Check if this is a merch order
  if (session.metadata?.type === "merch_order") {
    // Process with intelligent thread color selection
    await processMerchOrder(session);
  }
}
Enter fullscreen mode Exit fullscreen mode

Printful API Integration

We integrate with Printful's API to create orders with the correct embroidery options:

const options: any[] = [{ id: "embroidery_type", value: embroideryType }];

// Add thread color option (multi_select expects array)
options.push({ id: "thread_colors_front_large", value: [threadColor] });

const itemData = {
  variant_id: variantId,
  quantity: item.quantity,
  options: options,
  files: embroideryFiles,
};
Enter fullscreen mode Exit fullscreen mode

Benefits of This Approach

1. Zero Customer Friction

Customers don't need to understand embroidery requirements or make technical decisions during checkout.

2. Consistent Quality

Every product automatically gets the optimal thread color combination, ensuring professional results.

3. Scalable Operations

No manual configuration needed for new products or variants - the system handles it automatically.

4. Error Resilience

The retry system ensures orders succeed even when the primary thread color isn't available.

5. Brand Consistency

We can enforce brand colors (like our signature green) for specific product types.

Lessons Learned

1. API Limitations Drive Innovation

Printful's thread color validation forced us to build a robust fallback system that actually improved our product quality.

2. Automation Reduces Support Burden

By eliminating manual thread color selection, we've dramatically reduced support tickets related to embroidery quality.

3. Webhook Processing is Critical

Running this logic in the webhook ensures consistency and prevents human error in order processing.

4. Product Knowledge is Code

Our understanding of different hat types and their optimal thread colors is now encoded in our system, making it transferable and maintainable.

The Future

This system has become the foundation for other automated product customizations at AllTales. We're now applying similar logic to:

  • Print file selection based on product type
  • Size recommendations based on customer demographics
  • Material selection based on use case
  • Pricing optimization based on production costs

Conclusion

What started as a simple thread color problem evolved into a sophisticated automation system that improves both customer experience and operational efficiency. By encoding product knowledge into our webhook processing, we've created a system that scales with our product catalog while maintaining quality standards.

The key insight? Sometimes the most valuable automation isn't about replacing human decision-making - it's about encoding expert knowledge into systems that can apply it consistently at scale.


Interested in building similar intelligent e-commerce systems? Check out our open positions at AllTales.com or explore our merchandise store to see this system in action.

What automated product customizations have you built? Share your experiences in the comments below!

Top comments (0)