---
title: "FitaLabs Gateway — 1P Bundle"
description: "Documentation: FitaLabs Gateway — 1P Bundle"
type: reference
tags: [infra, bundle, 1p, spa, cdn, reverse-engineering]
timestamp: 2026-07-06
---

# FitaLabs Gateway — 1P Bundle

Hosting the Claude Desktop 1P bundle on `claude.unifita.app`.

## Bundle Origin

The 1P bundle was extracted from Desktop running in 1P mode (buildType=dev) via CDP
(Chrome DevTools Protocol) using Bezetacil Debugger Spy.

**Original location**: `~/.bezetacil/workdir/claude-desktop/ion-dist/`
**Extraction method**: `webContents.executeJavaScript` + CDP Network capturing
**Extraction date**: Jun 24, 2026

## Files

### Main bundle (CDN)
| File | Size | Description |
|------|------|-------------|
| `index-BW29VlNm.js` | 7.2 MB | Complete React webapp (voice, UI, GrowthBook) |
| `c6a992d55-CvsZ6KID.css` | 758 KB | Design system @ant-cds + Tailwind |
| `cf1a02a1a-CnIZRMjU.css` | 26 KB | Component styles |
| `f12a4347e1080fb88155.js` | 5 KB | Bootstrap/loader |
| `s.js` | 20 KB | Service worker / preload |

### Chunks (code splitting)
35+ vendor-*.js and c*.js files downloaded from CDN:
- Vendor: react, router, zustand, zod, intl, radix, lodash, query, motion, base-ui, luxon, growthbook, virtual, icons
- App: ~20 chunks with hash in name (c34d1f91f-DIhRpeoW.js, c32f15cb4-Bt8FU9pE.js, etc)

### Local assets (from .vite/renderer)
| File | Size | Description |
|------|------|-------------|
| `main_window/index.html` | 109 KB | Electron shell (title bar + error UI) |
| `main_window/window-shared.css` | 5 KB | Shell styles |
| `assets/main-Bh0l-09t.js` | 291 KB | React shell |
| `assets/MainWindowPage-1yenKknx.js` | 13 KB | UI components |
| Anthropic fonts | 4 .ttf files | AnthropicSans + AnthropicSerif |

## Server Structure

```
/var/www/claude/
├── index.html                          # SPA loader (created by us)
├── index-BW29VlNm.js                   # 7.2 MB — React app
├── vendor-*.js                         # 15+ vendor chunks
├── c*.js                               # 20+ app chunks
├── c*.css                              # 6+ stylesheets
├── assets/                             # Anthropic fonts
│   ├── AnthropicSans-Roman-Variable-DCEzLfgm.ttf
│   ├── AnthropicSans-Italic-Variable-Dqj5mHDM.ttf
│   ├── AnthropicSerif-Roman-Variable-D05ngSTe.ttf
│   └── AnthropicSerif-Italic-Variable-B9Ik5ODi.ttf
└── i18n/                               # Internationalization (stubs)

    ├── en-US.json
    ├── pt-BR.json
    └── dynamic/
        ├── en-US.json
        └── pt-BR.json
```

## Loader HTML

```html
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Claude</title>
  <link rel="stylesheet" href="/c6a992d55-CvsZ6KID.css">
  <link rel="stylesheet" href="/cf1a02a1a-CnIZRMjU.css">
  <link rel="stylesheet" href="/vendor-ant-cds-D6IJ1PR1.css">
</head>
<body>
  <div id="root"></div>
  <script>
    // Kill old Service Workers — Caddy handles auth
    if ('serviceWorker' in navigator) {
      navigator.serviceWorker.getRegistrations().then(regs => {
        regs.forEach(r => r.unregister());
      });
    }
  </script>
  <script src="/index-BW29VlNm.js" type="module"></script>
</body>
</html>
```

## CDN Fallback

Chunks not previously downloaded are served on-demand by Caddy:

```
handle_errors 404 {
    rewrite * /claude-ai/v2/assets/v1{uri}
    reverse_proxy https://assets-proxy.anthropic.com
}
```

CDN URL: `https://assets-proxy.anthropic.com/claude-ai/v2/assets/v1/{chunk-name}`

## Code Discoveries

### IPC Bridge vs Fetch
In Electron, the SPA communicates via `window.claudeAppBindings` (IPC bridge).
In the browser, it does direct `fetch()` with `custom3pCompatible: !0`.

### Key Functions in Bundle
- `cde()` — query `GET /api/account_profile` with `queryKey: [Oo]`
- `dde()` — mutation `PUT /api/account_profile`
- `Xut()` — mutation `POST /api/accounts/me/organizations/get_or_create_chat_organization`
- `Cjt()` — hook that reads `account.invites.some(...)` to decide route
- `_hs()` — conditional renderer based on account state

### Onboarding Flow
1. SPA loads → `GET /edge-api/bootstrap` → checks `has_finished_claudeai_onboarding`
2. If false → redirects to `/onboarding`
3. Onboarding component → `PUT /api/account_profile` with `{has_finished_claudeai_onboarding: true}`
4. Redirects to `/new` (chat)

### Bug: `e?.invites.some`
- `Cjt()` does `e?.invites.some(...)` where `e` is account
- If account query fails (401, 502), `e` becomes `undefined`
- `undefined?.invites` = `undefined`, `.some()` breaks
- Fix: ensure account ALWAYS has `invites: []` and query never fails
- Caddy auth injection resolves the 401

## References
- [[fitalabs-gateway-1p-jornada]] — overview
- [[fitalabs-gateway-caddy]] — Caddy config
- [[fitalabs-gateway-auth]] — authentication flow
