HALO Knowledge Docs
Generated knowledge spine · research/lanes/06-platform-multipliers.md

08 · Platform multipliers

What the Convex ecosystem makes nearly free that is not being used.

Generated from research/lanes/06-platform-multipliers.md · regenerate with /opt/homebrew/opt/node@24/bin/node site/scripts/generate-docs.mjs

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 buildCategoryStructuremultiple 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

ComponentLicencePushedReplaces / unlocksDifficultyVerdict
get-convex/workflow80Apache-2.008-27Fire-and-forget Drive provisioning; scan fanoutMediumInstall
get-convex/aggregate31Apache-2.008-28dashboard.ts full scans, leaderboardsMediumInstall
get-convex/better-auth765Apache-2.008-28Salted-SHA256 haloAuth.login + localStorage sessionHighOther agent's lane
get-convex/agent346Apache-2.008-28Persistent chat history, AI agentsMediumSee §3
get-convex/stripe78Apache-2.008-27Invoicing payment railsMediumVertical lane
get-convex/prosemirror-sync62Apache-2.008-28Collaborative contract/note editingMediumLater
get-convex/r249Apache-2.008-28Convex storage → Cloudflare R2 (egress cost)LowOnly if bills bite
get-convex/polar39Apache-2.008-28Merchant-of-record billingMediumVertical lane
get-convex/resend39Apache-2.008-28Transactional email w/ durable retryLowInstall if email exists
get-convex/rag36Apache-2.008-28Chunking/embedding/retrieval over Drive+contractsMediumSee §3
get-convex/persistent-text-streaming32Apache-2.008-27LLM streaming that survives reloadLowWith §3
get-convex/workpool31Apache-2.008-28Parallelism limits (Drive API quota)LowInstall
get-convex/geospatial29Apache-2.008-27Location queriesLowNo use case
get-convex/rate-limiter27Apache-2.008-29Login brute-force, ElevenLabs spend capLowInstall
get-convex/table-history22Apache-2.008-27Audit log on contracts/paymentsLowStrong fit
get-convex/migrations20Apache-2.008-27Supabase→Convex backfills, snake_case fixesLowInstall
get-convex/presence19Apache-2.008-26"Who's viewing this creator"LowCheap win
get-convex/expo-push-notifications19Apache-2.008-27Mobile pushLowWith §6
get-convex/action-cache15Apache-2.008-27Would have replaced the hand-rolled currencyRates cacheLowNote for next time
get-convex/twilio13Apache-2.008-27SMS to creatorsLowOptional
get-convex/action-retrier12Apache-2.008-28Subset of workflowLowSkip — take workflow
get-convex/launchdarkly7Apache-2.008-26Feature flags (needs paid LD)LowSkip
get-convex/crons6Apache-2.008-27Runtime-registered cronsLowSkip — see below
get-convex/sharded-counter5Apache-2.008-27High-contention countersLowOverkill

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.

CapabilityToolVerifiedVerdict
Semantic search over Drive indexConvex vectorIndex native✓ docsDo first — free
RAG over contractsget-convex/rag 36★ Apache-2.0Yes
Chat drafting / CRM assistantget-convex/agent 346★ + persistent-text-streaming 32★Yes
Model callsvercel/ai 26,478★ · NOASSERTION · 2026-08-28Yes
Orchestration frameworklangchainjs 18,143★ MITSkip — the Convex components cover it
LlamaIndexTS 3,076★ MITARCHIVED 2026-03-11Do not adopt
Invoice/statement OCRdatalab-to/surya 21,329★ Apache-2.0 · 08-21Best current, but Python — external service
datalab-to/marker 39,353★ Apache-2.0 · 08-27Document→markdown, Python
allenai/olmocr 19,399★ Apache-2.0 · last push 2026-03-25Going stale
tesseract 76,239★ Apache-2.0Old-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:

NeedToolVerifiedVerdict
EXIF/GPS strippinglovell/sharp 32,613★ Apache-2.0Audit first, then fix (Node action only)
EXIF detectionmattiasw/ExifReader 997★ MPL-2.0Pure JS, default runtime
CDN + resizeimgproxy 11,034★ Apache-2.0 · 08-27Only if egress hurts
thumbor 10,514★ MIT · 08-27Python, heavier
Perceptual dedupefacebook/ThreatExchange (PDQ) 1,377★ NOASSERTIONReal fit for reposted content, but a project
Video transcodenode-fluent-ffmpeg 8,240★ MITARCHIVED 2025-05-22Don't adopt; call ffmpeg directly
Adaptive streaminghls.js 16,904★ · MuxOverkill — 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 ~/Downloads works 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/husky 35,292★ MIT (last push 2026-03-19, stable not stale) + lint-staged 14,720★ MIT · 2026-08-27 — a pre-push hook running npm run lint && npm run build is 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; the driveScan/googleDrive split already shows he knows the pattern.

6. New product surface

SurfaceCostVerdict
Presence on recordsget-convex/presence 19★Hours. Reactivity is already paid for.
Real-time dashboardsAlready have itConvex queries are live by default — verify no polling exists
Mobile app (Expo)expo/expo 51,884★ MITReal 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 outConvex httpAction nativeDays
Public creator portalConvex + authWeeks — depends on the auth rebuild
Collaborative editingprosemirror-sync 62★Days, if there's a document surface
Offline supportReal project. Skip.

Convex already does this — skip the dependency

  1. Cron schedulingcronJobs() is native and his crons.ts is correct. Don't install the crons component.
  2. Vector search — native vectorIndex(). No pgvector, no external vector DB.
  3. Full-text search — native searchIndex(). He has zero. No Meilisearch/Typesense/Algolia needed.
  4. Backups — native, plus npx convex export. No backup tooling.
  5. Exception reporting — native Sentry/PostHog integration. Don't npm i @sentry/node into functions.
  6. Real-time subscriptions — every query is live. No Pusher/Ably/socket.io.
  7. File storagectx.storage works. R2 is a cost optimization, not a capability.
  8. Preview environments / DB branching — native preview deployments with isolated data.
  9. Basic job schedulingctx.scheduler is fine for fire-and-forget; upgrade only where durability matters.
  10. End-to-end types_generated/api.d.ts already 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 + rag components 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).

Canonical source remains research/lanes/06-platform-multipliers.md. This HTML is a generated projection; edit the source, then run generate-docs.mjs.