Monorepo Layout
HiveCFM is two repos. hivecfm-core is a pnpm + Turbo TypeScriptTypeScriptJavaScript with a static type system. Every HiveCFM Node service, the frontend, and the dev hub are written in it. monorepo that holds every user-facing app, API, and shared library. hivecfm-hub is a Go service with its own cmd/ and internal/ layout. This page documents the folders that exist today — every path below was checked against the current tree.
hivecfm-core/
hivecfm-core/
├── apps/
│ ├── web/ # The main Next.js 14 app (App Router)
│ ├── license-portal/ # Separate Next.js app for licence self-service
│ └── storybook/ # Component explorer
├── packages/ # Shared libraries (pnpm workspaces)
├── docker/ # Dockerfiles for the web and worker images
├── nginx/ # Reverse-proxy config
├── superset/ # Superset container config + dashboards
├── openapi.yml # API contract, mirrored into the dev hub
├── docker-compose.yml # Full-stack services
├── docker-compose.dev-ports.yml # Overlay that exposes postgres:5433 + redis:6380
├── pnpm-workspace.yaml # Workspace declaration
├── turbo.json # Turbo task graph
└── vitest.workspace.ts # Shared Vitest configapps/web/ — the main app
The Next.jsNext.jsReact framework used by HiveCFM Core. Handles routing, server rendering, and API routes in one bundle. 14 App Router application. Relevant subfolders:
app/— Router. Routes live as nested folders.app/api/holds route handlers (the REST surface);app/(auth)/andapp/(app)/are route groups.modules/— Feature modules (survey, campaigns, responses, analysis, email, organization, etc.). The business logic each route calls into.lib/— Cross-cutting helpers: logger wiring, Prisma client, feature flags.middleware.ts— Edge middleware (auth gating, locale detection).playwright/— End-to-end tests.
apps/license-portal/ and apps/storybook/
license-portal/— A smaller Next.js app that handles commercial-licence issuance and downloads. Deployed separately from the main web app.storybook/— Storybook for thesurvey-uiand shared UI packages; runs on port 6009 in dev.
packages/ — the 16 shared workspaces
Every package exports a small, typed surface. The ones you will open most often:
| Package | Purpose |
|---|---|
packages/database/ | PrismaPrismaThe TypeScript ORM HiveCFM uses to talk to Postgres. The schema lives at packages/database/schema.prisma. schema + migrations + generated client. schema.prisma is here. |
packages/cache/ | RedisRedisIn-memory key-value store used for caching, sessions, and rate limiting. Runs on port 6380 locally. client wrapper used by the web and workers. |
packages/storage/ | S3/MinIOMinIOS3-compatible object storage for survey attachments and uploads. Runs locally; swaps for real S3 in prod. client for uploads and exports. |
packages/types/ | Shared TypeScriptTypeScriptJavaScript with a static type system. Every HiveCFM Node service, the frontend, and the dev hub are written in it. domain types — import these rather than redefining. |
packages/logger/ | Structured JSON logger with request-scoped context. |
packages/email/ | Email rendering + transport adapter (SMTP, SES, MailHog in dev). |
packages/surveys/ | Core survey domain logic (question types, branching, scoring). |
packages/survey-ui/ | ReactReactThe component-based UI library every HiveCFM frontend is written in. Components are TypeScript functions returning JSX. components that render surveys (shared with embeds). |
packages/js-core/ | The public JS SDK that customer apps embed. |
packages/i18n-utils/ | Locale helpers used by both the app and the SDK. |
packages/license-crypto/ | Key generation and verification for the licence portal. |
packages/config-eslint/ | Shared ESLint config. |
packages/config-prettier/ | Shared Prettier config. |
packages/config-typescript/ | Base tsconfig.json variants. |
packages/vite-plugins/ | Build-time plugins used by Vitest and Storybook. |
hivecfm-hub/
hivecfm-hub/
├── cmd/
│ ├── api/ # main.go — HTTP server + worker bootstrap
│ ├── backfill-embeddings/ # One-shot CLI for embedding old rows
│ └── backfill-sentiment/ # One-shot CLI for scoring old rows
├── internal/
│ ├── api/ # HTTP handlers
│ ├── service/ # Business logic (embeddings, webhooks, search)
│ ├── repository/ # Postgres access (squirrel + pgx)
│ ├── workers/ # River workers — one file per job type
│ ├── models/ # Go domain types (mirrors Prisma)
│ ├── config/ # Env-var loading + validation
│ ├── googleai/ # Google AI / Gemini client
│ ├── openai/ # OpenAI client
│ ├── observability/ # Logger + metrics wiring
│ ├── huberrors/ # Typed errors
│ └── datatypes/ # Custom scalars used across layers
├── migrations/ # Goose SQL migrations for the hub's own tables
├── api/ # OpenAPI spec + generated code
├── pkg/ # Exportable helpers (thin)
├── tests/ # Integration tests
├── Makefile # `make build`, `make test`, `make init-db`, …
├── go.mod # Go 1.25 minimum
└── compose.yml # Standalone postgres for native devThe workers you will actually touch
hivecfm-hub/internal/workers/ contains one file per job type. As of today:
feedback_embedding.go— computes a vector for each new response and writes it back.sentiment_analysis.go— scores response text and updates thesentimentcolumn.webhook_dispatch.go— delivers outbound webhooks with retry/backoff. The test filewebhook_dispatch_test.goshows the pattern.
When you add a new worker, copy webhook_dispatch.go as the template: it has the full RiverRiverThe Go background-job queue Hub uses. Jobs are rows in Postgres, so there is no separate broker to run. worker interface, args type, and a matching service call.
Two invariants
- Shared types live in
packages/types/. Do not redefine a domain type inapps/web/. Import it from@hivecfm/types. - Cross-service contracts live as YAML.
hivecfm-core/openapi.ymlis the canonical REST contract; the Hub publishes its own athivecfm-hub/openapi.yaml. Both are mirrored into this dev hub undergenerated/.