CodeCharta City Visualization Research¶
Status: Research Document Created: March 2026 Scope: Forma 3D Connect — Code-as-a-City Visualization with SonarCloud + Git History
Table of Contents¶
- Executive Summary
- What Is CodeCharta
- Data Sources & Metrics
- Option A — Local Developer Workstation
- Option B — CI-Generated Artifacts (No Serving)
- Option C — Hosted Web Studio + Docs-Served Data (Recommended)
- Option D — CI-Generated + Self-Hosted Visualization Container
- Architecture Diagrams
- SonarCloud Integration Details
- Git History Integration Details
- Merging Sonar + Git Metrics
- Pipeline Integration (Azure DevOps)
- Cost & Resource Analysis
- Security Considerations
- Comparison Matrix
- Recommended Approach
- Implementation Roadmap
- References
1. Executive Summary¶
CodeCharta is an open-source tool by MaibornWolff that transforms code metrics into an interactive 3D city visualization. Each file becomes a building — its footprint represents size (lines of code), height represents complexity, and color represents quality indicators. The result is an immediately comprehensible view of hotspots, tech debt, and change frequency across the entire codebase.
CodeCharta can ingest metrics from SonarCloud (which we already run in our Azure DevOps pipeline) and git history (which we already have). No additional scanning infrastructure is needed.
Key Findings¶
| Aspect | A: Local | B: CI Artifact | C: Hosted Studio + Docs Data | D: Self-Hosted Container |
|---|---|---|---|---|
| Setup effort | 10 min | 2–4 hrs | 2–4 hrs | 4–8 hrs |
| Ongoing maintenance | None | Minimal | Minimal | Low |
| Team access | Single developer | Download artifact | Shareable URL | Shareable URL |
| Freshness | On-demand | Per-pipeline run | Per-pipeline run | Per-pipeline run |
| Infrastructure cost | $0 | $0 | $0 | ~$0 (extra container) |
| Extra container needed | No | No | No | Yes |
| Recommended for | Exploration / POC | Small teams | Team-wide adoption | Full self-hosting |
Recommendation¶
Start with Option A (local) for immediate validation, then move to Option C — generate the .cc.json in CI and serve it from the existing docs container; use the publicly hosted CodeCharta Web Studio at codecharta.com for visualization. No extra Docker image, no extra DNS record — just a shareable URL. The CI pipeline already has a Code Quality stage; the CodeCharta generation step slots in after it.
2. What Is CodeCharta¶
CodeCharta consists of two components:
| Component | Purpose | Distribution |
|---|---|---|
| CCSH (CodeCharta Shell) | CLI that imports, parses, and merges metrics into .cc.json files |
npm i -g codecharta-analysis or codecharta/codecharta-analysis Docker image |
| Web Studio | Browser-based 3D visualization that renders .cc.json files |
codecharta/codecharta-visualization Docker image or hosted instance |
The data flow is straightforward:
Source (Sonar API / git repo) → CCSH → .cc.json → Web Studio → 3D City Map
Key features relevant to us:
- SonarCloud importer — pulls all metrics via the SonarCloud Web API using a user token
- Git log parser — extracts commit history metrics (authors, churn, coupling, age)
- Merge filter — combines multiple
.cc.jsonfiles into one enriched map - URL parameter loading — Web Studio can auto-load
.cc.jsonfiles from a URL - Delta mode — compare two snapshots to see what changed between sprints/releases
- Runs entirely client-side — no metrics ever leave the browser once loaded
3. Data Sources & Metrics¶
3.1 SonarCloud Metrics (via sonarimport)¶
These are already computed by our SonarCloud analysis. CodeCharta pulls them via API:
| Metric | City Dimension | Value |
|---|---|---|
ncloc (lines of code) |
Building footprint (area) | File size |
complexity / cognitive_complexity |
Building height | Complexity hotspots |
code_smells |
Building color (red) | Quality issues |
bugs |
Building color (red) | Defects |
vulnerabilities |
Building color (red) | Security issues |
coverage |
Building color (green→red) | Test coverage |
duplicated_lines_density |
Alternative color metric | Code duplication |
sqale_index (tech debt) |
Alternative height | Debt in minutes |
3.2 Git History Metrics (via gitlogparser)¶
These are extracted directly from the git repository:
| Metric | Insight |
|---|---|
number_of_authors |
Knowledge distribution — single-author files are bus-factor risks |
number_of_commits |
Change frequency — frequently changed files deserve more attention |
weeks_with_commits |
Sustained activity vs. burst edits |
age_in_weeks |
File age — old + complex = likely tech debt |
highly_coupled_files |
Files that always change together (hidden dependencies) |
number_of_renames |
Refactoring churn |
fix_commits / hotfix_commits |
Bug-prone files |
3.3 Combined View (Merged)¶
The real power comes from merging both sources:
- Area =
ncloc(lines of code) → big buildings are big files - Height =
cognitive_complexity(from Sonar) → tall buildings are complex - Color =
number_of_commits(from git) → red buildings change often - Edge metric =
temporal_coupling→ lines connect files that always change together
This immediately highlights hotspots: large, complex files that change frequently — the prime candidates for refactoring.
4. Option A — Local Developer Workstation¶
The fastest way to validate CodeCharta's value. Run everything on your MacBook.
Prerequisites¶
- Node.js >= 20 (already available)
- Java >= 11 (
brew install openjdk@21) - SonarCloud user token (generate at sonarcloud.io → My Account → Security)
Steps¶
# 1. Install CodeCharta CLI
npm i -g codecharta-analysis
# 2. Import SonarCloud metrics
ccsh sonarimport \
https://sonarcloud.io \
devgem_forma-3d-connect \
--user-token=<YOUR_SONARCLOUD_TOKEN> \
--output-file=sonar.cc.json
# 3. Parse git history (repo-scan mode — no manual log extraction)
ccsh gitlogparser repo-scan \
--repo-path /Users/jeankedotcom/devgem/forma-3d-connect \
--add-author \
-o git.cc.json
# 4. Merge both into a single enriched map
ccsh merge --leaf sonar.cc.json git.cc.json -o forma3d.cc.json
# 5. Open in Web Studio (Docker)
docker run -d -p 9100:80 codecharta/codecharta-visualization
# 6. Open browser → localhost:9100 → Import → upload forma3d.cc.json
macOS note: When using the Docker analysis container, add
--user=501:dialoutbefore the image name to avoid git permission issues.
Alternative: All-in-Docker (No npm Install)¶
# Run analysis entirely in Docker
docker run --rm \
-v $(pwd):/src \
--user=501:dialout \
-w /src \
codecharta/codecharta-analysis bash -c '
git config --global --add safe.directory /src &&
ccsh sonarimport https://sonarcloud.io devgem_forma-3d-connect \
--user-token=<TOKEN> -o sonar.cc.json -nc &&
ccsh gitlogparser repo-scan --repo-path /src --add-author -o git.cc.json -nc &&
ccsh merge --leaf sonar.cc.json git.cc.json -o forma3d.cc.json -nc
'
Effort & Outcome¶
| Aspect | Detail |
|---|---|
| Setup time | ~10 minutes |
| Output | forma3d.cc.json file on disk + local Web Studio |
| Who can access | Developer who ran the command |
| When to refresh | Manually, whenever desired |
5. Option B — CI-Generated Artifacts (No Serving)¶
Generate the .cc.json in the Azure DevOps pipeline as a build artifact. Team members download and open it in the hosted Web Studio.
How It Works¶
Pipeline YAML Fragment¶
- stage: CodeCharta
displayName: 'CodeCharta City Map'
dependsOn: CodeQuality
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- job: GenerateCityMap
displayName: 'Generate CodeCharta Map'
pool:
vmImage: 'ubuntu-latest'
container:
image: codecharta/codecharta-analysis
steps:
- checkout: self
fetchDepth: 0 # Full history for gitlogparser
- script: |
git config --global --add safe.directory $(Build.SourcesDirectory)
ccsh sonarimport \
https://sonarcloud.io \
devgem_forma-3d-connect \
--user-token=$(SONARCLOUD_TOKEN) \
-o sonar.cc.json -nc
ccsh gitlogparser repo-scan \
--repo-path $(Build.SourcesDirectory) \
--add-author \
-o git.cc.json -nc
ccsh merge --leaf sonar.cc.json git.cc.json \
-o $(Build.ArtifactStagingDirectory)/forma3d.cc.json -nc
displayName: 'Generate city map from SonarCloud + Git'
- publish: $(Build.ArtifactStagingDirectory)/forma3d.cc.json
artifact: codecharta-map
displayName: 'Publish CodeCharta artifact'
Effort & Outcome¶
| Aspect | Detail |
|---|---|
| Setup time | 2–4 hours (pipeline + token setup) |
| Output | Downloadable artifact per main build |
| Who can access | Anyone with Azure DevOps access |
| When to refresh | Every main branch build |
6. Option C — Hosted Web Studio + Docs-Served Data (Recommended)¶
The simplest path to team-wide access: generate the .cc.json in CI, bake it into the existing docs container, and use the publicly hosted CodeCharta Web Studio at codecharta.com for visualization. No extra Docker image, no extra DNS, no extra docker-compose entry.
The key insight: CodeCharta's Web Studio runs entirely in the browser. It can load .cc.json files from any URL via the ?file= query parameter, as long as the server responds with the correct CORS header.
Architecture¶
What Changes¶
Only two files need modification — no new containers:
1. Nginx config — add a CORS-enabled location for /codecharta/:
# Added to deployment/docs/nginx.conf inside the server block
location /codecharta/ {
add_header Access-Control-Allow-Origin "https://codecharta.com" always;
add_header Access-Control-Allow-Methods "GET, OPTIONS" always;
add_header Access-Control-Allow-Headers "Range" always;
add_header Cache-Control "no-cache";
try_files $uri =404;
}
2. Docs Dockerfile — copy the pipeline-generated .cc.json into the image:
# Added to deployment/docs/Dockerfile in the production stage
# The cc.json is generated by the CodeCharta pipeline stage and placed
# in the build context before the Docker build runs.
COPY codecharta/forma3d.cc.json /usr/share/nginx/html/codecharta/forma3d.cc.json
Shareable URLs¶
Users receive a single link. The CodeCharta Web Studio handles everything in the browser:
| Link | View |
|---|---|
codecharta.com/visualization/app/index.html?file=https://staging-connect-docs.forma3d.be/codecharta/forma3d.cc.json&area=ncloc&height=cognitive_complexity&color=code_smells |
Complexity hotspots |
...&area=ncloc&height=number_of_commits&color=number_of_authors |
Change frequency & knowledge silos |
...&area=ncloc&height=sqale_index&color=coverage |
Tech debt vs. coverage |
...&file=.../sprint-42.cc.json&file=.../sprint-43.cc.json&mode=Delta |
Sprint-over-sprint delta |
Why This Works¶
- CodeCharta Web Studio is a static JavaScript app — all rendering happens client-side
- The
?file=parameter triggers an XHR fetch to the provided URL - As long as the Nginx serving the
.cc.jsonresponds withAccess-Control-Allow-Origin: https://codecharta.com, the fetch succeeds - No source code is ever sent anywhere — the
.cc.jsononly contains file paths and numeric metrics
Effort & Outcome¶
| Aspect | Detail |
|---|---|
| Setup time | 2–4 hours (pipeline stage + Nginx tweak + Dockerfile tweak) |
| Output | Shareable URL that opens a pre-loaded 3D city map |
| Who can access | Anyone with the link |
| When to refresh | Every main branch build (map updates with docs image) |
| Extra infrastructure | None — reuses existing docs container |
7. Option D — CI-Generated + Self-Hosted Visualization Container¶
A heavier alternative if you want full control over the visualization (e.g., to customize the UI, run offline, or avoid any dependency on codecharta.com).
Custom Dockerfile¶
# deployment/codecharta/Dockerfile
FROM codecharta/codecharta-visualization:latest
COPY forma3d.cc.json /usr/share/nginx/html/data/forma3d.cc.json
RUN sed -i 's|<head>|<head><script>if(!location.search)location.search="file=data/forma3d.cc.json\&area=ncloc\&height=cognitive_complexity\&color=number_of_commits";</script>|' \
/usr/share/nginx/html/index.html
Docker Compose Addition¶
codecharta:
image: registry.digitalocean.com/forma-3d/forma3d-connect-codecharta:${BUILD_NUMBER:-latest}
restart: unless-stopped
labels:
- "traefik.enable=true"
- "traefik.http.routers.codecharta.rule=Host(`codecharta.forma3d.be`)"
- "traefik.http.routers.codecharta.entrypoints=websecure"
- "traefik.http.routers.codecharta.tls.certresolver=letsencrypt"
- "traefik.http.services.codecharta.loadbalancer.server.port=80"
networks:
- web
Effort & Outcome¶
| Aspect | Detail |
|---|---|
| Setup time | 4–8 hours (Dockerfile, pipeline, DNS, docker-compose) |
| Output | Self-hosted visualization at codecharta.forma3d.be |
| Who can access | Anyone with the URL |
| Extra infrastructure | New container (~15 MB / ~20 MB RAM), new DNS record |
8. Architecture Diagrams¶
8.1 Data Flow — End to End¶
8.2 Pipeline Integration — Option C (Recommended)¶
8.3 Option C vs Option D — No Extra Container Needed¶
9. SonarCloud Integration Details¶
8.1 API Access¶
CodeCharta's sonarimport communicates with the same Web API that SonarCloud exposes. The command syntax is identical for SonarCloud and SonarQube — only the URL and authentication differ.
| Parameter | Our Value |
|---|---|
| URL | https://sonarcloud.io |
| Project Key | devgem_forma-3d-connect |
| Organization | devgem (implicit in project key) |
| Token | SonarCloud user token (generate under My Account → Security) |
8.2 Command¶
ccsh sonarimport \
https://sonarcloud.io \
devgem_forma-3d-connect \
--user-token=$SONARCLOUD_TOKEN \
--output-file=sonar.cc.json
8.3 Metric Selection¶
By default, sonarimport pulls all available metrics. To limit to the most useful ones:
ccsh sonarimport \
https://sonarcloud.io \
devgem_forma-3d-connect \
--user-token=$SONARCLOUD_TOKEN \
--metrics=ncloc,complexity,cognitive_complexity,code_smells,bugs,vulnerabilities,coverage,duplicated_lines_density,sqale_index \
--output-file=sonar.cc.json
8.4 SonarCloud Token Management¶
| Environment | Storage |
|---|---|
| Local | ~/.codecharta/sonarcloud-token or environment variable |
| Azure DevOps | Secret variable in forma3d-staging variable group |
10. Git History Integration Details¶
9.1 repo-scan Mode (Recommended)¶
The simplest approach — point the parser at the repo and it handles everything:
ccsh gitlogparser repo-scan \
--repo-path . \
--add-author \
-o git.cc.json
Important for CI: The pipeline checkout step must use fetchDepth: 0 (full clone) instead of the default shallow clone, otherwise git history will be incomplete.
9.2 log-scan Mode (Alternative)¶
For environments where direct repo access is awkward:
git log --numstat --raw --topo-order --reverse -m > git.log
git ls-files > file-list.txt
ccsh gitlogparser log-scan \
--git-log git.log \
--repo-files file-list.txt \
-o git.cc.json
9.3 Edge Metrics¶
The git log parser produces edge metrics (temporal coupling between files). These appear as connecting lines in the city map, revealing hidden dependencies — files that always change together but may not have explicit import relationships.
11. Merging Sonar + Git Metrics¶
10.1 Merge Strategy¶
Use --leaf merging to fit git metrics into the Sonar project structure:
ccsh merge --leaf sonar.cc.json git.cc.json -o forma3d.cc.json
The --leaf strategy matches files by name (leaf node) rather than full path, which handles cases where SonarCloud and git may have slightly different path structures.
10.2 Pipe-Through Alternative¶
Some importers support piping, avoiding the need for intermediate files:
ccsh sonarimport https://sonarcloud.io devgem_forma-3d-connect \
--user-token=$TOKEN -o sonar.cc.json -nc | \
ccsh gitlogparser repo-scan --repo-path . --add-author -o forma3d.cc.json -nc
10.3 Delta Maps¶
For sprint-over-sprint comparison, generate maps at two points in time and load both in Delta mode:
codecharta.forma3d.be/?file=data/sprint-42.cc.json&file=data/sprint-43.cc.json&mode=Delta
This highlights what grew, shrank, or changed quality between sprints.
12. Pipeline Integration (Azure DevOps)¶
12.1 Where It Fits¶
The CodeCharta stage runs after Code Quality (SonarCloud) and before Build & Package. It depends on SonarCloud completion because it needs the analysis results available via the SonarCloud API.
12.2 Full Pipeline YAML¶
# Addition to azure-pipelines.yml
- stage: CodeCharta
displayName: 'CodeCharta City Map'
dependsOn: CodeQuality
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
jobs:
- job: GenerateCityMap
displayName: 'Generate CodeCharta Map'
pool:
vmImage: 'ubuntu-latest'
steps:
- checkout: self
fetchDepth: 0
- task: DockerInstaller@0
inputs:
dockerVersion: '24.0'
- script: |
docker run --rm \
-v $(Build.SourcesDirectory):/src \
-w /src \
codecharta/codecharta-analysis bash -c '
git config --global --add safe.directory /src &&
ccsh sonarimport \
https://sonarcloud.io \
devgem_forma-3d-connect \
--user-token=$(SONARCLOUD_CODECHARTA_TOKEN) \
-o sonar.cc.json -nc &&
ccsh gitlogparser repo-scan \
--repo-path /src \
--add-author \
-o git.cc.json -nc &&
ccsh merge --leaf sonar.cc.json git.cc.json \
-o /src/forma3d.cc.json -nc
'
displayName: 'Generate city map'
- publish: $(Build.SourcesDirectory)/forma3d.cc.json
artifact: codecharta-map
displayName: 'Publish CodeCharta artifact'
12.3 Token Configuration¶
Add a secret variable SONARCLOUD_CODECHARTA_TOKEN to the forma3d-staging variable group. This is a read-only SonarCloud user token — separate from the existing SonarCloud service connection token used for analysis.
13. Cost & Resource Analysis¶
| Cost Category | Option A (Local) | Option B (CI Artifact) | Option C (Hosted + Docs) | Option D (Self-Hosted) |
|---|---|---|---|---|
| Infrastructure | $0 | $0 | $0 | $0 (shared droplet) |
| CI compute | $0 | ~2 min MS-hosted | ~2 min MS-hosted | ~2 min MS-hosted |
| Docker registry storage | $0 | $0 | $0 (reuses docs image) | ~15 MB (negligible) |
| SonarCloud | Existing plan | Existing plan | Existing plan | Existing plan |
| DNS | N/A | N/A | N/A (reuses docs domain) | New CNAME record |
| Extra container | No | No | No | Yes (~20 MB RAM) |
| Total incremental cost | $0 | ~$0 | $0 | ~$0 |
The codecharta-analysis Docker image (~1.2 GB) is pulled during CI only. On Microsoft-hosted agents, this is cached across builds.
14. Security Considerations¶
| Concern | Mitigation |
|---|---|
| SonarCloud token in CI | Store as secret variable in forma3d-staging variable group; use a read-only user token |
| Metrics data exposure | CodeCharta Web Studio is client-side only — no server-side processing; metrics stay in the browser |
.cc.json public access |
The file contains file paths and numeric metrics — no source code. Low sensitivity, but restrict access via Nginx allow/deny or Traefik IP whitelist if desired |
| Dependency on codecharta.com | The hosted Web Studio is a static JavaScript app. If it goes down, fall back to the Docker image (codecharta/codecharta-visualization) locally or use Option D |
15. Comparison Matrix¶
| Criterion | A: Local | B: CI Artifact | C: Hosted + Docs (Rec.) | D: Self-Hosted Container |
|---|---|---|---|---|
| Setup complexity | Low | Medium | Medium | Medium-High |
| Team accessibility | Single user | Download required | Shareable URL | Shareable URL |
| Freshness | Manual | Per main build | Per main build | Per main build |
| Bookmarkable views | No | No | Yes (URL params) | Yes (URL params) |
| Extra container | No | No | No | Yes |
| Extra DNS record | No | No | No | Yes |
| Infrastructure cost | $0 | $0 | $0 | ~$0 |
| Maintenance | None | Pipeline config | Pipeline + Nginx tweak | Pipeline + container |
| Sprint demo friendly | No | No | Yes | Yes |
| Works if codecharta.com is down | Yes | Yes | No (fallback: local Docker) | Yes |
| CI pipeline changes | None | New stage | New stage | New stage + Dockerfile |
16. Recommended Approach¶
Phase 1: Validate (Week 1)¶
Option A — Local exploration
- Install CCSH:
npm i -g codecharta-analysis - Generate a merged map from SonarCloud + git
- Open in Web Studio (either
docker run -p 9100:80 codecharta/codecharta-visualizationor atcodecharta.com) - Evaluate whether the city view provides actionable insights for the team
Phase 2: Automate (Week 2)¶
Option C — Hosted Web Studio + Docs-served data
- Add
SONARCLOUD_CODECHARTA_TOKEN(read-only) to pipeline variables - Add the CodeCharta generation stage to
azure-pipelines.yml - Add CORS location block to
deployment/docs/nginx.conf - Add
COPYline todeployment/docs/Dockerfilefor the.cc.json - Test end-to-end: pipeline generates map → docs image includes it → codecharta.com loads it
Phase 3: Operationalize (Week 3+)¶
- Share bookmarked URLs for different views (complexity, churn, coverage)
- Add delta maps for sprint comparison
- Integrate link into the docs site sidebar
- Consider historical map archiving for trend analysis
Implementation Checklist¶
17. Implementation Roadmap¶
18. References¶
| Resource | URL |
|---|---|
| CodeCharta Introduction | https://codecharta.com/docs/overview/introduction |
| CodeCharta Getting Started | https://codecharta.com/docs/overview/getting-started |
| Sonar Importer Docs | https://codecharta.com/docs/importer/sonar |
| Git Log Parser Docs | https://codecharta.com/docs/parser/git-log |
| Merge Filter Docs | https://codecharta.com/docs/filter/merge-filter |
| Docker Containers | https://codecharta.com/docs/overview/dockerized |
| Load Maps from URL | https://codecharta.com/docs/how-to/load-map-using-url |
| SonarCloud + Git How-To | https://codecharta.com/docs/how-to/analyze-with-sonar-git-and-svn |
| Docker Hub — Analysis | https://hub.docker.com/r/codecharta/codecharta-analysis |
| Docker Hub — Visualization | https://hub.docker.com/r/codecharta/codecharta-visualization |
| Automated Sonar Analysis | https://codecharta.com/docs/how-to/automated-sonar-analysis |
| Existing SonarCloud Research | sonarqube-code-quality-research.md |