- intelligent-backend
intelligent-backend powers Farcaster-centric social analytics. The service:
- Ingests Farcaster casts, reactions, followers, etc. through the Airstack & Neynar APIs.
- Persists raw entities & derived analytics to Firebase Firestore.
- Performs interval-based aggregations (24 h, 7 d, 30 d, 180 d), ranking, and list generation inside a PostgreSQL data-mart codenamed Mimir.
- Orchestrates IO-heavy tasks via BullMQ workers backed by Redis.
- Supports gated routes secured by Privy auth tokens and a Firestore-driven whitelist.
- Surfaces REST endpoints under
/api/**for clients (web / mobile / cron).
| Layer | Library / Service | Notes |
|---|---|---|
| Web server | Express | Typed with TypeScript. |
| Task queues | BullMQ | Redis-backed job scheduling & workers. |
| Persistent store | Firebase Firestore | Raw casts, user documents, interval stats, etc. |
| Analytics DW | PostgreSQL | Queried via pg in the mimir module. |
| Farcaster data | Airstack, Neynar | GraphQL & REST endpoints. |
| Auth | Privy JWT | Middleware validates Authorization: Bearer <token>. |
| Cloud jobs | cron | (Optional) recurring tasks, currently commented. |
-
Bootstrap (
src/index.ts)- Loads environment variables via
dotenv. - Initializes Airstack (
initializeAirstack) and Postgres pool (initializeMimir). - Registers Express middlewares (
json,urlencoded,cors). - Side-effect imports spin up BullMQ queues & workers at start-up (important: do not remove those imports).
- Binds routers (root,
/api,/api/alfafrens,/api/user,/api/mimir,/api/degen).
- Loads environment variables via
-
Incoming Request ➜ Router
- Public endpoints: basic health checks, Farcaster cast analysis, reaction-fetch trigger, pagination helpers.
- Protected endpoints:
checkPrivyTokenmiddleware verifies Privy JWT, checks Firestore whitelist, kicks off globalUserUpdateQueue.
-
Job Execution (BullMQ workers)
- Examples:
fetchRepliesFromCastWorker,fetchReactionsFromCastWorker,syncAlfaFrensWorker,intervalAggregationsWorker, etc. - Workers fetch external data (Airstack, AlfaFrens, SQL) → transform → persist in Firestore.
- Examples:
-
Analytics (Mimir)
- SQL files under
src/mimir/sql/**implement heavy aggregations (followers delta, mention counts, etc.). - Jobs in
src/mimir/jobs/**execute those queries for each user & timeframe, writing results back to Firestore so the client can consume without hitting Postgres directly.
- SQL files under
src/
├─ airstack/ # Airstack client bootstrap
├─ crons/ # (Optional) cron-scheduled jobs
├─ db/ # Firestore wrappers (add/fetch)
│ └─ ecosystem/alfafrens # AlfaFrens-specific collections
├─ ecosystems/ # One-off importers (e.g., completeAFSubs.ts)
├─ firebase/ # Firebase Admin SDK init (service account via env)
├─ middleware/ # Express middlewares (Privy auth, etc.)
├─ mimir/ # Analytics engine (jobs, SQL, router)
│ ├─ jobs/ # BullMQ workers for analytics
│ ├─ router/ # `/api/mimir` Express routes
│ └─ sql/ # Parameterised SQL fragments
├─ neynar/ # Neynar SDK client
├─ queues/ # BullMQ queues & workers for Farcaster data
├─ routes/ # Top-level API endpoints
├─ utils/ # Shared helpers (Redis conn, Airstack GQL builders, etc.)
└─ index.ts # Application entry point
src/routes/index.ts– generic helpers: analyze URL, fetch replies/reactions, sync cast.src/routes/alfafrens.ts,users.ts,degen.ts– domain-specific sub-routers.checkPrivyToken.ts– ensuresAuthorizationheader is valid Privy JWT and caller FID is whitelisted.
- Airstack:
getCastByUrlQuery,getRepliesByUrlQuery,getLikesByUrlQuery, etc. build GraphQL;fetchQueryWithPaginationstreams paginated results. - Neynar:
Used mainly for quick cast lookup (lookUpCastByHashOrWarpcastUrl).
- Encapsulated in tiny helpers under
src/db/**– e.g.,addCastToDB,addRepliesToDB,fetchRepliesFromDBUsingUrl. - Firestore collections used:
casts,replies,reactionsuser_stats(interval analytics)whitelist(FIDs allowed beyond auth)based_games,ecosystems/*(auxiliary)
- Queues live in
src/queues/**. Adding a job ➜ immediate worker execution in same process. - Redis connection parameters switch between development & production via env vars.
- Worker logs prefix each operation for Cloudwatch / Logtail searching.
- Connection pool created in
src/mimir/mimir.ts(initializeMimir). - SQL fragments parameterised for reuse (
src/mimir/sql/**). - Queue
globalUserUpdateQueueorchestrates dozens of analytics sub-jobs per user, enforcing a 20-minute cooldown.
syncAlfaFrensQueuefetches user profile & channel subscribers via AlfaFrens public API.- Results stored in Firestore under
ecosystem/alfafrens/*collections.
- Client calls
GET /api/sync-cast?castUrl=<warpcast-url>with a valid Privy token. 📲 checkPrivyTokenvalidates token ➜ kicks off globalUserUpdateQueue(fid) for the caller.- Route executes Airstack
getCastByUrlQueryto resolve the cast → persists in Firestore viaaddCastToDB. - Two jobs are queued:
fetchRepliesFromCastQueue(gathers every reply, pagination-aware).fetchReactionsFromCastQueue(likes + recasts).
- Workers ingest data, de-paginate via
fetchQueryWithPagination, augment object (reactionType), then fireaddRepliesToDB/addReactionsToDB. - UI can now call
/api/get-replies(Firestore-backed) for instant hydration while deeper analytics run asynchronously in Mimir.
| Variable | Purpose |
|---|---|
PORT |
Express port (default 3000) |
FIREBASE_SERVICE_ACCOUNT |
Stringified service-account JSON (see src/firebase/firebase.ts) |
AIRSTACK_API_KEY |
Airstack API key |
NEYNAR_API_KEY |
(Optional) Neynar key (demo fallback exists) |
PRIVY_APP_ID / PRIVY_APP_SECRET |
Privy production creds |
PRIVY_DEV_APP_ID / PRIVY_DEV_APP_SECRET |
Privy dev creds |
REDIS_DEVELOPMENT_HOST / REDIS_DEVELOPMENT_PASSWORD |
Local Redis |
REDIS_PRODUCTION_HOST / REDIS_PRODUCTION_PASSWORD |
Prod Redis |
DB_USER, DB_PASSWORD, DB_HOST, DB_NAME, DB_PORT |
Postgres (Mimir) |
Most secrets should be injected via your container/orchestrator — never commit them. See
.env.examplefor a full list.
-
Clone & Install
git clone [email protected]:<you>/intelligent-backend.git cd intelligent-backend pnpm i # or npm install / yarn
-
Configure Secrets
- Copy
.env.example→.envand fill values. - Export
FIREBASE_SERVICE_ACCOUNTas one line (e.g.$(cat serviceAccount.json | jq -c)).
- Copy
-
Start Services
# requires Redis & Postgres running locally or via Docker npm run dev -
Trigger Example
curl -X GET \ -H "Authorization: Bearer <privy-jwt>" \ "http://localhost:3000/api/sync-cast?castUrl=https://warpcast.com/~/cast/0x..."
Logs will show queue creation (🚄 … SYNC QUEUE) and worker processing in real time.
- Use TypeScript strict mode; run
pnpm lintbefore PRs. - Secrets must come from env; CI enforces
gitleaksscan. - Long-running SQL lives under
src/mimir/sql; keep business logic in jobs not routes.
Happy hacking 👋