> ## Documentation Index
> Fetch the complete documentation index at: https://docs.shipnative.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Web Deployment

> Deploy your Shipnative app as a web application

Shipnative fully supports web deployment via Expo Web. Your React Native app runs on iOS, Android, **and** web from a single codebase.

<Tip>
  **Same code, three platforms.** You don't need to maintain a separate web app - your React Native code works on web automatically via react-native-web.
</Tip>

***

## Quick Start

Build and preview your web app:

```bash theme={null}
cd apps/app

# Development
yarn web              # Start dev server at localhost:19006

# Production build
yarn bundle:web       # Creates optimized build in web-build/
```

***

## What Works on Web

Everything! Shipnative's architecture ensures feature parity across platforms:

| Feature            | Web Support                               |
| ------------------ | ----------------------------------------- |
| **UI Components**  | Unistyles 3.0 fully supports web          |
| **Authentication** | Supabase (email/password + OAuth)         |
| **Social Login**   | Google & Apple OAuth via browser redirect |
| **Payments**       | RevenueCat Web Billing                    |
| **Analytics**      | PostHog JavaScript SDK                    |
| **Error Tracking** | Sentry Browser SDK                        |
| **Dark Mode**      | Automatic theme switching                 |
| **Navigation**     | React Navigation web support              |

***

## Deployment Options

### Vercel (Recommended)

1. Push your code to GitHub
2. Import project at [vercel.com](https://vercel.com)
3. Set **Root Directory** to `apps/app`
4. Set **Build Command** to `yarn bundle:web`
5. Set **Output Directory** to `web-build`
6. Add environment variables (from your `.env`)
7. Deploy!

### Netlify

1. Import repo at [netlify.com](https://netlify.com)
2. Set **Base directory** to `apps/app`
3. Set **Build command** to `yarn bundle:web`
4. Set **Publish directory** to `apps/app/web-build`
5. Add environment variables
6. Deploy!

### Other Platforms

The web build is a static site, so it works anywhere:

* Cloudflare Pages
* AWS Amplify
* GitHub Pages
* Firebase Hosting
* Any static host

***

## Environment Variables

Web builds need the same `EXPO_PUBLIC_*` variables as mobile:

```bash theme={null}
# Required for production
EXPO_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY=your-key

# Payments (RevenueCat Web Billing)
EXPO_PUBLIC_REVENUECAT_WEB_KEY=your-web-key

# Analytics
EXPO_PUBLIC_POSTHOG_API_KEY=your-posthog-key
EXPO_PUBLIC_POSTHOG_HOST=https://app.posthog.com

# Error tracking
EXPO_PUBLIC_SENTRY_DSN=your-sentry-dsn
```

<Warning>
  **CORS Configuration:** Add your web domain to Supabase's allowed origins:

  1. Go to Supabase Dashboard → Project Settings → API
  2. Add your domain to "Allowed Origins (CORS)"
  3. Include `http://localhost:19006` for local development
</Warning>

***

## Social Login on Web

Google and Apple OAuth work on web via browser redirects. See [Social Login → Web OAuth Setup](/core-features/social-login#web-oauth-setup) for configuration details.

**Quick checklist:**

* Add redirect URLs to Supabase: `https://yourapp.com/auth/callback`
* Add JavaScript origins to Google Cloud Console: `https://yourapp.com`
* Ensure CORS is configured (see warning above)

***

## RevenueCat Web Billing

RevenueCat supports web subscriptions via their Web Billing feature:

1. Enable Web Billing in your RevenueCat project
2. Connect a payment gateway (Stripe recommended)
3. Add `EXPO_PUBLIC_REVENUECAT_WEB_KEY` to your environment
4. Create web-specific products in RevenueCat dashboard

The `PaywallScreen` automatically detects the web platform and uses the web SDK.

***

## Web-Specific Considerations

### Responsive Design

Shipnative uses Unistyles breakpoints for responsive layouts:

```typescript theme={null}
const styles = StyleSheet.create((theme, runtime) => ({
  container: {
    // Mobile-first
    flexDirection: 'column',
    padding: theme.spacing.md,
    
    // Tablet+
    variants: {
      breakpoint: {
        md: {
          flexDirection: 'row',
          maxWidth: 800,
        },
      },
    },
  },
}))
```

### Navigation on Web

React Navigation handles web routing automatically:

* Screen names become URL paths
* Back button works with browser history
* Deep linking supported

### SEO

For better SEO, consider:

* Adding meta tags via `expo-document-picker` or custom HTML
* Using semantic HTML elements
* Implementing proper heading hierarchy

***

## Troubleshooting

<AccordionGroup>
  <Accordion title="Vercel: 'Missing required environment variables' error">
    **Issue:** Expo web builds deployed to Vercel fail with:

    ```
    Missing required environment variables: supabaseUrl, supabasePublishableKey
    ```

    **Why this happens:** Metro doesn't inline `process.env.EXPO_PUBLIC_*` variables for web builds the way it does for native. The app falls back to reading from `Constants.expoConfig.extra`, which requires the variables to be explicitly passed in `app.config.ts`.

    **Solution:** This is already fixed in the boilerplate. The `app.config.ts` includes an `extra` section that passes all `EXPO_PUBLIC_*` variables through to `Constants.expoConfig.extra`. Just make sure you have the latest boilerplate version.

    If you're on an older version, add this to your `app.config.ts`:

    ```typescript theme={null}
    return {
      ...baseConfig,
      extra: {
        ...baseConfig.extra,
        supabase_url: process.env.EXPO_PUBLIC_SUPABASE_URL,
        supabase_publishable_key: process.env.EXPO_PUBLIC_SUPABASE_PUBLISHABLE_KEY,
        // ... other env vars
      },
      // ... rest of config
    }
    ```
  </Accordion>

  <Accordion title="CORS errors">
    Add your domain to Supabase's allowed origins:

    * Dashboard → Project Settings → API → Allowed Origins
    * Include both development (`localhost:19006`) and production URLs
  </Accordion>

  <Accordion title="Styles look different on web">
    Some React Native styles don't translate perfectly to web. Check:

    * Shadow properties (use `boxShadow` for web)
    * Touch feedback (may need web-specific hover states)
    * Fonts (ensure web fonts are loaded)
  </Accordion>

  <Accordion title="Build fails with 'window is not defined'">
    Some native-only packages reference `window`. Fix:

    1. Check if the package supports web
    2. Use platform-specific imports: `MyComponent.web.tsx` / `MyComponent.tsx`
    3. Add to Metro's `resolver.resolveRequest` if needed
  </Accordion>
</AccordionGroup>

***

## Marketing Page vs App Web Build

Shipnative includes **two** web experiences:

|               | App Web Build               | Marketing Page          |
| ------------- | --------------------------- | ----------------------- |
| **Location**  | `apps/app` (this guide)     | `apps/web`              |
| **Purpose**   | Full app running in browser | Landing/waitlist page   |
| **Framework** | Expo Web + react-native-web | Vite + React + Tailwind |
| **Styling**   | Unistyles 3.0               | Tailwind CSS            |
| **Deploy**    | Your app domain             | Your marketing domain   |

[Learn about the marketing page →](/getting-started/marketing-page)
