# Deploy a React app (/guides/deploy-react)



<Callout type="warn" title="Legacy guide - retired af CLI">
  This page was written for the retired `af` CLI and the sites/storage workflow.
  The current CLI is `acc` (compute services), which does not include these
  commands yet. Commands on this page will not work with `acc`. Kept for
  reference while this functionality is rebuilt.
</Callout>

Deploy your React application to decentralized infrastructure using Alternate Futures. This guide covers both Vite-based and Create React App projects.

## Prerequisites [#prerequisites]

Before you begin, make sure you have:

* **An Alternate Futures account** - [Sign up here](https://clouds.alternatefutures.ai) (free, no credit card required)
* **The AF CLI installed** - `npm install -g @alternatefutures/cli`
* **Node.js 18 or later** - [Download here](https://nodejs.org/en/download)
* **A React project** (or we will create one below)

## Quick Deploy (Existing React Project) [#quick-deploy-existing-react-project]

If you already have a React project, deploy it in three commands:

<Tabs items="[&#x22;Vite&#x22;,&#x22;Create React App&#x22;]">
  <Tab value="Vite">
    ```bash
    # Build the production bundle
    npm run build

    # Initialize AF configuration
    af sites init

    # Deploy to IPFS
    af sites deploy
    ```
  </Tab>

  <Tab value="Create React App">
    ```bash
    # Build the production bundle
    npm run build

    # Initialize AF configuration (set output directory to 'build')
    af sites init

    # Deploy to IPFS
    af sites deploy
    ```
  </Tab>
</Tabs>

<Callout type="info" title="Output Directory">
  * **Vite projects** output to `./dist` by default
  * **Create React App projects** output to `./build` by default

  Set the correct directory when running `af sites init`.
</Callout>

## Step 1: Create a New React Project [#step-1-create-a-new-react-project]

If you do not have a project yet, start from our template or create one from scratch.

### Option A: Use the AF Template (Recommended) [#option-a-use-the-af-template-recommended]

```bash
# Clone the AF-optimized React template
git clone https://github.com/alternatefutures/template-react my-react-app
cd my-react-app

# Install dependencies
npm install
```

### Option B: Create with Vite (Recommended) [#option-b-create-with-vite-recommended]

```bash
# Create a new React + Vite project
npm create vite@latest my-react-app -- --template react-ts
cd my-react-app

# Install dependencies
npm install
```

### Option C: Create with Create React App [#option-c-create-with-create-react-app]

```bash
# Create a new CRA project
npx create-react-app my-react-app --template typescript
cd my-react-app

# Install dependencies
npm install
```

## Step 2: Configure for Deployment [#step-2-configure-for-deployment]

### Vite Configuration [#vite-configuration]

Vite projects work out of the box with Alternate Futures. No additional configuration is needed for basic deployments.

If you need a custom base path, edit `vite.config.ts`:

```ts
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],

  // Set base path if deploying to a subdirectory
  // base: '/my-app/',

  build: {
    // Output directory (default: 'dist')
    outDir: 'dist',

    // Generate source maps for debugging (optional)
    sourcemap: false,
  },
});
```

### Create React App Configuration [#create-react-app-configuration]

CRA projects also work out of the box. If you need a custom base path, set the `homepage` field in `package.json`:

```json
{
  "homepage": ".",
  "scripts": {
    "build": "react-scripts build"
  }
}
```

<Callout type="info" title="Setting homepage to '.'">
  Setting `homepage` to `"."` ensures all asset paths are relative, which is important for IPFS deployments where your site may be served from different gateway URLs.
</Callout>

## Step 3: Build Your Project [#step-3-build-your-project]

<Tabs items="[&#x22;Vite&#x22;,&#x22;Create React App&#x22;]">
  <Tab value="Vite">
    ```bash
    # Build the production bundle
    npm run build

    # Preview locally (optional)
    npm run preview
    ```
  </Tab>

  <Tab value="Create React App">
    ```bash
    # Build the production bundle
    npm run build

    # Preview locally (optional)
    npx serve build
    ```
  </Tab>
</Tabs>

## Step 4: Authenticate with AF [#step-4-authenticate-with-af]

If you have not already authenticated:

```bash
# Interactive login (opens browser)
af login

# Or use a Personal Access Token
export AF_TOKEN=pat_your_token_here
```

## Step 5: Initialize and Deploy [#step-5-initialize-and-deploy]

<Tabs items="[&#x22;Vite&#x22;,&#x22;Create React App&#x22;]">
  <Tab value="Vite">
    ```bash
    # Initialize AF site configuration
    af sites init

    # When prompted, configure:
    #   Site name: my-react-app
    #   Build command: npm run build
    #   Output directory: dist
    #   Storage network: ipfs

    # Deploy to decentralized storage
    af sites deploy
    ```
  </Tab>

  <Tab value="Create React App">
    ```bash
    # Initialize AF site configuration
    af sites init

    # When prompted, configure:
    #   Site name: my-react-app
    #   Build command: npm run build
    #   Output directory: build
    #   Storage network: ipfs

    # Deploy to decentralized storage
    af sites deploy
    ```
  </Tab>
</Tabs>

You should see output like:

```
  Building site...
  Uploading files to IPFS...
  Deployment successful!
  CID: bafybei...
  URL: https://ipfs.io/ipfs/bafybei...
```

## Step 6: Handle Client-Side Routing [#step-6-handle-client-side-routing]

If your React app uses React Router (or any client-side routing), you need to handle the case where users navigate directly to a route like `/about`. On a traditional server, this would return a 404 because `/about/index.html` does not exist.

### Solution: Add a 404 Redirect [#solution-add-a-404-redirect]

Create a `public/_redirects` file (for Vite) or a `_redirects` file in your `public/` folder (for CRA):

```
/*    /index.html   200
```

This tells the gateway to serve `index.html` for all routes, letting React Router handle the routing.

### Alternative: Use Hash Router [#alternative-use-hash-router]

If redirects are not available, switch to `HashRouter`:

```tsx
import { HashRouter, Routes, Route } from 'react-router-dom';

function App() {
  return (
    <HashRouter>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/about" element={<About />} />
      </Routes>
    </HashRouter>
  );
}
```

Hash-based URLs (e.g., `/#/about`) work on any static server without configuration.

## Automating Deployments with CI/CD [#automating-deployments-with-cicd]

Deploy automatically on every push using GitHub Actions:

```yaml
# .github/workflows/deploy.yml
name: Deploy to Alternate Futures

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install dependencies
        run: npm install

      - name: Build
        run: npm run build

      - name: Deploy to AF
        run: npx @alternatefutures/cli sites deploy ./dist --network ipfs
        env:
          AF_TOKEN: ${{ secrets.AF_TOKEN }}
```

See [CI/CD Integration](./cicd.md) for more providers.

## Using the SDK [#using-the-sdk]

Deploy programmatically with the Alternate Futures SDK:

```typescript
import { AlternateFuturesSdk, PersonalAccessTokenService } from '@alternatefutures/sdk/node';

const af = new AlternateFuturesSdk({
  accessTokenService: new PersonalAccessTokenService({
    personalAccessToken: process.env.AF_TOKEN,
    projectId: process.env.AF_PROJECT_ID,
  }),
});

// Deploy the build output
const result = await af.ipfs().add('./dist');
console.log('Deployed! CID:', result.pin.cid);
```

## Environment Variables [#environment-variables]

### Vite [#vite]

Vite exposes environment variables prefixed with `VITE_` to your application:

```bash
# .env
VITE_API_URL=https://api.example.com
VITE_APP_TITLE=My App
```

Access them in your code:

```tsx
const apiUrl = import.meta.env.VITE_API_URL;
```

### Create React App [#create-react-app]

CRA exposes variables prefixed with `REACT_APP_`:

```bash
# .env
REACT_APP_API_URL=https://api.example.com
REACT_APP_TITLE=My App
```

Access them in your code:

```tsx
const apiUrl = process.env.REACT_APP_API_URL;
```

<Callout type="warn" title="Security">
  Environment variables prefixed with `VITE_` or `REACT_APP_` are embedded in your build output and visible to anyone who inspects your site. Never put secrets (API keys, tokens) in client-side environment variables.
</Callout>

## Common Issues [#common-issues]

### "Page not found" on route refresh [#page-not-found-on-route-refresh]

Your app uses client-side routing but the static server cannot find the route. See the [Handle Client-Side Routing](#step-6-handle-client-side-routing) section above.

### "Build output is too large" [#build-output-is-too-large]

* Enable code splitting (Vite does this automatically)
* Use `React.lazy()` for route-based code splitting
* Analyze your bundle: `npx vite-bundle-visualizer` (Vite) or `npx source-map-explorer build/static/js/*.js` (CRA)
* Remove unused dependencies

### "Assets not loading after deployment" [#assets-not-loading-after-deployment]

* Make sure `base` in `vite.config.ts` is set to `'/'` or `'./'`
* For CRA, set `"homepage": "."` in `package.json`
* Check that asset paths are relative, not absolute

### "Blank white page after deployment" [#blank-white-page-after-deployment]

* Open the browser console for JavaScript errors
* Verify the `index.html` file references the correct bundle paths
* Try building with `npm run build` and testing locally with `npx serve dist` before deploying

## Next Steps [#next-steps]

* [Custom Domains](./custom-domains.md) - Connect your own domain
* [CI/CD Integration](./cicd.md) - Automate deployments
* [Storage Management](./storage.md) - Choose the right storage network
* [Deploy Next.js](./deploy-nextjs.md) - Deploy a Next.js app
* [Deploy Astro](./deploy-astro.md) - Deploy an Astro site
