Initial commit

This commit is contained in:
Trey
2026-03-20 18:49:48 -05:00
commit dfa1697fef
197 changed files with 29298 additions and 0 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,75 @@
{
"permissions": {
"allow": [
"Bash(npm create:*)",
"Bash(npm install)",
"Bash(npm install:*)",
"Bash(npx tailwindcss:*)",
"Bash(./node_modules/.bin/tailwindcss:*)",
"Bash(npm ls:*)",
"Bash(curl -s -X POST \"http://localhost:3000/api/firebase/v1/token?key=AIzaSyD9o9mzulN50-hqOwF6ww9pxUNUxwVOCXA\" -H \"Content-Type: application/json\" -d '{\"\"grantType\"\":\"\"refresh_token\"\",\"\"refreshToken\"\":\"\"AMf-vBxB7p1m84Jw8GNk1CsuEbgMInPt0lzOKXK81e-XiO13PUeA1VfkZ6gu29MN6izbLIWrBqeGaczU3DC5FY-vSePOoGAn3RZnjLWN2DzLmTiOiAH25UxTZPeE3d-g_8-JeBDgQptuP1xy1U0EGxM5msolSLEu8GBRnkxAtEhoIzVtyjCsaD1aBHdWqZiIPStLz-6YQj2j-pDoEVYr3aOBvNxnzv_vL4y91wFkVtMFaC0jOZZE39gbbSj5GH7JcHHiW-NJFcfD0BYKM9zfqs0SxPaYYuqTSQyS3lra1SVxn0XB-ZhcR-I\"\"}')",
"Bash(TOKEN=\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFjMzIxOTgzNGRhNTBlMjBmYWVhZWE3Yzg2Y2U3YjU1MzhmMTdiZTEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZjItcHJvZC01MzQ3NSIsImF1ZCI6ImYyLXByb2QtNTM0NzUiLCJhdXRoX3RpbWUiOjE3NTQ1MDU5NTEsInVzZXJfaWQiOiJkVkRCalVRakF2WHBZMWl0aUF1N2txOTdEUHkyIiwic3ViIjoiZFZEQmpVUWpBdlhwWTFpdGlBdTdrcTk3RFB5MiIsImlhdCI6MTc2OTI1NzIxNSwiZXhwIjoxNzY5MjYwODE1LCJlbWFpbCI6InJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiYXBwbGUuY29tIjpbIjAwMTc1MS45NTZkNjJkODA2YjY0ZTgzYjFhNTBmNjBkMDBhNDYyZi4wMTU3Il0sImVtYWlsIjpbInJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiYXBwbGUuY29tIn19.X6CSKNsEEoOOepMcSky4qkV2dnKmiZ8GI_9PkrWp0rAyGcD3HJFYJk3T5LmmP9lnyrAzIIRPeXQ0qHCN4ZLdzLNBu4gDdVDvlAKe0xX5DM2ee0goJAreS3Sy3SsEADsFLQvpaAT_aWkZj0bJ3nm_oAMQMu5VMqmuHyBPfxFhZNWErVmCahsZlIQnDJirI0r5k2wGPNZDdAzbaKESNFpU60EcxdWWGin7P0dUOADKftAdNbcr08Jtek17f0V3jma4N2F8lvS2IAW-2v-dDz1uOePCWHKeRH10TQQGqVR-vYoNU-ekHugpJ2tJ7qrME238R1IOuQRzLSJLMvwX9WuJ0A\")",
"Bash(__NEW_LINE_c7bab749a7abcf34__ curl -s -X POST \"http://localhost:3000/api/graphql\" -H \"Content-Type: application/json\" -H \"Accept: */*\" -H \"Authorization: Bearer $TOKEN\" -H \"x-profile-id: profile#73b79341-5ff8-411c-806f-5b25cb834471\" -H \"x-device-os: ios\" -H \"x-app-version: 8.7.8\" -H \"x-os-version: 18.6.2\" -H \"x-transaction-id: test-123\" -H \"x-event-analytics-id: 53923e7d-39bb-42ac-99c6-99cdf6008d11\" -d '{\"\"query\"\":\"\"query { profile\\(profileId: \\\\\"\"profile#73b79341-5ff8-411c-806f-5b25cb834471\\\\\"\"\\) { id imaginaryName } }\"\"}')",
"Bash(__NEW_LINE_f4d4c9f184cf811b__ curl -s -X POST \"http://localhost:3000/api/graphql\" -H \"Content-Type: application/json\" -H \"Accept: */*\" -H \"Authorization: Bearer $TOKEN\" -H \"x-profile-id: profile#73b79341-5ff8-411c-806f-5b25cb834471\" -H \"x-device-os: ios\" -H \"x-app-version: 8.7.8\" -H \"x-os-version: 18.6.2\" -H \"x-transaction-id: test-123\" -H \"x-event-analytics-id: 53923e7d-39bb-42ac-99c6-99cdf6008d11\" -d '{\"\"query\"\":\"\"query ProfileQuery\\($profileId: String!\\) { profile\\(id: $profileId\\) { id imaginaryName age gender } }\"\",\"\"variables\"\":{\"\"profileId\"\":\"\"profile#73b79341-5ff8-411c-806f-5b25cb834471\"\"}}')",
"Bash(curl:*)",
"Bash(node -e:*)",
"Bash(npx tsc:*)",
"Bash(unzip:*)",
"Bash(python3:*)",
"Bash(done)",
"Skill(frontend-design)",
"Bash(for f in request_*)",
"Bash(do if grep -q \"WhoLikesMe\\\\|whoLikesMe\\\\|filteredWhoLikesMe\" \"$f\")",
"Bash(then echo \"=== $f ===\")",
"Bash(fi)",
"Bash(do grep -l \"interactions\\\\|Interaction\\\\|whoLikes\\\\|whoPings\" \"$f\")",
"Bash(source /tmp/feeld_creds.sh)",
"Bash(docker restart:*)",
"Bash(docker logs:*)",
"Bash(cat:*)",
"Bash(docker-compose down:*)",
"Bash(docker-compose up:*)",
"Bash(docker ps:*)",
"Bash(docker exec feeld-web-nginx curl -s http://feeld-web-backend:3001/api/auth/login -X POST -H \"Content-Type: application/json\" -d '{\"\"username\"\":\"\"admin\"\",\"\"password\"\":\"\"feeld123\"\"}')",
"Bash(docker exec:*)",
"Bash(docker port:*)",
"Bash(nc:*)",
"Bash(docker-compose restart:*)",
"Bash(lsof:*)",
"Bash(docker network:*)",
"Bash(docker-compose build:*)",
"Bash(docker version:*)",
"Bash(osascript:*)",
"Bash(open:*)",
"Bash(zip:*)",
"Bash(for f in /Users/treyt/Desktop/code/Feeld/proxyman_extracted/request_*)",
"Bash(do)",
"Bash(if grep -l \"sendMessage\\\\|GetMessages\\\\|channel\\\\|chat.getstream\" \"$f\")",
"Bash(then)",
"Bash(echo:*)",
"Bash(ls:*)",
"Bash(grep:*)",
"Bash(npm run build:*)",
"Bash(timeout 15 npm run dev:*)",
"Bash(docker-compose ps:*)",
"Bash(docker-compose logs:*)",
"Bash(for f in /Users/treyt/Desktop/code/Feeld/proxyman_chat/request_*)",
"Bash(do echo \"=== $f ===\" cat \"$f\")",
"WebSearch",
"Bash(docker compose:*)",
"Bash(docker compose build:*)",
"Bash(ACCESS_TOKEN=\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFjMzIxOTgzNGRhNTBlMjBmYWVhZWE3Yzg2Y2U3YjU1MzhmMTdiZTEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZjItcHJvZC01MzQ3NSIsImF1ZCI6ImYyLXByb2QtNTM0NzUiLCJhdXRoX3RpbWUiOjE3NTQ1MDU5NTEsInVzZXJfaWQiOiJkVkRCalVRakF2WHBZMWl0aUF1N2txOTdEUHkyIiwic3ViIjoiZFZEQmpVUWpBdlhwWTFpdGlBdTdrcTk3RFB5MiIsImlhdCI6MTc2OTI3NTE3MCwiZXhwIjoxNzY5Mjc4NzcwLCJlbWFpbCI6InJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiYXBwbGUuY29tIjpbIjAwMTc1MS45NTZkNjJkODA2YjY0ZTgzYjFhNTBmNjBkMDBhNDYyZi4wMTU3Il0sImVtYWlsIjpbInJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiYXBwbGUuY29tIn19.wSyOIOlzhrWsjYrOKyFJReAx8xANive5sbvUk2RChQ6rmnOxkgTUQABrd3YXzBiz2qvtS1yESp2bEy3XdvdkPjvKg4RTe8xWaYIIwvajFRgmoQG_bE6GRyrrKzeqshe72klNUhEPJDLGy4ERPRHaCVp27GyN2pyLC1uAqCal6NjMafcBlxGJXe263a6naDdeyM1Zl_GxRgFbdrPWJ6Ua335DDaNVvToM9z73USzSACADccX0xX20vUBz-7TWnjfYjBFXRdbauawF3V7PqfGwuROPc_F7Zb1bxcZPWP37Rgg2m_BzMPzcOarxHITRqUrK5accSaML-Rogkf6fg4ZoWA\")",
"Bash(__NEW_LINE_f2a0275964ca9170__ curl -s -X POST 'https://core.api.fldcore.com/graphql' -H 'Content-Type: application/json' -H \"Authorization: Bearer $ACCESS_TOKEN\" -H 'x-profile-id: profile#73b79341-5ff8-411c-806f-5b25cb834471' -H 'x-device-os: ios' -H 'x-app-version: 8.7.8' -H 'x-os-version: 18.6.2' -H 'User-Agent: feeld-mobile' -d '{\"\"operationName\"\":\"\"ListSummaries\"\",\"\"variables\"\":{\"\"limit\"\":10},\"\"query\"\":\"\"query ListSummaries\\($limit: Int = 30, $cursor: String\\) { summaries: getChatSummariesForChatList\\(limit: $limit, cursor: $cursor\\) { nodes { id name type status streamChannelId } } }\"\"}')",
"Bash(TOKEN=\"eyJhbGciOiJSUzI1NiIsImtpZCI6IjFjMzIxOTgzNGRhNTBlMjBmYWVhZWE3Yzg2Y2U3YjU1MzhmMTdiZTEiLCJ0eXAiOiJKV1QifQ.eyJpc3MiOiJodHRwczovL3NlY3VyZXRva2VuLmdvb2dsZS5jb20vZjItcHJvZC01MzQ3NSIsImF1ZCI6ImYyLXByb2QtNTM0NzUiLCJhdXRoX3RpbWUiOjE3NTQ1MDU5NTEsInVzZXJfaWQiOiJkVkRCalVRakF2WHBZMWl0aUF1N2txOTdEUHkyIiwic3ViIjoiZFZEQmpVUWpBdlhwWTFpdGlBdTdrcTk3RFB5MiIsImlhdCI6MTc2OTI3NTI2MSwiZXhwIjoxNzY5Mjc4ODYxLCJlbWFpbCI6InJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImZpcmViYXNlIjp7ImlkZW50aXRpZXMiOnsiYXBwbGUuY29tIjpbIjAwMTc1MS45NTZkNjJkODA2YjY0ZTgzYjFhNTBmNjBkMDBhNDYyZi4wMTU3Il0sImVtYWlsIjpbInJ5NzRwMjV4MnZAcHJpdmF0ZXJlbGF5LmFwcGxlaWQuY29tIl19LCJzaWduX2luX3Byb3ZpZGVyIjoiYXBwbGUuY29tIn19.wVpZhw2K9hzusOg9i6WArHRs7B67yqM-mHQyBLtoRK1apUcdZsbQRGI9en2FE4NLX2NowWKEKodMED9OfHQZTWbdo2z2kPXmdCffYF-63zuZWZQ4qJ7Y6yjJ4NSF_AnFbKBYYkvELW91JbPOJGGCn3cRjmKSPU4-5rGobI17J6R_Pt0Eftsw9B3pLoHaIRnW_iS3j1oJ6UweuMI331FOdc8gQkvsd4ahFoE7MvBsSvO2-IhMZcc53m5yavvPGhOoh6kEVNlEcNUQG8s_gbpOBMsROsgl_sgf8TNNUKXaE6iFZdBzIXFQ9QzO1RvZ_JdnGDTIch71BATOcqlP1FRaSg\")",
"Bash(xargs:*)",
"Bash(chmod:*)",
"Bash(docker info:*)",
"Bash(docker-compose exec:*)",
"Bash(sshpass:*)",
"Bash(ssh:*)",
"Bash(sort:*)",
"Bash(for f in /Users/treyt/Desktop/code/Feeld/ping_calls/profile_update_logs/request_*)",
"Bash(find:*)"
]
}
}

4780
API_DOCUMENTATION.md Normal file

File diff suppressed because it is too large Load Diff

379
claude.md Normal file
View File

@@ -0,0 +1,379 @@
# Feeld Web Client
A React/TypeScript web application that provides browser-based access to the Feeld dating platform. Connects to the same GraphQL backend as the mobile app using Firebase authentication.
## Quick Start
```bash
cd web
npm install
npm run dev:all # Starts both Vite dev server and Express backend
```
- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
## Project Structure
```
/Feeld
├── web/ # Main React application
│ ├── src/
│ │ ├── api/ # API layer
│ │ │ ├── auth.ts # Firebase token management (AuthManager class)
│ │ │ ├── client.ts # Apollo GraphQL client setup
│ │ │ ├── dataSync.ts # localStorage + server sync service
│ │ │ └── operations/ # GraphQL queries and mutations
│ │ │ ├── queries.ts
│ │ │ ├── mutations.ts
│ │ │ └── experimental.ts
│ │ ├── components/
│ │ │ ├── ui/ # Shared UI primitives
│ │ │ │ ├── Avatar.tsx # Profile avatar with fallback
│ │ │ │ ├── Badge.tsx # Status/tag badges
│ │ │ │ ├── Button.tsx # Styled button component
│ │ │ │ ├── Card.tsx # Card container
│ │ │ │ ├── Loading.tsx # Loading spinner/skeleton
│ │ │ │ └── ProxiedImage.tsx # Image component with proxy URL handling
│ │ │ ├── layout/ # Layout and Navigation
│ │ │ │ ├── Layout.tsx # Main layout wrapper with nav
│ │ │ │ └── Navigation.tsx # Side rail (desktop) / bottom bar (mobile)
│ │ │ ├── profile/ # Profile display components
│ │ │ │ ├── ProfileCard.tsx # Profile card (used in Likes, Discover, etc.)
│ │ │ │ ├── ProfileDetailModal.tsx # Full profile modal with partner nav
│ │ │ │ └── PingModal.tsx # Send ping modal with message
│ │ │ ├── chat/ # Chat components
│ │ │ │ └── ChatListItem.tsx
│ │ │ └── LoginPage.tsx
│ │ ├── pages/ # Route pages
│ │ │ ├── Discover.tsx # Profile discovery feed with scanner
│ │ │ ├── Likes.tsx # Likes/Pings/You Liked/Passed (4 tabs)
│ │ │ ├── SentPings.tsx # Outbound pings tracker
│ │ │ ├── Messages.tsx # Chat list
│ │ │ ├── Chat.tsx # Individual conversation
│ │ │ ├── Profile.tsx # Own profile view
│ │ │ ├── Settings.tsx # App settings
│ │ │ └── ApiExplorer.tsx # Debug tool for testing GraphQL
│ │ ├── hooks/ # Custom React hooks
│ │ │ ├── useAuth.tsx # Authentication context/provider
│ │ │ ├── useLocation.tsx # Location context with geocoding
│ │ │ ├── useLikedProfiles.ts
│ │ │ ├── useDislikedProfiles.ts # Track passed/disliked profiles
│ │ │ └── useSentPings.ts # Track outbound pings
│ │ ├── context/
│ │ │ └── StreamChatContext.tsx # Stream Chat SDK provider
│ │ ├── config/
│ │ │ └── constants.ts # API URLs, headers, credentials
│ │ ├── utils/
│ │ │ └── images.ts # Image URL proxying
│ │ ├── App.tsx # Root component with providers
│ │ └── main.tsx # Entry point
│ ├── server/
│ │ └── index.js # Express backend for data persistence
│ ├── vite.config.ts # Vite bundler config with API proxies
│ ├── package.json
│ ├── docker-compose.yml # Docker stack for Unraid production
│ └── docker-compose.local.yml # Docker stack for local development
├── proxyman_extracted/ # Captured API requests/responses
├── proxyman_chat/ # Captured Stream Chat API data
├── stream_extracted/ # Stream Chat SDK captures
└── API_DOCUMENTATION.md # Comprehensive API docs (4780 lines)
```
## Architecture
### Stack
- **React 19** with TypeScript
- **Apollo Client 4** for GraphQL
- **Stream Chat SDK** for real-time messaging
- **Tailwind CSS 4** for styling
- **Vite 7** for bundling
- **Express 5** for local backend
### State Management
- **React Context** for global state (Auth, StreamChat, Location)
- **Apollo Client cache** for GraphQL data
- **localStorage** for offline persistence with server sync
### Provider Hierarchy
```tsx
<AuthProvider>
<ApolloProvider>
<StreamChatProvider>
<LocationProvider>
<BrowserRouter>
<Routes />
</BrowserRouter>
</LocationProvider>
</StreamChatProvider>
</ApolloProvider>
</AuthProvider>
```
## Key Files
| File | Purpose |
|------|---------|
| `web/src/App.tsx` | Root component with all providers |
| `web/src/api/client.ts` | Apollo GraphQL client with auth headers |
| `web/src/api/auth.ts` | Firebase token refresh (AuthManager singleton) |
| `web/src/api/dataSync.ts` | Dual storage: localStorage + backend server |
| `web/src/config/constants.ts` | API endpoints, credentials, headers |
| `web/src/hooks/useAuth.tsx` | Auth context and login/logout |
| `web/src/context/StreamChatContext.tsx` | Stream Chat initialization |
| `web/src/components/profile/ProfileCard.tsx` | Profile card with `safeText()` rendering |
| `web/src/pages/Likes.tsx` | Likes page with enrichment, scanner, auto-refresh |
| `web/server/index.js` | Express backend for data persistence |
| `API_DOCUMENTATION.md` | Full API reference from reverse engineering |
## API Integration
### GraphQL Backend
- **Endpoint**: `https://core.api.fldcore.com/graphql` (proxied via Vite)
- **Client**: Apollo Client with auth link middleware
- **Key queries**: `ProfileQuery`, `DiscoverProfiles`, `WhoLikesMe`, `ListSummaries`
- **Key mutations**: `ProfileLike`, `ProfileDislike`, `DeviceLocationUpdate`, `SearchSettingsUpdate`
### Required Headers
```typescript
{
'Authorization': 'Bearer <firebase_jwt>',
'x-profile-id': 'profile#<uuid>',
'x-app-version': '8.8.3',
'x-device-os': 'ios',
'x-os-version': '18.6.2',
'x-transaction-id': '<uuid>',
'x-event-analytics-id': '<uuid>'
}
```
### Firebase Authentication
- Token refresh via `https://securetoken.googleapis.com/v1/token`
- AuthManager class handles automatic refresh with 1-minute buffer
- Tokens stored in memory, refresh token in localStorage
### Stream Chat
- Real-time messaging via Stream Chat SDK
- Credentials fetched via `StreamCredentialsQuery` GraphQL
- API Key: `y4tp4akjeb49`
### Local Backend Endpoints
```
GET/PUT /api/data/:userId # Full user data
GET/PUT /api/data/:userId/:key # Specific key
DELETE /api/data/:userId/:key # Delete key
POST /api/data/:userId/liked-profiles
DELETE /api/data/:userId/liked-profiles/:profileId
GET/POST /api/disliked-profiles # Passed/disliked profiles cache
DELETE /api/disliked-profiles/:id # Remove from passed
GET/POST /api/who-liked-you # Cache profiles that liked user
GET/POST /api/sent-pings # Track outbound pings
PUT /api/sent-pings/:targetProfileId # Update ping status
DELETE /api/sent-pings/:targetProfileId # Remove sent ping
POST /api/auth/login
GET /api/auth/verify
POST /api/auth/logout
GET /api/health
```
## Data Persistence
Hybrid localStorage + server approach in `dataSync.ts`:
1. **Write**: localStorage immediately → sync to server
2. **Read**: Try server first → fallback to localStorage
3. **Health check**: Server ping every 30 seconds
Keys synced: `liked_profiles`, `disliked_profiles`, `who_liked_you_profiles`, `locations`, `credentials`, `current_location`, `analytics_id`
## Routes
| Path | Page | Description |
|------|------|-------------|
| `/discover` | DiscoverPage | Profile discovery feed with scanner |
| `/likes` | LikesPage | Likes / Pings / You Liked / Passed (4 tabs) |
| `/sent-pings` | SentPingsPage | Outbound pings tracker |
| `/messages` | MessagesPage | Chat conversation list |
| `/chat/:channelId` | ChatPage | Individual chat |
| `/profile` | ProfilePage | Own profile view |
| `/settings` | SettingsPage | Location, search settings, credentials |
| `/api-explorer` | ApiExplorerPage | Debug tool for testing GraphQL queries |
## Development
### Scripts
```bash
npm run dev # Vite dev server only
npm run server # Express backend only
npm run dev:all # Both in parallel (recommended)
npm run build # Production build
npm run lint # ESLint check
npm run docker:local # Start local Docker stack
npm run docker:local:down # Stop local Docker stack
npm run docker:local:logs # View local Docker logs
```
### Vite Proxy Configuration
The Vite dev server proxies requests to bypass CORS:
**External APIs:**
- `/api/graphql``core.api.fldcore.com` (GraphQL backend)
- `/api/firebase``securetoken.googleapis.com` (auth tokens)
- `/api/images``res.cloudinary.com` (profile images)
- `/api/fldcdn``prod.fldcdn.com` (CDN assets)
**Local backend:**
- `/api/who-liked-you``localhost:3001`
- `/api/sent-pings``localhost:3001`
- `/api/disliked-profiles``localhost:3001`
- `/api/data``localhost:3001`
- `/api/auth``localhost:3001`
- `/api/health``localhost:3001`
Mobile app User-Agent is injected on external proxies to bypass hotlink protection.
### Docker
Two compose files:
- **`docker-compose.yml`** - Production config for Unraid server (absolute paths to `/mnt/user/appdata/FeeldWeb`)
- **`docker-compose.local.yml`** - Local dev config (relative paths)
```bash
# Local development
docker compose -f docker-compose.local.yml up -d --build
# Production (on Unraid server)
cd /mnt/user/appdata/FeeldWeb && docker compose up -d --build
```
- Frontend: port 3000 (Vite dev server)
- Backend: port 3001 (Express)
- Nginx: port 7743 (reverse proxy)
## Testing
No automated tests currently. Manual testing via:
- `/api-explorer` route for GraphQL query testing
- Console logging throughout codebase
- `/api/health` endpoint for backend status
## Credentials & Configuration
Credentials are stored in `constants.ts` and localStorage:
- `feeld_profile_id` - Current profile UUID
- `feeld_refresh_token` - Firebase refresh token
- `feeld_auth_token` - Current session token
- `feeld_analytics_id` - Event tracking ID
## Features
### Likes Page (4 Tabs)
- **Likes**: Profiles that have liked you, enriched with cached data from `/api/who-liked-you`
- **Pings**: Profiles that pinged you (liked with a message)
- **You Liked**: Profiles you've liked
- **Passed**: Profiles you've disliked/passed on, stored via `/api/disliked-profiles`
**Enrichment**: WhoLikesMe API returns limited data (null photos for non-Majestic users). Cached profile data from the scanner (Discover API) is merged in via `useMemo`. Older likes (further down the list) get matched first to preserve chronological accuracy when multiple people share the same name.
**Auto-refresh**: On page load, profiles with missing/expired photos are automatically refreshed via individual `ProfileQuery` calls. Uses `useRef` + `sessionStorage` to prevent crash-remount loops (React error unmounts/remounts the component, resetting `useState` but not `useRef`/`sessionStorage`).
**Scanner**: Scans multiple saved locations via the Discover API to find real profile data. "Fuck It" mode scans all saved locations. Profiles that have liked you are auto-saved to `/api/who-liked-you`.
### Profile Detail Modal
- View full profile details including photos, bio, desires, interests
- **Partner navigation**: Click on linked partner profiles to view their details
- Back button to return to previous profile when viewing partners
- Like/Dislike actions with API mutations
- Ping modal for sending messages with likes
### Discover Page
- Profile browsing with like/dislike/ping actions
- Auto-saves profiles that have liked you (detected via `interactionStatus.theirs === 'LIKED'`)
- Profiles cached to `/api/who-liked-you` for enriching Likes page data
### Sent Pings Page
- Tracks outbound pings (likes with messages) sent to other profiles
- Shows ping message, target profile, and status
- Stored via `/api/sent-pings` backend endpoint
## Gotchas
### GraphQL `__typename` Objects
The Feeld GraphQL API can return profile fields (gender, sexuality, location, goals, distance) as objects with `{__typename: "..."}` instead of plain strings. **Always use `safeText()` or type checks when rendering any profile field.** Never render `profile.gender` or similar fields directly in JSX.
```tsx
// ProfileCard.tsx has a safeText() helper:
const safeText = (v: any): string => {
if (v == null) return '';
if (typeof v === 'string') return v;
if (typeof v === 'number' || typeof v === 'boolean') return String(v);
return '';
};
// Usage: <span>{safeText(profile.gender)}</span>
// NOT: <span>{profile.gender}</span> // Can crash with "Objects are not valid as React child"
```
Also sanitize profile data before saving to backend cache with `safeStr()`:
```tsx
const safeStr = (v: any) => (typeof v === 'string' ? v : '');
```
### Signed Image URLs
Cloudinary/fldcdn signed image URLs expire after a few hours. Cached profiles need periodic refresh to get new URLs. The auto-refresh on the Likes page handles this.
### API Version Enforcement
Feeld API enforces `x-app-version` — old versions get `UNSUPPORTED_APP_VERSION` 400 errors. Check the App Store for the current version and update `constants.ts` and `vite.config.ts` headers.
### WhoLikesMe Photo Limitations
WhoLikesMe API returns null photo URLs for non-Majestic (non-paying) users. The scanner (Discover API) returns real photos, which is why we cache scanner results and enrich WhoLikesMe data.
### Render-time Side Effects
Never call functions with side effects during React render. Use `useMemo` for data transformation and separate `useEffect` for side effects like API calls or cache updates. Calling side-effect functions during render causes infinite re-render loops.
## Common Tasks
### Add a new page
1. Create component in `web/src/pages/`
2. Add route in `web/src/App.tsx`
3. Add navigation link in `web/src/components/layout/Navigation.tsx`
### Add a new GraphQL query/mutation
1. Define in `web/src/api/operations/queries.ts` or `mutations.ts`
2. Use fragments from existing definitions for consistency
3. Call via Apollo's `useQuery`/`useMutation` hooks
### Add a new context/hook
1. Create in `web/src/hooks/` or `web/src/context/`
2. Export provider and hook
3. Add provider to hierarchy in `App.tsx`
### Debug API issues
1. Use `/api-explorer` route to test queries directly
2. Check Network tab for request/response
3. Verify headers in `constants.ts`
4. Check `API_DOCUMENTATION.md` for endpoint details
## Remote Deployment (Unraid)
Production runs on an Unraid server at `10.3.3.11`. Code lives at `/mnt/user/appdata/FeeldWeb/`, persistent data at `/mnt/user/downloads/feeldWeb/`.
```bash
# SSH in
sshpass -p 'Intel22' ssh -o StrictHostKeyChecking=no root@10.3.3.11
# Sync a file
sshpass -p 'Intel22' scp -o StrictHostKeyChecking=no \
"web/FILE_PATH" "root@10.3.3.11:/mnt/user/appdata/FeeldWeb/FILE_PATH"
# Restart containers
sshpass -p 'Intel22' ssh -o StrictHostKeyChecking=no root@10.3.3.11 \
'docker restart feeld-web-frontend feeld-web-backend feeld-web-nginx'
```
External URL: https://feeld.treytartt.com (proxied via Nginx Proxy Manager on port 7743)
## External Resources
- **API Documentation**: `API_DOCUMENTATION.md` (comprehensive reverse-engineered docs)
- **Captured Requests**: `proxyman_extracted/`, `proxyman_chat/`, `stream_extracted/`
- **Stream Chat Docs**: https://getstream.io/chat/docs/
- **Apollo Client Docs**: https://www.apollographql.com/docs/react/

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

114
docker-compose.unraid.yml Normal file
View File

@@ -0,0 +1,114 @@
# Docker Compose for Unraid
#
# Access at http://YOUR_UNRAID_IP:8580
#
# ============================================
# CONFIGURE THESE PATHS FOR YOUR UNRAID SETUP
# ============================================
# Edit the left side of the colon (:) for each volume mount
#
# DATABASE_PATH: Where to store the SQLite database
# IMAGES_PATH: Where to store downloaded images (can be large, 100GB+)
# EXPORTS_PATH: Where to store generated export zip files
# IMPORTS_PATH: Where to place images for bulk import (source/species/images)
# LOGS_PATH: Where to store scraper log files for debugging
services:
backend:
build:
context: /mnt/user/appdata/PlantGuideScraper/backend
dockerfile: Dockerfile
container_name: plant-scraper-backend
restart: unless-stopped
volumes:
- /mnt/user/appdata/PlantGuideScraper/backend:/app:ro
# === CONFIGURABLE DATA PATHS ===
- /mnt/user/downloads/PlantGuideDocker/database:/data/db # DATABASE_PATH
- /mnt/user/downloads/PlantGuideDocker/images:/data/images # IMAGES_PATH
- /mnt/user/downloads/PlantGuideDocker/exports:/data/exports # EXPORTS_PATH
- /mnt/user/downloads/PlantGuideDocker/imports:/data/imports # IMPORTS_PATH
- /mnt/user/downloads/PlantGuideDocker/logs:/data/logs # LOGS_PATH
environment:
- DATABASE_URL=sqlite:////data/db/plants.sqlite
- REDIS_URL=redis://plant-scraper-redis:6379/0
- IMAGES_PATH=/data/images
- EXPORTS_PATH=/data/exports
- IMPORTS_PATH=/data/imports
- LOGS_PATH=/data/logs
depends_on:
- redis
command: uvicorn app.main:app --host 0.0.0.0 --port 8000
networks:
- plant-scraper
celery:
build:
context: /mnt/user/appdata/PlantGuideScraper/backend
dockerfile: Dockerfile
container_name: plant-scraper-celery
restart: unless-stopped
volumes:
- /mnt/user/appdata/PlantGuideScraper/backend:/app:ro
# === CONFIGURABLE DATA PATHS (must match backend) ===
- /mnt/user/downloads/PlantGuideDocker/database:/data/db # DATABASE_PATH
- /mnt/user/downloads/PlantGuideDocker/images:/data/images # IMAGES_PATH
- /mnt/user/downloads/PlantGuideDocker/exports:/data/exports # EXPORTS_PATH
- /mnt/user/downloads/PlantGuideDocker/imports:/data/imports # IMPORTS_PATH
- /mnt/user/downloads/PlantGuideDocker/logs:/data/logs # LOGS_PATH
environment:
- DATABASE_URL=sqlite:////data/db/plants.sqlite
- REDIS_URL=redis://plant-scraper-redis:6379/0
- IMAGES_PATH=/data/images
- EXPORTS_PATH=/data/exports
- IMPORTS_PATH=/data/imports
- LOGS_PATH=/data/logs
depends_on:
- redis
command: celery -A app.workers.celery_app worker --beat --loglevel=info --concurrency=4
networks:
- plant-scraper
redis:
image: redis:7-alpine
container_name: plant-scraper-redis
restart: unless-stopped
volumes:
- /mnt/user/appdata/PlantGuideScraper/redis:/data
networks:
- plant-scraper
frontend:
build:
context: /mnt/user/appdata/PlantGuideScraper/frontend
dockerfile: Dockerfile
container_name: plant-scraper-frontend
restart: unless-stopped
volumes:
- /mnt/user/appdata/PlantGuideScraper/frontend:/app
- plant-scraper-node-modules:/app/node_modules
environment:
- VITE_API_URL=
command: npm run dev -- --host
networks:
- plant-scraper
nginx:
image: nginx:alpine
container_name: plant-scraper-nginx
restart: unless-stopped
ports:
- "8580:80"
volumes:
- /mnt/user/appdata/PlantGuideScraper/nginx/nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- backend
- frontend
networks:
- plant-scraper
networks:
plant-scraper:
name: plant-scraper
volumes:
plant-scraper-node-modules:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"endAt":791306209.6549392,"requestEndAt":1769613409.6549392,"timezone":"CST","isIntercepted":true,"name":"128","fileName":null,"websocketMessageStorage":null,"uniqueID":null,"timing":{"responseEndedAt":1769613409.6549392,"requestStartedAt":1769613409.524766,"requestEndedAt":1769613409.6549392,"responseStartedAt":1769613409.654933},"response":{"createdAt":1769613409.654933,"customPreviewerTabs":null,"version":{"major":1,"minor":1},"bodyData":null,"compressedBodyDataCount":0,"error":null,"header":{"entries":[{"value":"upgrade","key":{"nameInLowercase":"connection","name":"Connection"},"isEnabled":true},{"key":{"name":"Date","nameInLowercase":"date"},"value":"Wed, 28 Jan 2026 15:16:49 GMT","isEnabled":true},{"key":{"name":"Upgrade","nameInLowercase":"upgrade"},"value":"websocket","isEnabled":true},{"key":{"name":"Sec-WebSocket-Accept","nameInLowercase":"sec-websocket-accept"},"value":"fXS1ZX2H7nxscNAKe1\/fkCsgy5o=","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-protocol","name":"Sec-WebSocket-Protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"nameInLowercase":"x-cache","name":"X-Cache"},"value":"Miss from cloudfront","isEnabled":true},{"key":{"name":"Via","nameInLowercase":"via"},"value":"1.1 51d0a1b74b16c30679726a1e0d574f5c.cloudfront.net (CloudFront)","isEnabled":true},{"key":{"nameInLowercase":"x-amz-cf-pop","name":"X-Amz-Cf-Pop"},"value":"DFW56-P10","isEnabled":true},{"key":{"name":"X-Amz-Cf-Id","nameInLowercase":"x-amz-cf-id"},"value":"xFILIXQ2sz0DHKsjlwIj20I82E5aIOgd504imMt5owVzDfNvAoUX_A==","isEnabled":true},{"key":{"nameInLowercase":"access-control-allow-origin","name":"Access-Control-Allow-Origin"},"value":"*","isEnabled":true}]},"status":{"strict":false,"phrase":"Switching Protocols","code":101}},"isFromFile":false,"proxyCreatedAt":1769613409.524766,"style":null,"request":{"method":{"name":"GET"},"compressedBodyDataCount":0,"host":"core.api.fldcore.com","version":{"major":1,"minor":1},"isSSL":true,"bodyData":null,"header":{"entries":[{"isEnabled":true,"key":{"name":"Host","nameInLowercase":"host"},"value":"core.api.fldcore.com"},{"isEnabled":true,"key":{"name":"Sec-WebSocket-Protocol","nameInLowercase":"sec-websocket-protocol"},"value":"graphql-transport-ws"},{"isEnabled":true,"key":{"nameInLowercase":"sec-websocket-key","name":"Sec-WebSocket-Key"},"value":"8bu\/ZEvnkXG30xUxkXTbAQ=="},{"isEnabled":true,"key":{"nameInLowercase":"sec-websocket-version","name":"Sec-WebSocket-Version"},"value":"13"},{"isEnabled":true,"key":{"name":"Upgrade","nameInLowercase":"upgrade"},"value":"websocket"},{"key":{"name":"Origin","nameInLowercase":"origin"},"isEnabled":true,"value":"https:\/\/core.api.fldcore.com"},{"key":{"name":"User-Agent","nameInLowercase":"user-agent"},"isEnabled":true,"value":"feeld-mobile"},{"key":{"name":"Connection","nameInLowercase":"connection"},"isEnabled":true,"value":"Upgrade"}]},"isWebSocketUpgrade":true,"scheme":"wss","uri":"\/subscription","fullPath":"wss:\/\/core.api.fldcore.com\/subscription","port":443,"customPreviewerTabs":null},"isSSL":true,"id":"128","summary":{"clientPort":58374,"clientIpAddress":"127.0.0.1","serverIpAddress":"13.249.205.128","serverPort":443,"hostDNS":null,"tag":null},"client":null,"createAt":1769613409.524766,"isUnderNetworkCondition":false,"extraInfo":null,"toolMetadata":null,"isRelayed":false,"remoteDevice":{"ip":"127.0.0.1","name":"127.0.0.1"}}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"isIntercepted":true,"client":null,"id":"195","websocketMessageStorage":null,"summary":{"hostDNS":null,"tag":null,"clientPort":58489,"clientIpAddress":"127.0.0.1","serverIpAddress":"52.84.20.111","serverPort":443},"uniqueID":null,"isFromFile":false,"isSSL":true,"request":{"port":443,"host":"core.api.fldcore.com","customPreviewerTabs":null,"header":{"entries":[{"key":{"nameInLowercase":"host","name":"Host"},"value":"core.api.fldcore.com","isEnabled":true},{"key":{"name":"Sec-WebSocket-Protocol","nameInLowercase":"sec-websocket-protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"name":"Sec-WebSocket-Key","nameInLowercase":"sec-websocket-key"},"value":"k0DR\/N9CDih3sgDU0N1mnA==","isEnabled":true},{"key":{"name":"Sec-WebSocket-Version","nameInLowercase":"sec-websocket-version"},"value":"13","isEnabled":true},{"key":{"nameInLowercase":"upgrade","name":"Upgrade"},"value":"websocket","isEnabled":true},{"key":{"nameInLowercase":"origin","name":"Origin"},"value":"https:\/\/core.api.fldcore.com","isEnabled":true},{"key":{"name":"User-Agent","nameInLowercase":"user-agent"},"value":"feeld-mobile","isEnabled":true},{"key":{"name":"Connection","nameInLowercase":"connection"},"value":"Upgrade","isEnabled":true}]},"fullPath":"wss:\/\/core.api.fldcore.com\/subscription","isSSL":true,"bodyData":null,"uri":"\/subscription","compressedBodyDataCount":0,"isWebSocketUpgrade":true,"method":{"name":"GET"},"version":{"minor":1,"major":1},"scheme":"wss"},"createAt":1769615178.7193441,"response":{"version":{"major":1,"minor":1},"bodyData":null,"compressedBodyDataCount":0,"error":null,"header":{"entries":[{"value":"upgrade","key":{"name":"Connection","nameInLowercase":"connection"},"isEnabled":true},{"value":"Wed, 28 Jan 2026 15:46:19 GMT","key":{"name":"Date","nameInLowercase":"date"},"isEnabled":true},{"value":"websocket","key":{"name":"Upgrade","nameInLowercase":"upgrade"},"isEnabled":true},{"value":"V2XEVJk2qtuHtYjszipvCJkL09U=","key":{"name":"Sec-WebSocket-Accept","nameInLowercase":"sec-websocket-accept"},"isEnabled":true},{"value":"graphql-transport-ws","key":{"name":"Sec-WebSocket-Protocol","nameInLowercase":"sec-websocket-protocol"},"isEnabled":true},{"value":"Miss from cloudfront","key":{"name":"X-Cache","nameInLowercase":"x-cache"},"isEnabled":true},{"value":"1.1 58ea7d14c4c1fcd2d3e94e640c0a2236.cloudfront.net (CloudFront)","key":{"name":"Via","nameInLowercase":"via"},"isEnabled":true},{"value":"LAX53-P5","key":{"nameInLowercase":"x-amz-cf-pop","name":"X-Amz-Cf-Pop"},"isEnabled":true},{"value":"JXqLaVJXpQw70bwS8ByMIqUgCf5qDyBCB0Sk6C62gk9Lqhp-PNjUhQ==","key":{"nameInLowercase":"x-amz-cf-id","name":"X-Amz-Cf-Id"},"isEnabled":true},{"value":"*","key":{"nameInLowercase":"access-control-allow-origin","name":"Access-Control-Allow-Origin"},"isEnabled":true}]},"createdAt":1769615179.051711,"customPreviewerTabs":null,"status":{"strict":false,"phrase":"Switching Protocols","code":101}},"proxyCreatedAt":1769615178.7193441,"isUnderNetworkCondition":false,"timing":{"responseStartedAt":1769615179.051711,"responseEndedAt":1769615179.051713,"requestEndedAt":1769615179.051713,"requestStartedAt":1769615178.7193441},"extraInfo":null,"isRelayed":false,"style":null,"toolMetadata":null,"remoteDevice":{"name":"127.0.0.1","ip":"127.0.0.1"},"endAt":791307979.051713,"fileName":null,"name":"195","timezone":"CST","requestEndAt":1769615179.051713}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"extraInfo":null,"isRelayed":false,"isSSL":true,"summary":{"serverIpAddress":"13.249.205.39","hostDNS":null,"tag":null,"serverPort":443,"clientIpAddress":"127.0.0.1","clientPort":58972},"isFromFile":false,"uniqueID":null,"timezone":"CST","requestEndAt":1769621453.599446,"toolMetadata":null,"isUnderNetworkCondition":false,"websocketMessageStorage":null,"id":"467","remoteDevice":{"ip":"127.0.0.1","name":"127.0.0.1"},"client":null,"endAt":791314253.599446,"name":"467","request":{"isSSL":true,"compressedBodyDataCount":0,"isWebSocketUpgrade":true,"header":{"entries":[{"key":{"nameInLowercase":"host","name":"Host"},"value":"core.api.fldcore.com","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-protocol","name":"Sec-WebSocket-Protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-key","name":"Sec-WebSocket-Key"},"value":"6Bi\/7ocVw8sTNYnI+SaH9A==","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-version","name":"Sec-WebSocket-Version"},"value":"13","isEnabled":true},{"key":{"nameInLowercase":"upgrade","name":"Upgrade"},"value":"websocket","isEnabled":true},{"key":{"nameInLowercase":"origin","name":"Origin"},"value":"https:\/\/core.api.fldcore.com","isEnabled":true},{"key":{"nameInLowercase":"user-agent","name":"User-Agent"},"value":"feeld-mobile","isEnabled":true},{"key":{"nameInLowercase":"connection","name":"Connection"},"value":"Upgrade","isEnabled":true}]},"version":{"minor":1,"major":1},"uri":"\/subscription","fullPath":"wss:\/\/core.api.fldcore.com\/subscription","method":{"name":"GET"},"customPreviewerTabs":null,"scheme":"wss","port":443,"bodyData":null,"host":"core.api.fldcore.com"},"style":null,"fileName":null,"response":{"createdAt":1769621453.599441,"compressedBodyDataCount":0,"status":{"phrase":"Switching Protocols","strict":false,"code":101},"version":{"minor":1,"major":1},"error":null,"header":{"entries":[{"key":{"nameInLowercase":"connection","name":"Connection"},"value":"upgrade","isEnabled":true},{"key":{"nameInLowercase":"date","name":"Date"},"value":"Wed, 28 Jan 2026 17:30:53 GMT","isEnabled":true},{"key":{"nameInLowercase":"upgrade","name":"Upgrade"},"value":"websocket","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-accept","name":"Sec-WebSocket-Accept"},"value":"iimrBcfHnP7lkZUE8M4hWo6Vz6Y=","isEnabled":true},{"key":{"nameInLowercase":"sec-websocket-protocol","name":"Sec-WebSocket-Protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"nameInLowercase":"x-cache","name":"X-Cache"},"value":"Miss from cloudfront","isEnabled":true},{"key":{"nameInLowercase":"via","name":"Via"},"value":"1.1 2d6372565e269658e59fe35e195ee728.cloudfront.net (CloudFront)","isEnabled":true},{"key":{"nameInLowercase":"x-amz-cf-pop","name":"X-Amz-Cf-Pop"},"value":"DFW56-P10","isEnabled":true},{"key":{"nameInLowercase":"x-amz-cf-id","name":"X-Amz-Cf-Id"},"value":"I0shX1_gISI2uHTOxa8EK2jyPP4RRbhEo6UKD6dbGGMDIpzv4l43fg==","isEnabled":true},{"key":{"nameInLowercase":"access-control-allow-origin","name":"Access-Control-Allow-Origin"},"value":"*","isEnabled":true}]},"customPreviewerTabs":null,"bodyData":null},"createAt":1769621453.446475,"proxyCreatedAt":1769621453.446475,"timing":{"requestStartedAt":1769621453.446475,"responseStartedAt":1769621453.599441,"responseEndedAt":1769621453.599446,"requestEndedAt":1769621453.599446},"isIntercepted":true}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
{"fileName":null,"requestEndAt":1769272531.1225991,"isSSL":true,"proxyCreatedAt":1769272531.00792,"id":"448","summary":{"tag":null,"serverIpAddress":"13.249.205.36","clientPort":50370,"hostDNS":null,"serverPort":443,"clientIpAddress":"127.0.0.1"},"toolMetadata":null,"name":"448","isRelayed":false,"response":{"customPreviewerTabs":null,"status":{"code":101,"strict":false,"phrase":"Switching Protocols"},"header":{"entries":[{"key":{"name":"Connection","nameInLowercase":"connection"},"value":"upgrade","isEnabled":true},{"key":{"name":"Date","nameInLowercase":"date"},"value":"Sat, 24 Jan 2026 16:35:31 GMT","isEnabled":true},{"key":{"name":"Upgrade","nameInLowercase":"upgrade"},"value":"websocket","isEnabled":true},{"key":{"name":"Sec-WebSocket-Accept","nameInLowercase":"sec-websocket-accept"},"value":"VlKG0B7TEj4q076XVRYJT6kzhRE=","isEnabled":true},{"key":{"name":"Sec-WebSocket-Protocol","nameInLowercase":"sec-websocket-protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"name":"X-Cache","nameInLowercase":"x-cache"},"value":"Miss from cloudfront","isEnabled":true},{"key":{"name":"Via","nameInLowercase":"via"},"value":"1.1 380fc6a906659ffac1234c1391eafb90.cloudfront.net (CloudFront)","isEnabled":true},{"key":{"name":"X-Amz-Cf-Pop","nameInLowercase":"x-amz-cf-pop"},"value":"DFW56-P10","isEnabled":true},{"key":{"name":"X-Amz-Cf-Id","nameInLowercase":"x-amz-cf-id"},"value":"erjaD39k06fdEiseWwKn0meTZ8ZxGVAdlrDr5RQJyX6tdBuRLI46qg==","isEnabled":true},{"key":{"name":"Access-Control-Allow-Origin","nameInLowercase":"access-control-allow-origin"},"value":"*","isEnabled":true}]},"createdAt":1769272531.122596,"bodyData":null,"version":{"major":1,"minor":1},"error":null,"compressedBodyDataCount":0},"createAt":1769272531.00792,"isUnderNetworkCondition":false,"client":null,"style":null,"extraInfo":null,"remoteDevice":{"ip":"127.0.0.1","name":"127.0.0.1"},"endAt":790965331.1225991,"uniqueID":null,"timing":{"requestEndedAt":1769272531.1225991,"responseStartedAt":1769272531.122596,"requestStartedAt":1769272531.00792,"responseEndedAt":1769272531.1225991},"websocketMessageStorage":null,"request":{"uri":"\/subscription","header":{"entries":[{"key":{"name":"Host","nameInLowercase":"host"},"value":"core.api.fldcore.com","isEnabled":true},{"key":{"name":"Sec-WebSocket-Protocol","nameInLowercase":"sec-websocket-protocol"},"value":"graphql-transport-ws","isEnabled":true},{"key":{"name":"Sec-WebSocket-Key","nameInLowercase":"sec-websocket-key"},"value":"ZLjXfJWfIp\/yRNTCsF7ZXg==","isEnabled":true},{"key":{"name":"Sec-WebSocket-Version","nameInLowercase":"sec-websocket-version"},"value":"13","isEnabled":true},{"key":{"name":"Upgrade","nameInLowercase":"upgrade"},"value":"websocket","isEnabled":true},{"key":{"name":"Origin","nameInLowercase":"origin"},"value":"https:\/\/core.api.fldcore.com","isEnabled":true},{"key":{"name":"User-Agent","nameInLowercase":"user-agent"},"value":"feeld-mobile","isEnabled":true},{"key":{"name":"Connection","nameInLowercase":"connection"},"value":"Upgrade","isEnabled":true}]},"isSSL":true,"isWebSocketUpgrade":true,"fullPath":"wss:\/\/core.api.fldcore.com\/subscription","scheme":"wss","version":{"major":1,"minor":1},"compressedBodyDataCount":0,"customPreviewerTabs":null,"port":443,"method":{"name":"GET"},"bodyData":null,"host":"core.api.fldcore.com"},"isIntercepted":true,"timezone":"CST","isFromFile":false}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More