The Problem

Organizations that need live, shareable dashboards from multiple APIs and databases typically must stitch together custom ETL, UI, and scheduling logic. This repo supplies a ready‑made platform that connects to SQL/NoSQL sources, offers an AI assistant, and publishes embeddable charts, but the codebase contains several structural weaknesses that affect maintainability and security.

What This Does

Chartbrew is a full‑stack web app for building and sharing dashboards. The client (client/src/App.jsx, client/src/reducers/index.js, client/src/sources/index.js) renders the UI, manages state through Redux slices (client/src/slices/team.js, client/src/slices/project.js, client/src/slices/chart.js) and provides data‑source adapters under client/src/sources/. The server (server/api/index.js, server/controllers/ChartController.js, server/models/models/index.js) exposes REST endpoints, handles authentication, and orchestrates queries to MySQL/PostgreSQL or external APIs. Docker (Dockerfile, docker-compose.yml) and GitHub Actions (.github/workflows/ci.yml) provide containerised deployment and CI. The AI assistant lives in client/src/containers/Ai/ and integrates with the data‑source layer via client/src/api/ai.js.

How It Is Wired

Execution starts at the client entry client/index.html → client/src/App.jsx which mounts the React router and loads the Redux store. User actions flow through action creators (client/src/actions/*.js) into reducers (client/src/reducers/index.js). The most‑connected module is server/models/models/index (111 importers, 2 importers, instability 0.02), a hub that model controllers depend on; changes here have a high‑blast radius. A circular import cycle involves server/controllers/ChartController.js, server/sources/index.js, and server/controllers/DatasetController.js (each imports the other, instability 0.5). The data‑source index client/src/sources/index (8 importers, 37 imported, instability 0.82) is another high‑degree node; any new source adapter ripples through many components. Import cycles and the hub model mean refactors must carefully extract shared types or defer imports to avoid breaking downstream modules.

How To Use It

Setup

git clone https://github.com/moses-y/chartbrew
cd chartbrew && npm run setup

Edit chartbrew/.env with the required variables (DB credentials, CB_ENCRYPTION_KEY, etc.) as documented in the README.

Configuration

  • Database: create an empty MySQL 5+ or PostgreSQL 12.5+ database; the name must match CB_DB_NAME.
  • Encryption key: generate a 32‑byte hex string with node -e "console.log(require('crypto').randomBytes(32).toString('hex'))" and set it as CB_ENCRYPTION_KEY.

Running it Start the front‑end and back‑end in separate terminals:

# frontend
cd client/
npm run start        # Vite dev server, defaults to http://localhost:4018

# backend
cd server/
npm run start-dev    # Express with nodemon

Real‑World Use

A product team wants an internal KPI dashboard that pulls sales data from a PostgreSQL database and a third‑party API. They add a new SQL source via the UI (client/src/containers/AddChart/components/VisualSQL.jsx), which stores the connection config in server/models/models/index. The AI assistant (client/src/containers/Ai/AiComposer.jsx) can then suggest query syntax, and the resulting chart is embeddable via an iframe snippet generated by client/src/containers/Chart/Chart.jsx. Scheduling is configured in the UI and persisted through server/controllers/ChartController.js.

Code Health & Issues

  • Measured analysis (static, 778 files): 278 total findings – 69 high, 209 medium, 0 low, in 5 categories.
  • Hub modules: server/models/models/index.js, client/src/slices/team.js, client/src/components/Row.jsx – 111, 72, 62 importers respectively.
  • Oversized files: server/controllers/ChartController.js, client/src/slices/project.js, client/src/slices/chart.js – >1400 lines each.
  • Import cycles: server/controllers/ChartController.js, server/sources/index.js, server/controllers/DatasetController.js.
  • High branching density: same three files plus client/src/containers/Chart/components/ChartTooltip.js.
  • Deep nesting: server/controllers/DatasetController.js, client/src/containers/Dataset/DataTransform.jsx, client/src/containers/Chart/Chart.jsx – max indent 6.
  • Code‑health audit (11 findings, ranked):
  • CRITICAL – Keep secrets out of workflows a fork can trigger – .github/workflows/cla.yml (PERSONAL_ACCESS_TOKEN).
  • HIGH – Pin third‑party GitHub Actions to commit SHA – .github/workflows (schneegans/dynamic-badges-action@v1.6.0, codecov/codecov-action@v5, contributor-assistant/github-action@v2.6.1).
  • HIGH – Replace wildcard CORS origin with explicit allow list – server/index.js.
  • HIGH – Remove continue-on-error from correctness‑gate steps – .github/workflows/ci.yml line 42.
  • MEDIUM – Declare least‑privilege GITHUB_TOKEN permissions – .github/workflows/badges.yml.
  • MEDIUM – Enable Dependabot or Renovate – no bot configured (4 manifests).
  • MEDIUM – Pin container base image by digest – Dockerfile uses node:22-slim.
  • MEDIUM – Set persist-credentials: false on checkout – .github/workflows/ci.yml.
  • MEDIUM – Add non‑root USER to the image – Dockerfile has no USER directive.
  • LOW – Set timeout-minutes on workflow jobs – .github/workflows/badges.yml declares no job timeout.

The Bottom Line

Chartbrew delivers a capable, self‑hosted dashboard platform with AI assistance and broad data‑source support, but the codebase suffers from a few high‑impact hubs, import cycles, and security‑related CI configurations. Teams that can tolerate periodic refactoring to flatten the most‑connected modules and tighten CI secrets handling will find it a solid starting point; others may need dedicated effort to restructure the controller and source layers before scaling.