fashn-logo
FASHNAI

React Router Quickstart

React Router powers millions of web applications, from indie projects to enterprise platforms. It's the go-to framework for building Shopify apps, making it an ideal choice for e-commerce developers looking to add cutting-edge features like virtual try-on.

In this guide, you'll learn how to integrate the FASHN SDK into a React Router application. We'll build a complete virtual try-on feature that lets customers visualize garments on models in real-time, a game-changer for online fashion retailers.

What you'll build: A production-ready web application that displays model and garment images, then generates photorealistic try-on results showing the model wearing the selected garment.

Tech stack: React Router v7, TypeScript, and the FASHN SDK.

By the end of this tutorial, you'll have a solid foundation for adding FASHN's AI-powered virtual try-on to your e-commerce applications and Shopify apps.

Prerequisites

Before diving in, you'll need a FASHN API key to authenticate your requests. Getting started is straightforward:

  1. Head to the Developer API dashboard and click "Create new API key"
  2. Copy your key immediately, it's only shown once
  3. Store it securely (use a password manager or your team's secrets vault)

Security note: API keys should always stay server-side. React Router's server actions make this easy. We'll configure your key as an environment variable that never touches the browser.

Step 1: Create Your React Router Project

Let's scaffold a new React Router application with all the modern tooling configured out of the box, Vite for lightning-fast builds, TypeScript for type safety, and Tailwind CSS for styling.

npx create-react-router@latest my-rr-fashn-app
cd my-rr-fashn-app
npm run dev

Visit http://localhost:5173 to confirm everything's running. You should see the React Router welcome screen.

Step 2: Add the FASHN SDK

The FASHN TypeScript SDK eliminates boilerplate by handling authentication, polling, and error management automatically. It's built specifically for server-side environments, keeping your API credentials secure.

Install it with npm:

npm install fashn

Architecture note: The SDK must only be called from server actions or backend routes, never from client components. This server-side-only design is intentional and protects your API key from exposure.

Step 3: Set Up Environment Variables

Create a .env.local in your project root:

FASHN_API_KEY=your_api_key_here

Replace your_api_key_here with your actual key.

Important reminders:

  • Restart your dev server after adding environment variables
  • Verify .env.local is in your .gitignore (it should be by default)
  • Never commit API keys to version control

Step 4: Create the Try-On Interface

Now for the fun part: building the UI. We'll create a clean interface that showcases the before and after, making the virtual try-on transformation clear to users. Replace the contents of app/routes/home.tsx with this code:

import { useFetcher } from "react-router";
import { runGeneration } from "~/actions";
import type { Route } from "./+types/home";
 
export async function action({ request }: Route.ActionArgs) {
  const formData = await request.formData();
  const modelImage = formData.get("modelImage") as string;
  const garmentImage = formData.get("garmentImage") as string;
  const result = await runGeneration(modelImage, garmentImage);
  return result;
}
 
export default function Home() {
  const fetcher = useFetcher();
  const loading = fetcher.state !== "idle";
  const result = fetcher.data?.output;
  const error = fetcher.data?.error;
 
  const modelImage =
    "https://cm7xvlqw96.ufs.sh/f/wXFHUNfTHmLj9QTMwFWT5IXsA4Lhru0e7dJiKFwpQ6Glm28S";
  const garmentImage =
    "https://utfs.io/f/wXFHUNfTHmLjtkhepmqOUnkr8XxZbNIFmRWldShDLu320TeC";
 
  const handleTryOn = () => {
    fetcher.submit(
      {
        modelImage,
        garmentImage,
      },
      {
        method: "POST",
      }
    );
  };
 
  return (
    <div className="font-sans grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20">
      <main className="flex flex-col gap-[32px] row-start-2 items-center sm:items-start">
        <div className="grid grid-cols-2 md:grid-cols-3 gap-4 max-w-7xl">
          <div className="flex flex-col items-center gap-4">
            <img src={garmentImage} alt="Garment Image" />
            Garment Image
          </div>
 
          <div className="flex flex-col items-center gap-4">
            <img src={modelImage} alt="Model Image" />
            Model Image
          </div>
 
          <div className="flex flex-col items-center gap-4 col-span-2 md:col-span-1">
            <div className="flex items-center justify-center gap-4 w-full h-full min-h-[300px] md:min-h-auto bg-gray-200 text-black">
              {result && <img src={result} alt="Result Image" />}
              {error && <p>{error}</p>}
              {loading && <p>Loading...</p>}
            </div>
            Result Image
          </div>
        </div>
 
        <div className="flex gap-4 items-center justify-end flex-col sm:flex-row w-full">
          <button
            className="rounded-full border border-solid border-black/[.08] dark:border-white/[.145] transition-colors flex items-center justify-center hover:bg-[#f2f2f2] dark:hover:bg-[#1a1a1a] hover:border-transparent font-medium text-sm sm:text-base h-10 sm:h-12 px-4 sm:px-5 w-full sm:w-auto md:w-[158px]"
            onClick={handleTryOn}
          >
            Virtual Try-On
          </button>
        </div>
      </main>
      <footer className="row-start-3 flex gap-[24px] flex-wrap items-center justify-center">
        <a
          className="flex items-center gap-2 hover:underline hover:underline-offset-4"
          href="https://fashn.ai"
          target="_blank"
          rel="noopener noreferrer"
        >
          Go to fashn.ai →
        </a>
      </footer>
    </div>
  );
}

This interface includes:

  • Side-by-side layout showing the original garment and model
  • One-click generation with a clear call-to-action button
  • Real-time feedback through loading states
  • Results display that highlights the transformation

Step 5: Implement the Server Action

Create app/actions.ts to handle the FASHN SDK integration:

import Fashn from "fashn";
 
const client = new Fashn();
 
export async function runGeneration(modelImage: string, garmentImage: string) {
  try {
    const response = await client.predictions.subscribe({
      model_name: "tryon-v1.6",
      inputs: {
        model_image: modelImage,
        garment_image: garmentImage,
      },
    });
 
    // 1. Check for Runtime Errors (during model execution). Status can be failed, canceled or time_out.
    if (response.status !== "completed") {
      return { error: response.error?.message };
    }
 
    // 2. Success case (status is completed)
    return { output: response.output?.at(0) };
  } catch (error) {
    console.error(error);
    // 3. Handle API-Level Errors (before request processing)
    if (error instanceof Fashn.APIError) {
      return { error: error.message };
    } else {
      return { error: "Network or unexpected error" };
    }
  }
}

How it works:

  • Initializes the FASHN client with your API key from the environment
  • Calls the subscribe method, which creates a generation job using the tryon-v1.6 model and automatically polls until the result is ready
  • Returns the final image URL to display in your UI
  • Handles errors gracefully, providing meaningful feedback if something goes wrong

The subscribe method is the secret sauce here. It turns a complex async workflow into a single awaitable function call.

Step 6: Test Your Integration

With everything wired up, let's see the result:

  • Restart your dev server (npm run dev)
  • Open http://localhost:5173
  • Review the pre-selected model and garment images
  • Click "Virtual Try-On"
  • Watch as the AI generates a photorealistic result

The entire process typically takes 5-15 seconds. The FASHN SDK manages everything behind the scenes, job creation, status polling, and result retrieval.

Taking It Further

You've built a working virtual try-on feature! This tutorial uses pre-selected images for simplicity, but for production you would typically need:

  • User management - Track usage, prevent abuse, and implement rate limiting
  • File upload - Let customers upload their own photos or choose from a catalog
  • Image preprocessing - Validate dimensions, format, and quality before processing
  • Enhanced UX - User-friendly messages, retry logic and progress bars

Resources to Explore

Built something cool? Share it with the FASHN community or reach out to our team. We love seeing what developers create!

On this page