Try Our Free Chrome Extension – and Steal Our Code to Make Your Own AI Tool

Posted by:
Caitlin Fithian
on
January 2, 2025

We couldn’t resist the hype any longer – we caved and built an AI tool. We know, total developer cliché. 🙈 

Meet "How Do I Look?", a free AI Chrome Extension that lets you virtually try on clothes from any e-commerce site. But here’s the twist: we didn’t just build a cool product — we’re giving away the code for free.

Spongebob holding a rainbow

Sure, virtual try-ons are handy (who still shops in-person?!). But the best part is you can use this code to kickstart your next AI-powered project. 

How can you do this?

  1. Productize the code and sell it. 💰
  2. Save your user’s looks and let them build a virtual closet. 👕
  3. Add a backend, let your users save their favorite outfits, and link back to the retailers (use a referral link to make money). 🤝 

So, go ahead – steal the code, personalize it, and monetize what you create!

Let’s dive into the tech and see how to get started with the extension. 

“How Do I Look?” AI Chrome Extension Structure

First, check out our GitHub and video demo

The extension is built with standard web technologies (HTML, CSS, and JavaScript) and follows Chrome's extension architecture. The main components are:

  • A popup interface (popup.html)
  • Content scripts that interact with web pages (content.js)
  • Utility functions (utils.js)
  • Settings management (settings.js)

Now, let’s review the user journey so you can start using “How Do I Look?” ASAP (or at least copy the code for your own project 😉).

Quick Start Guide

1. Set-Up the AI Chrome Extension 

When you first install the extension, set-up is quick and painless. Configure your API keys, and you’re ready to go! 

And don’t worry, the extension checks for these keys automatically on startup.

Manage your API Keys: 

document
  .getElementById('settingsForm')
  .addEventListener('submit', function (e) {
    e.preventDefault();
    const openAIApiKey = document.getElementById('openAIApiKey').value;
    const replicateApiToken = document.getElementById('replicateApiToken').value;
    const simpleFileUploadBucketId = 
    document.getElementById('simpleFileUploadBucketId').value;

    localStorage.setItem('openAIApiKey', openAIApiKey);
    localStorage.setItem('replicateApiToken', replicateApiToken);
    localStorage.setItem('simpleFileUploadBucketId', simpleFileUploadBucketId);

    document.getElementById('saveSettings').innerHTML = 'Saved';
    setTimeout(() => {
      if (openAIApiKey && replicateApiToken) {
        hideSettings();
      }
    }, 1000);
  });

Pro Tip: if you release this as a product, you’ll need to do this on the server for all your users. 

2. Image Selection

Once you’ve set-up the extension, it’s easy to get started — you can: 

  • Upload a new image of yourself to try on your latest finds. 
  • Browse through cached images for quick access to past uploads. 
  • Delete old images you don’t want anymore. 

The image handling is managed through an interface that shows visual thumbnails and a quick-access upload button:

  <div id="mainContent">
    <div id="cachedImages">
      <!-- Cached images will be inserted here -->
    </div>
    <button id="tryOn" disabled>Try On</button>
    <div id="loader" class="loader"></div>
    <div id="loadingMessage">It may take around 30s to dress up the person</div>
    <div id="result"></div>
    <input type="file" id="personImage" accept="image/*" style="display: none;">
  </div>

Pro Tip: Want to set-up a subscription service and let your users save their looks? Sign-up for Simple File Upload, and you can start monetizing your code in under 5 minutes. 

3. Image Processing

Here’s what happens when you upload an image. 

  • The image is resized for optimal processing:
function resizeImage(file, maxWidth) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = function (e) {
      const img = new Image();
      img.onload = function () {
        const canvas = document.createElement('canvas');
        const ctx = canvas.getContext('2d');
        const scaleFactor = maxWidth / img.width;
        canvas.width = maxWidth;
        canvas.height = img.height * scaleFactor;
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        canvas.toBlob((blob) => {
          resolve(new File([blob], file.name, { type: file.type }));
        }, file.type);
      };
      img.src = e.target.result;
    };
    reader.readAsDataURL(file);
  });
}
  • The resized image is uploaded to Simple File Upload for AI processing.
  • Append your file tags to keep your files organized on the Simple File Upload dashboard. Simple File Upload will return a specially formatted URI called AI URL:
function uploadImageToSimpleFileUpload(imageFile) {
  // Files are deleted frequently - to save files sign up 
  for an account at https://simplefileupload.com/

  const bucketId = localStorage.getItem('simpleFileUploadBucketId') || 
  'e8557605f1b5ac9b18c913603d29a8c8';
  const url = "https://app.simplefileupload.com/api/v1/file"

  return resizeImage(imageFile, 500).then((resizedFile) => {
    const formData = new FormData();
    formData.append('file', resizedFile);
    formData.append('bucket_id', bucketId);
    // If you want to add tags to the upload to keep everything organized, 
    you can add them here.
    // formData.append('tags', 'user_image');
    return fetch(url, {
      method: 'POST',
      body: formData,
    })
      .then(response => {
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }
        return response.json();
      })
      .then(data => {
        if (data.data.attributes['ai-url']) {
          return data.data.attributes['ai-url'];
        } else {
          throw new Error('No AI URL in the response');
        }
      })
      .catch(error => {
        console.error('Error uploading to Simple File Upload:', error);
        throw error;
      });
  });
}

Pro Tip: This example deletes images every few minutes, but you can try Simple File Upload for free for 7 days if you want to store your images. 

4. Image Detection 

When you click "Try On", the extension:

  • Injects a content script into the current webpage.
  • Uses OpenAI's GPT-4 to analyze the page's HTML and find the main product image.
  • Extracts the product image URL.

This is handled by the content script:

async function getProductImageFromGPT(htmlContent, openAIApiKey) {
  console.log('getProductImageFromGPT', openAIApiKey, !openAIApiKey);
  if (!openAIApiKey) {
    console.error('OpenAI API key not provided');
    return null;
  }

  const apiUrl = 'https://api.openai.com/v1/chat/completions';

  const prompt = `
    Analyze the following HTML content and extract the URL of the 
    main product image.
    Look for both <img> tags and CSS background-image properties.
    Consider elements and children with class names or IDs 
    containing words like 
    'product-image' 'product', 'main', 'featured' etc.
    Return only the full URL with commonly used image extensions 
    (jpg, jpeg, png, webp) of the main product image in JSON format,
    with the key "productImageUrl".
    If you can't find a product image, return {"productImageUrl": null}.

    HTML content:
    ${htmlContent.substring(
      0,
      50000
    )} // Limiting to few characters to avoid exceeding token limits
  `;

  try {
    const response = await fetch(apiUrl, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        Authorization: `Bearer ${openAIApiKey}`,
      },
      body: JSON.stringify({
        model: 'gpt-4o',
        messages: [{ role: 'user', content: prompt }],
        response_format: {
          type: 'json_object',
        },
      }),
    });

    const data = await response.json();

    const result = JSON.parse(data.choices[0].message.content.trim());
    console.log('getProductImageFromGPTresult', result);
    return result.productImageUrl;
  } catch (error) {
    console.error('Error fetching product image from GPT-4o:', error);
    return null;
  }
}

5. AI Image Handling  

The magic happens when your photo and the photo of the outfit are processed. 🪄

  • The extension sends both images to Replicate's AI model.
  • The images are processed (wait for ~30 seconds).
  • Results are displayed in the popup.
  function performVirtualTryOn(personImageUrl, productImageUrl, currentPageUrl) {
    const replicateApiToken = localStorage.getItem('replicateApiToken');
    if (!replicateApiToken) {
      showError('Replicate API token is missing. Please set it in the settings.');
      return;
    }

    const payload = {
      version: "c871bb9b046607b680449ecbae55fd8c6d945e0a1948644bf2361b3d021d3ff4",
      input: {
        "crop": false,
        "seed": 42,
        "steps": 30,
        "category": "upper_body",
        "force_dc": false,
        "garm_img": productImageUrl,
        "human_img": personImageUrl,
        "mask_only": false,
        "garment_des": "cute pink top"
        }
      }
    console.log('Sending request to Replicate API:', payload);

    fetch('https://api.replicate.com/v1/predictions', {
      method: 'POST',
      headers: {
          'Authorization': `Bearer ${replicateApiToken}`,
          'Content-Type': 'application/json'
      },
      body: JSON.stringify(payload)
    })
      .then((response) => {
        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
      }

      response.json().then((data) => {

        console.log('Replicate API response:', data);
        const getUrl = data.urls.get;
        listenForResult(getUrl, productImageUrl, currentPageUrl);
      });
    })
    .catch((error) => {
      console.error('Error in virtual try-on process:', error);
      showError(`Could not perform virtual try-on. Error: ${error.message}`);
    });
}

Pro Tip: You can use different Replicate models for fun! This example is focused on the “upper body,” so it works best for shirts and sweaters.

Code, Customize, and Monetize Your Own AI Tool

And that’s a wrap — a complete guide to how we built "How Do I Look?", plus tips on how you can use it to create your own AI-powered project. 

Whether you’re building a virtual closet, upgrading your e-commerce site, or launching something new – use this code for your next AI tool. (Seriously, it’s free - go for it!). 

And hey, don’t forget to share what you create - we’d love to see what kind of AI tools you design next! 

P.S. Huge thanks to Shyjal for sparking this idea – sometimes the best innovations come from building on what inspires us. 💡

P.P.S. Ready to monetize your AI tool? Use Simple File Upload to turn your code into a product. It’s a win-win for everyone. 😉

Get Started With Simple File Upload.

Easy Uploads. Effortless Integration.

Start Uploading for Free