# Creating a React minting app

{% hint style="info" %}
This example uses [RainbowKit](https://rainbowkit.com/) and [Viem adapter](/client-sdk/sdk/account-adapters/viem.md). The SDK also works with Ethers v5 via the [EthersV5 adapter](/client-sdk/sdk/account-adapters/ethersv5.md).
{% endhint %}

The repository includes a complete example at [examples/rainbowkit-mint](https://github.com/manifoldxyz/client-sdk/tree/main/packages/examples/edition/rainbowkit-mint), demonstrating how to implement minting with Manifold products including [Edition Products](/client-sdk/reference/editionproduct.md)

**Overview**

The edition RainbowKit example showcases how to:

* Connect wallets with RainbowKit + wagmi
* Mint [Edition products](/client-sdk/reference/editionproduct.md) through the Manifold Client SDK
* Run on Next.js 14 with the App Router and TypeScript
* Display mint progress, costs, and errors in the UI
* Complete example at [examples/rainbowkit-mint](https://github.com/manifoldxyz/client-sdk/tree/main/packages/examples/edition/rainbowkit-mint)

**Quick start**

1. **Install workspace dependencies**

   ```bash
   pnpm install
   ```
2. **Create environment variables**

   ```bash
   cp .env.example \
      env.local
   ```

   Fill in:

   ```env
   NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=your_walletconnect_project_id
   NEXT_PUBLIC_INSTANCE_ID=your_edition_instance_id
   NEXT_PUBLIC_RPC_URL_SEPOLIA=your_alchemy_rpc_url
   ```

   `NEXT_PUBLIC_INSTANCE_ID` must point to an Edition product you published in Manifold Studio.\
   `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` is optional but required if you want to support [WalletConnect](https://dashboard.reown.com/sign-in) wallets.\
   `NEXT_PUBLIC_RPC_URL_SEPOLIA` your[ Alchemy Sepolia RPC URL](https://www.alchemy.com/overviews/private-rpc-endpoint).
3. **Launch the example**

```bash
pnpm dev
```

Visit `http://localhost:3000` and connect a wallet with RainbowKit’s `ConnectButton`.

**Key implementation steps**

1. Follow [RainbowKit setup instructions](https://rainbowkit.com/docs/installation)

Ensure you have the [ConnectButton](https://rainbowkit.com/docs/connect-button) component on your page.\
This handles wallet connections, which are required to create an [Account](/client-sdk/reference/account.md) that the SDK uses for checks and transaction execution.

```typescript
'use client';

import { ConnectButton } from '@rainbow-me/rainbowkit';

export default function Home() {
  return (
    <main>
      <div>
        <ConnectButton />
      </div>
    </main>
  );
}
```

2. Implement Minting Logic in [MintButton.tsx](https://github.com/manifoldxyz/client-sdk/blob/main/packages/examples/edition/rainbowkit-mint/src/components/MintButton.tsx)

```typescript
'use client';

import { ConnectButton } from '@rainbow-me/rainbowkit';
import { MintButton } from '@/components/MintButton';

export default function Home() {
  return (
    <main>
      <h1>
        Manifold SDK + RainbowKit
      </h1>

      <div>
        <ConnectButton />
        <MintButton />
      </div>
    </main>
  );
}
```

**Core Steps**

a. Create a [Manifold Client](/client-sdk/sdk/manifold-client.md) with a public provider

```typescript
import { createClient, createPublicProviderWagmi } from '@manifoldxyz/client-sdk';
import { useConfig } from 'wagmi';

// Get the Wagmi config from your React context
const config = useConfig();

// Create a public provider using Wagmi config
const publicProvider = createPublicProviderWagmi({ config });

// Initialize the client
const client = createClient({ publicProvider });
```

b. Create an [Account](/client-sdk/reference/account.md) representing the connected user.

```typescript
import { createAccountViem } from '@manifoldxyz/client-sdk';
import { useWalletClient } from 'wagmi';

// Get the wallet client from wagmi
const { data: walletClient } = useWalletClient();

// Create the account adapter
const account = createAccountViem({
  walletClient,
});
```

c. Fetch the product and verify its type

```typescript
const product = await client.getProduct(INSTANCE_ID) as EditionProduct;
```

d. Check the product status to ensure it’s still active

```typescript
const productStatus = await product.getStatus();
if (productStatus !== 'active') {
  throw new Error(`Product is ${productStatus}`);
}
```

e. Prepare the purchase by specifying the amount

```typescript
const preparedPurchase = await product.preparePurchase({
  address: address,
  payload: {
    quantity: 1,
  },
});
```

f. Execute the purchase

```typescript
const order = await product.purchase({
  account,
  preparedPurchase,
});
```

Key points:

* `createAccountViem` wraps wagmi’s wallet client so the SDK can sign and send transactions on the user’s behalf.
* `preparePurchase` performs all eligibility checks (allowlists, supply, promo codes) and returns the total cost breakdown. Supply the same `account` so balance checks run against the connected wallet.
* `purchase` executes the transaction sequence (ERC-20 approvals, mint, etc.) and returns a [Receipt](/client-sdk/reference/receipt.md) with the final transaction hash and minted tokens.

**Display token media and on-chain stats**

You can enrich the UI with product art and live supply data directly from the SDK:

```typescript
const product = await client.getProduct(instanceId);

// Off-chain media and metadata (safe to render immediately)
const { asset, title, contract } = product.data.publicData;
const media = await product.getPreviewMedia();
const imageUrl = media?.image;
const animationUrl = media?.animation;

// Fetch on-chain data once (cost, supply, timing)
const onchainData = await product.fetchOnchainData();
const { totalMinted, totalSupply, startDate, endDate, cost } = onchainData;

return (
  <section>
    {imageUrl && <img src={imageUrl} alt={title} />}
    {animationUrl && (
      <video src={animationUrl} autoPlay loop muted playsInline />
    )}

    <dl>
      <dt>Price</dt>
      <dd>{cost.formatted}</dd>
      <dt>Minted</dt>
      <dd>{totalMinted}</dd>
      <dt>Total supply</dt>
      <dd>{totalSupply === -1 ? 'Unlimited' : totalSupply}</dd>
      <dt>Start date</dt>
      <dd>{startDate?.toLocaleString() ?? 'TBD'}</dd>
      <dt>End date</dt>
      <dd>{endDate?.toLocaleString() ?? 'Open'}</dd>
      <dt>Contract</dt>
      <dd>{contract.address}</dd>
    </dl>
  </section>
);
```

Best practices:

* **Check status** with [getStatus](/client-sdk/sdk/product/common/getstatus.md) before attempting a purchase to verify the product is active.
* **Handle** [**ClientSDKError**](/client-sdk/reference/clientsdkerror.md) **codes** for common cases such as ineligibility, sold-out items, or insufficient funds.
* Call [`getAllocations`](/client-sdk/sdk/product/common/getallocations.md) when you need to show remaining allowlist spots.
* Inspect [`Receipt.order`](/client-sdk/reference/order.md) to display which tokens were minted after `purchase`.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.manifold.xyz/client-sdk/guides/creating-a-react-minting-app.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
