Everything is verified against source. Writing the report.
HALO CRM — Platform Force-Multipliers
All GitHub figures verified via gh api on 2026-08-29. All Convex components are get-convex/*, Apache-2.0, and pushed within the last 3 days — this is a live, maintained, first-party ecosystem, not a graveyard.
The five things to install this week
1. Convex preview deployments (native, zero dependency, ~30 min) This is the single highest-leverage item in this report because it fixes the exact incident recorded in his CLAUDE.md — "Pushing alone ships a frontend that may call functions production doesn't have — which has already happened once, breaking Model Profile's announcements, calendar and content limitations on the live site."
The root cause is that Vercel and Convex deploy on separate triggers. The fix is to make them one trigger: generate a preview deploy key in the Convex dashboard, set CONVEX_DEPLOY_KEY in Vercel, and change the Vercel build command to npx convex deploy --cmd 'npm run build'. Convex then pushes functions and builds the frontend against them, injecting the right VITE_CONVEX_URL. Frontend-ahead-of-backend becomes structurally impossible rather than a thing he has to remember. Preview branches get their own isolated deployment (auto-cleaned after 5 days on free, 14 on Pro). Beta, per Convex docs. No repo can substitute for this — it's a config change worth more than any library below.
2. get-convex/workflow — 80★ · Apache-2.0 · pushed 2026-08-27 Drive provisioning is ctx.scheduler.runAfter(0, …) fire-and-forget at creators.ts:115 and onboardingSubmissions.ts:193. I read provisionOneCreator (convex/googleDrive.ts:344-380): it calls mintAccessToken, then findOrCreateFolder, then buildCategoryStructure — multiple sequential Drive REST calls with no retry, no backoff, and no failure record. If Drive 500s on call three, the action throws, and the only trace is the absence of a driveCreatorFolders row. The comment is honest about this ("surfaces as not connected with a retry") but it means a transient blip becomes silent manual work.
Workflow gives him durable execution: configurable per-step retry, exactly-once mutations, restart-from-arbitrary-step after a third-party outage, and — the underrated part — live workflow status observable through ordinary reactive Convex queries. That last point means his existing "not connected" UI can become "provisioning, step 3 of 7, retrying after Drive 503" with no new plumbing. Same argument applies to driveScan.scanAll (convex/driveScan.ts:302), which fans out one scheduled action per creator with no aggregate success/failure tracking.
3. get-convex/aggregate — 31★ · Apache-2.0 · pushed 2026-08-28 convex/dashboard.ts:6 does ctx.db.query("creators").collect() then seven .filter().length passes in JS. Across convex/*.ts I counted 165 .collect() calls, at least 25 of which are full-table scans with no index. Convex bills on documents read and caps a single transaction's reads — this pattern gets slower and more expensive with every creator, and eventually throws rather than degrading. Aggregate maintains counts and sums in a data structure updated on write, so dashboard reads become O(log n) instead of O(table). Start with dashboard.ts and the gamification leaderboards (gamification.ts has ~10 full scans).
4. Sentry via Convex's native integration (dashboard toggle, ~15 min, Pro plan) No test framework, one developer, 221 public functions. He currently learns about backend exceptions when a user complains. Convex has first-party exception reporting — Deployment Settings → Integrations → Sentry, paste the DSN, set the Sentry project platform to Node.js. Convex auto-tags every event with func, func_type, request_id, environment (prod/dev/preview) and the authenticated user. PostHog Error Tracking is the same flow if he prefers. Do not install @sentry/node in Convex functions — use the integration. Add getsentry/sentry-javascript (8,728★ · MIT · 2026-08-28) on the frontend separately.
5. EXIF stripping on the Drive thumbnail path (highest safety-per-hour in this report) convex/driveScan.ts:252-253 fetches Drive thumbnails server-side and does ctx.storage.store(blob) verbatim. This is a creator-talent agency: photos shot on phones routinely carry GPS coordinates in EXIF, and Convex file URLs are effectively unguessable-but-public. Serving a creator's home coordinates is a real-world safety incident, not a compliance checkbox.
The honest verification result: lovell/sharp (32,613★ · Apache-2.0 · 2026-08-28) is the right tool but needs native binaries, so it only runs in a Convex Node action, not the default runtime — check that before committing. mattiasw/ExifReader (997★ · MPL-2.0 · 2026-08-28) is pure JS and works in the default runtime for detecting GPS tags. Note that Drive-generated thumbnailLink images may already be stripped by Google — audit ten stored thumbnails for GPS tags before building anything. If they're clean, this is a non-issue and you've saved the work; if not, it's urgent. Two candidates I could not verify (aaronshaf/exif-be-gone, exiftool-vendored) returned 404 under those names — treat as unverified.
1. Convex component ecosystem — full verified enumeration
| Component | ★ | Licence | Pushed | Replaces / unlocks | Difficulty | Verdict |
|---|---|---|---|---|---|---|
get-convex/workflow | 80 | Apache-2.0 | 08-27 | Fire-and-forget Drive provisioning; scan fanout | Medium | Install |
get-convex/aggregate | 31 | Apache-2.0 | 08-28 | dashboard.ts full scans, leaderboards | Medium | Install |
get-convex/better-auth | 765 | Apache-2.0 | 08-28 | Salted-SHA256 haloAuth.login + localStorage session | High | Other agent's lane |
get-convex/agent | 346 | Apache-2.0 | 08-28 | Persistent chat history, AI agents | Medium | See §3 |
get-convex/stripe | 78 | Apache-2.0 | 08-27 | Invoicing payment rails | Medium | Vertical lane |
get-convex/prosemirror-sync | 62 | Apache-2.0 | 08-28 | Collaborative contract/note editing | Medium | Later |
get-convex/r2 | 49 | Apache-2.0 | 08-28 | Convex storage → Cloudflare R2 (egress cost) | Low | Only if bills bite |
get-convex/polar | 39 | Apache-2.0 | 08-28 | Merchant-of-record billing | Medium | Vertical lane |
get-convex/resend | 39 | Apache-2.0 | 08-28 | Transactional email w/ durable retry | Low | Install if email exists |
get-convex/rag | 36 | Apache-2.0 | 08-28 | Chunking/embedding/retrieval over Drive+contracts | Medium | See §3 |
get-convex/persistent-text-streaming | 32 | Apache-2.0 | 08-27 | LLM streaming that survives reload | Low | With §3 |
get-convex/workpool | 31 | Apache-2.0 | 08-28 | Parallelism limits (Drive API quota) | Low | Install |
get-convex/geospatial | 29 | Apache-2.0 | 08-27 | Location queries | Low | No use case |
get-convex/rate-limiter | 27 | Apache-2.0 | 08-29 | Login brute-force, ElevenLabs spend cap | Low | Install |
get-convex/table-history | 22 | Apache-2.0 | 08-27 | Audit log on contracts/payments | Low | Strong fit |
get-convex/migrations | 20 | Apache-2.0 | 08-27 | Supabase→Convex backfills, snake_case fixes | Low | Install |
get-convex/presence | 19 | Apache-2.0 | 08-26 | "Who's viewing this creator" | Low | Cheap win |
get-convex/expo-push-notifications | 19 | Apache-2.0 | 08-27 | Mobile push | Low | With §6 |
get-convex/action-cache | 15 | Apache-2.0 | 08-27 | Would have replaced the hand-rolled currencyRates cache | Low | Note for next time |
get-convex/twilio | 13 | Apache-2.0 | 08-27 | SMS to creators | Low | Optional |
get-convex/action-retrier | 12 | Apache-2.0 | 08-28 | Subset of workflow | Low | Skip — take workflow |
get-convex/launchdarkly | 7 | Apache-2.0 | 08-26 | Feature flags (needs paid LD) | Low | Skip |
get-convex/crons | 6 | Apache-2.0 | 08-27 | Runtime-registered crons | Low | Skip — see below |
get-convex/sharded-counter | 5 | Apache-2.0 | 08-27 | High-contention counters | Low | Overkill |
Correction to the brief's premise: his crons.ts is not hand-rolled. cronJobs() from convex/server is the native, correct API, and the file is a clean 22 lines with a good comment. The crons component solves a different problem — registering crons dynamically at runtime — which he doesn't have. Don't touch it.
convex-helpers (489★ · Apache-2.0 · 2026-08-27) is worth a read regardless: custom function wrappers there would let him enforce auth once across 221 public functions instead of per-handler.
2. Durable execution verdict
Convex workflow, and nothing else. Temporal (22,593★ · MIT) and Trigger.dev (16,154★ · Apache-2.0) are excellent and both wrong here — they're separate services with their own infra, deploy pipeline, and auth boundary, for a solo dev who already forgets one deploy step. Inngest (5,776★) is lighter but still an external dependency crossing the Convex transaction boundary. graphile/worker (2,380★ · MIT) and river (5,610★ · MPL-2.0) are Postgres-backed and irrelevant to a Convex app.
The Convex component wins because steps are Convex functions — same types, same transactions, same reactive queries for status, no second system to deploy. Pair with workpool to cap Drive API concurrency.
3. AI surface
Convex has built-in vector search, verified: vectorIndex() in schema, 2–4096 dimensions, up to 16 filter fields, 4 indexes/table, up to 256 results, cosine similarity, strongly consistent. His schema has zero vector indexes and zero search indexes across 57 tables — he's paying for a database with semantic search built in and using none of it.
Important constraint: ctx.vectorSearch runs in actions only, returning {_id, _score} pairs — you then load documents in a separate query. Design around that.
| Capability | Tool | Verified | Verdict |
|---|---|---|---|
| Semantic search over Drive index | Convex vectorIndex native | ✓ docs | Do first — free |
| RAG over contracts | get-convex/rag 36★ Apache-2.0 | ✓ | Yes |
| Chat drafting / CRM assistant | get-convex/agent 346★ + persistent-text-streaming 32★ | ✓ | Yes |
| Model calls | vercel/ai 26,478★ · NOASSERTION · 2026-08-28 | ✓ | Yes |
| Orchestration framework | langchainjs 18,143★ MIT | ✓ | Skip — the Convex components cover it |
| — | LlamaIndexTS 3,076★ MIT | ✓ ARCHIVED 2026-03-11 | Do not adopt |
| Invoice/statement OCR | datalab-to/surya 21,329★ Apache-2.0 · 08-21 | ✓ | Best current, but Python — external service |
| — | datalab-to/marker 39,353★ Apache-2.0 · 08-27 | ✓ | Document→markdown, Python |
| — | allenai/olmocr 19,399★ Apache-2.0 · last push 2026-03-25 | ✓ | Going stale |
| — | tesseract 76,239★ Apache-2.0 | ✓ | Old-school, weak on tables |
Honest call on OCR: every strong option is Python and cannot run inside Convex. For a solo dev, a hosted vision-model call from a Convex action beats standing up a Python OCR service. LlamaIndexTS being archived is the kind of thing worth knowing before adopting it.
4. Media pipeline
He stores Drive thumbnails and that's the whole pipeline. Ranked by value:
| Need | Tool | Verified | Verdict |
|---|---|---|---|
| EXIF/GPS stripping | lovell/sharp 32,613★ Apache-2.0 | ✓ | Audit first, then fix (Node action only) |
| EXIF detection | mattiasw/ExifReader 997★ MPL-2.0 | ✓ | Pure JS, default runtime |
| CDN + resize | imgproxy 11,034★ Apache-2.0 · 08-27 | ✓ | Only if egress hurts |
| — | thumbor 10,514★ MIT · 08-27 | ✓ | Python, heavier |
| Perceptual dedupe | facebook/ThreatExchange (PDQ) 1,377★ NOASSERTION | ✓ | Real fit for reposted content, but a project |
| Video transcode | node-fluent-ffmpeg 8,240★ MIT | ✓ ARCHIVED 2025-05-22 | Don't adopt; call ffmpeg directly |
| Adaptive streaming | hls.js 16,904★ · Mux | ✓ | Overkill — Drive plays video |
5. Solo-dev safety net
Already covered: preview deploys (#1), Sentry (#4). Adding:
- Convex backups — native, verified. Manual "Backup Now" (7-day retention) on any plan; scheduled daily/weekly backups require Pro.
npx convex export --path ~/Downloadsworks from CLI today. Critical caveat: backups exclude functions, crons, schema, and environment variables — his Drive OAuth refresh token and ElevenLabs keys are not in any backup. Document them somewhere safe. renovatebot/renovate— 22,369★ · AGPL-3.0 · 2026-08-29. AGPL is on the hosted app, not your code; the GitHub App is free. Set it to group + auto-merge minors.typicode/husky35,292★ MIT (last push 2026-03-19, stable not stale) +lint-staged14,720★ MIT · 2026-08-27 — a pre-push hook runningnpm run lint && npm run buildis his only mechanical gate given zero tests.- Feature flags: skip for now. Unleash (13,769★ · AGPL-3.0) and Flagsmith (6,532★ · BSD-3-Clause) are both self-hosted services. Preview deployments deliver most of the safe-rollout value for one developer at a fraction of the cost.
OpenFeature js-sdk(277★ · Apache-2.0) is just an abstraction layer — pointless without a provider. - Tighten the function surface. 221 public vs 22 internal. Anything only called from other Convex functions should be
internalQuery/internalMutation/internalAction— public functions are internet-reachable endpoints. This is free and mechanical; thedriveScan/googleDrivesplit already shows he knows the pattern.
6. New product surface
| Surface | Cost | Verdict |
|---|---|---|
| Presence on records | get-convex/presence 19★ | Hours. Reactivity is already paid for. |
| Real-time dashboards | Already have it | Convex queries are live by default — verify no polling exists |
| Mobile app (Expo) | expo/expo 51,884★ MIT | Real project, but the path is proven: get-convex/turbo-expo-nextjs-clerk-convex-monorepo (393★ · Apache-2.0 · 08-28) is a first-party reference. Convex docs confirm React Native uses the standard React client, no separate package. Pair with expo-push-notifications component. |
| Webhooks out | Convex httpAction native | Days |
| Public creator portal | Convex + auth | Weeks — depends on the auth rebuild |
| Collaborative editing | prosemirror-sync 62★ | Days, if there's a document surface |
| Offline support | — | Real project. Skip. |
Convex already does this — skip the dependency
- Cron scheduling —
cronJobs()is native and hiscrons.tsis correct. Don't install the crons component. - Vector search — native
vectorIndex(). No pgvector, no external vector DB. - Full-text search — native
searchIndex(). He has zero. No Meilisearch/Typesense/Algolia needed. - Backups — native, plus
npx convex export. No backup tooling. - Exception reporting — native Sentry/PostHog integration. Don't
npm i @sentry/nodeinto functions. - Real-time subscriptions — every query is live. No Pusher/Ably/socket.io.
- File storage —
ctx.storageworks. R2 is a cost optimization, not a capability. - Preview environments / DB branching — native preview deployments with isolated data.
- Basic job scheduling —
ctx.scheduleris fine for fire-and-forget; upgrade only where durability matters. - End-to-end types —
_generated/api.d.tsalready gives this. No tRPC, no codegen layer.
Overkill for one dev
- Temporal / Trigger.dev / Inngest — separate services; workflow component covers it in-stack.
- Self-hosted Unleash or Flagsmith — infra to run and secure for one person's rollouts.
- Highlight (9,371★) session replay self-hosted — heavy; hosted PostHog if he wants it.
- imgproxy / thumbor — a service to operate before there's a cost problem to solve.
- LangChain / LlamaIndexTS — the Convex
agent+ragcomponents do this natively; LlamaIndexTS is archived. - Self-hosted Python OCR (surya/marker/olmOCR) — a GPU service and a deploy pipeline; call a hosted vision model.
- sharded-counter — solves write contention he doesn't have.
- Perceptual dedupe (PDQ) — genuinely valuable for reposted content, but a project, not a week.
- Offline-first mobile — the hardest thing on this list.
Sequencing
Week 1 (≈1 day total): preview deployments · Sentry integration · EXIF audit · rate-limiter · migrations. Week 2–3: workflow + workpool on Drive provisioning · aggregate on dashboard.ts · Renovate · husky pre-push · public→internal function audit. Month 2: vector index on the Drive content index (native, free) · rag + agent for a CRM assistant · table-history on contracts and payments.
Files that anchor the top recommendations: /Users/shaansisodia/SISO_Workspace/SISO_Agency/clients/halocrm/repo/convex/googleDrive.ts:344-380 (unretried multi-call provisioning), convex/driveScan.ts:252-253 (unstripped thumbnail store) and :302-316 (untracked fanout), convex/dashboard.ts:6 (full-table scan), convex/schema.ts (57 tables, zero vector/search indexes), CLAUDE.md "Deploying" section (the incident preview deploys prevent).