ArchitectureMonorepo Layout

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 config

apps/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)/ and app/(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 the survey-ui and 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:

PackagePurpose
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 dev

The 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 the sentiment column.
  • webhook_dispatch.go — delivers outbound webhooks with retry/backoff. The test file webhook_dispatch_test.go shows 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

  1. Shared types live in packages/types/. Do not redefine a domain type in apps/web/. Import it from @hivecfm/types.
  2. Cross-service contracts live as YAML. hivecfm-core/openapi.yml is the canonical REST contract; the Hub publishes its own at hivecfm-hub/openapi.yaml. Both are mirrored into this dev hub under generated/.