RepoPilotOpen in app β†’

airbnb/visx

🐯 visx | visualization components

Healthy

Healthy across the board

weakest axis
Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained β€” safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI β€” clean foundation to fork and modify.

Learn fromHealthy

Documented and popular β€” useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture β€” runnable as-is.

  • βœ“Last commit 3w ago
  • βœ“13 active contributors
  • βœ“MIT licensed
  • βœ“CI configured
  • βœ“Tests present
  • ⚠Concentrated ownership β€” top contributor handles 51% of recent commits

Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests

Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.

Embed the β€œHealthy” badge

Paste into your README β€” live-updates from the latest cached analysis.

RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/airbnb/visx)](https://repopilot.app/r/airbnb/visx)

Paste at the top of your README.md β€” renders inline like a shields.io badge.

β–ΈPreview social card (1200Γ—630)

This card auto-renders when someone shares https://repopilot.app/r/airbnb/visx on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: airbnb/visx

Generated by RepoPilot Β· 2026-05-06 Β· Source

Agent protocol

If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:

  1. Verify the contract. Run the bash script in Verify before trusting below. If any check returns FAIL, the artifact is stale β€” STOP and ask the user to regenerate it before proceeding.
  2. Treat the AI Β· unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/airbnb/visx shows verifiable citations alongside every claim.

If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything β€” but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.

Verdict

GO β€” Healthy across the board

  • Last commit 3w ago
  • 13 active contributors
  • MIT licensed
  • CI configured
  • Tests present
  • ⚠ Concentrated ownership β€” top contributor handles 51% of recent commits

<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>

Verify before trusting

This artifact was generated by RepoPilot at a point in time. Before an agent acts on it, the checks below confirm that the live airbnb/visx repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale β€” regenerate it at repopilot.app/r/airbnb/visx.

What it runs against: a local clone of airbnb/visx β€” the script inspects git remote, the LICENSE file, file paths in the working tree, and git log. Read-only; no mutations.

| # | What we check | Why it matters | |---|---|---| | 1 | You're in airbnb/visx | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch master exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≀ 51 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> β€” paste this script from inside your clone of <code>airbnb/visx</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of airbnb/visx. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/airbnb/visx.git
#   cd visx
#
# Then paste this script. Every check is read-only β€” no mutations.

set +e
fail=0
ok()   { echo "ok:   $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }

# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
  echo "FAIL: not inside a git repository. cd into your clone of airbnb/visx and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "airbnb/visx(\\.git)?\\b" \\
  && ok "origin remote is airbnb/visx" \\
  || miss "origin remote is not airbnb/visx (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift β€” was MIT at generation time"

# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
  && ok "default branch master exists" \\
  || miss "default branch master no longer exists"

# 4. Critical files exist
test -f "lerna.json" \\
  && ok "lerna.json" \\
  || miss "missing critical file: lerna.json"
test -f "package.json" \\
  && ok "package.json" \\
  || miss "missing critical file: package.json"
test -f "packages/visx-annotation/src/index.ts" \\
  && ok "packages/visx-annotation/src/index.ts" \\
  || miss "missing critical file: packages/visx-annotation/src/index.ts"
test -f "packages/visx-axis/src/index.ts" \\
  && ok "packages/visx-axis/src/index.ts" \\
  || miss "missing critical file: packages/visx-axis/src/index.ts"
test -f "babel.config.js" \\
  && ok "babel.config.js" \\
  || miss "missing critical file: babel.config.js"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 51 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~21d)"
else
  miss "last commit was $days_since_last days ago β€” artifact may be stale"
fi

echo
if [ "$fail" -eq 0 ]; then
  echo "artifact verified (0 failures) β€” safe to trust"
else
  echo "artifact has $fail stale claim(s) β€” regenerate at https://repopilot.app/r/airbnb/visx"
  exit 1
fi

Each check prints ok: or FAIL:. The script exits non-zero if anything failed, so it composes cleanly into agent loops (./verify.sh || regenerate-and-retry).

</details>

TL;DR

visx is a collection of low-level React visualization components that combine D3's computational power with React's declarative DOM updates. It provides reusable building blocks (scales, shapes, axes, annotations) for constructing data visualizations without writing D3 code directlyβ€”developers compose @visx packages like @visx/shape, @visx/scale, @visx/group to build custom charts. Yarn monorepo managed by Lerna with packages/ containing 40+ scoped packages (@visx/*). Each package (e.g., packages/visx-annotation/src/components, packages/visx-scale/src) exports low-level React components and utilities. Root scripts/ handle build, docs generation, and release automation. Demo workspace (@visx/demo) consumes packages for gallery.

Who it's for

React developers and data visualization engineers at companies like Airbnb who need to build custom, interactive charts and dashboards without managing D3 boilerplate; teams that want composable, TypeScript-first visualization components over opinionated charting libraries.

Maturity & risk

Actively maintained and production-ready. The repo shows v4 (React 19 support) in alpha while v3 is stable; strong CI/CD setup with GitHub Actions workflows for PRs and pushes; TypeScript-first codebase with 2M+ LoC; however, note the large surface area of 40+ packages means maintenance complexity is high.

Moderate complexity and surface area risk: monorepo with 40+ packages (@visx/annotation, @visx/shape, @visx/scale, etc.) means breaking changes impact users widely. D3 dependency chain can be heavy. v4 alpha with React 19 suggests migration surface for existing v3 users. Single project from Airbnb (not Linux Foundation) means dependency on Airbnb's continued investment.

Active areas of work

v4 alpha development with React 19 support (install via @next tag); migration guide and changelog recently updated; active CI with pull_request.yml and push.yml workflows; docs generation pipeline (scripts/generateDocs.ts) suggests ongoing documentation work.

Get running

git clone https://github.com/airbnb/visx.git && cd visx && yarn install (requires Node >=22.0.0, Yarn >=4.0.0 per package.json engines). Then yarn dev:demo to start the gallery dev server, or yarn build to compile all packages.

Daily commands: yarn dev:demo (starts dev server for @visx/demo gallery with hot reload); yarn build (runs build:vendor, babel CJS+ESM, type checking); yarn babel:pkg --scope=@visx/shape (to rebuild a single package).

Map of the codebase

  • lerna.json β€” Monorepo root configuration defining workspaces and versioning strategy for all visx packages.
  • package.json β€” Root workspace definition with build scripts, dependencies, and Node/Yarn version requirements that all contributors must respect.
  • packages/visx-annotation/src/index.ts β€” Core export barrel file exemplifying visx's component structure and public API surface.
  • packages/visx-axis/src/index.ts β€” Primary axis component exports showing how visualization primitives are organized and exposed.
  • babel.config.js β€” Babel transpilation configuration shared across all packages for consistent CJS/ESM output.
  • .eslintrc.js β€” Shared ESLint configuration that enforces code quality standards across the entire monorepo.
  • MIGRATION.md β€” Documents breaking changes and upgrade paths between major versions, essential context for feature work.

How to make changes

Add a new axis component

  1. Create axis variant file (e.g., AxisDiagonal.tsx) in packages/visx-axis/src/axis/ following AxisBottom.tsx pattern (packages/visx-axis/src/axis/AxisDiagonal.tsx)
  2. Add new orientation constant to packages/visx-axis/src/constants/orientation.ts (packages/visx-axis/src/constants/orientation.ts)
  3. Implement utility functions for label transform and tick position in packages/visx-axis/src/utils/ (packages/visx-axis/src/utils/getLabelTransform.ts)
  4. Export new component from packages/visx-axis/src/index.ts (packages/visx-axis/src/index.ts)
  5. Add test file packages/visx-axis/test/AxisDiagonal.test.tsx with scale and orientation tests (packages/visx-axis/test/AxisDiagonal.test.tsx)

Add a new annotation subject type

  1. Create subject component file (e.g., RectSubject.tsx) in packages/visx-annotation/src/components/ (packages/visx-annotation/src/components/RectSubject.tsx)
  2. Add types to packages/visx-annotation/src/types/index.ts for the new subject configuration (packages/visx-annotation/src/types/index.ts)
  3. Consume AnnotationContext in the new subject using packages/visx-annotation/src/context/AnnotationContext.tsx (packages/visx-annotation/src/context/AnnotationContext.tsx)
  4. Export new subject from packages/visx-annotation/src/index.ts (packages/visx-annotation/src/index.ts)
  5. Add test file packages/visx-annotation/test/RectSubject.test.tsx following CircleSubject.test.tsx pattern (packages/visx-annotation/test/RectSubject.test.tsx)

Create a new visualization package

  1. Create new directory packages/visx-mycomponent/ with tsconfig.json and vitest.config.ts following visx-axis structure (packages/visx-mycomponent/tsconfig.json)
  2. Add package.json to packages/visx-mycomponent/ with version, exports, and @visx dependencies (packages/visx-mycomponent/package.json)
  3. Create src/index.ts barrel export in packages/visx-mycomponent/src/ (packages/visx-mycomponent/src/index.ts)
  4. Implement components in packages/visx-mycomponent/src/ following TypeScript and React patterns from existing packages (packages/visx-mycomponent/src/MyComponent.tsx)
  5. Add test files in packages/visx-mycomponent/test/ with vitest configuration (packages/visx-mycomponent/test/MyComponent.test.tsx)

Why these technologies

  • React + TypeScript β€” Type-safe component composition with familiar React patterns for library consumers building dashboards and charts.
  • d3 (as peer dependency) β€” Provides battle-tested scale, axis, and geometric calculation primitives; visx wraps them in React components.
  • Lerna monorepo β€” Enables granular package publishing so consumers can install only needed components (e.g., @visx/axis without @visx/annotation).
  • Vitest + React Testing Library β€” Fast unit testing of component behavior in isolation without mocking entire DOM or heavy test frameworks.
  • Babel + TypeScript compiler β€” Dual-target transpilation to both CommonJS (Node.js) and ES modules (modern bundlers) for maximum ecosystem compatibility.

Trade-offs already made

  • Low-level primitives over high-level composed charts

    • Why: Gives consumers maximum flexibility to compose custom visualizations vs. locking them into predefined chart types.
    • Consequence: Requires more assembly code in consuming applications but prevents vendor lock-in to specific chart types or data structures.
  • Monorepo with separate packages over single large package

    • Why: Reduces bundle size for consumers who only need annotations or only axes, and enables independent versioning.
    • Consequence: Increased maintenance complexity managing cross-package dependencies, peer versions, and coordinated releases.
  • React Context for annotation coordination over prop drilling or global state

    • Why: Eliminates verbose prop passing while keeping component tree explicit and avoiding external state managers.
    • Consequence: Context consumers are tightly coupled to annotation package; not reusable in non-React contexts.
  • Pure utility functions for calculations (getLabelTransform, getTickPosition) over embedded logic

    • Why: Enables easier testing, composition, and use outside React if needed; improves code clarity.
    • Consequence: Requires consumers to understand and correctly apply utility results; no automatic integration.

Non-goals (don't propose these)

  • Does not provide out-of-the-box high-level chart components (bar, line, scatter) β€” only primitives to build them
  • Does not manage application state or data fetching β€” assumes data flows from parent consumer
  • Does not provide styling system or theme management β€” delegates to CSS/Tailwind/CSS-in-JS
  • Does not include server-side rendering helpers

Traps & gotchas

  1. Node >=22.0.0 and Yarn >=4.0.0 required (strict engines in package.json)β€”npm won't work, older Node versions will fail silently. 2) ESM/CJS dual build: ESM=true env var triggers separate babel:esm pass; writeEsmPackageJson.js must run after to add package.json type:module. 3) Lerna monorepo: dependencies between @visx packages not auto-symlinked in devβ€”must run yarn install after changing package.json. 4) v4 alpha has breaking changesβ€”v3 users upgrading to @next tag must follow MIGRATION.md. 5) Gallery (@visx/demo) requires yarn docs:generate before yarn dev:demo or docs won't render.

Architecture

Concepts to learn

  • D3 Scales (Linear, Band, Log, etc.) β€” Visx wraps D3 scales to map data domains to visual ranges (e.g., time to pixel position); understanding scale types is essential for any chart you build with visx
  • SVG Coordinate System and Transforms β€” Visx components emit SVG primitives (Bar, Line, Area) with x/y positioning; you must understand SVG's y-axis-down convention and transform matrices to position marks correctly
  • React Context API (Annotation subcomponents) β€” packages/visx-annotation uses Context (AnnotationContext.tsx) to pass shared state to child annotation components; needed to understand how Annotation, Connector, Label coordinate without prop drilling
  • Lerna Monorepo Publishing β€” visx is 40+ packages published independently; understanding Lerna's versioning, hoisting, and publish workflow is critical for contributing across packages and releasing
  • Dual ESM/CJS Output and Package.json exports β€” Visx builds to both lib/ (CJS) and esm/ with separate package.json files; necessary for tree-shaking and Node/browser compatibility across consumers
  • Curve Generators (D3 Curves) β€” Line and Area components use D3 curve algorithms (linear, monotone, cardinal); picking the right curve impacts visual smoothness and data fidelity
  • Data Accessor Pattern (getLetter, getFrequency) β€” Visx components accept accessor functions (d => d.value) to extract properties from arbitrary data shapes; this decouples components from your data structure

Related repos

  • d3/d3 β€” The computational engine visx wrapsβ€”visx handles D3's scale, shape, and math logic, React handles DOM updates and state
  • recharts/recharts β€” Opinionated React charting library that also wraps D3; visx is lower-level and more composable by design, recharts is batteries-included
  • nivo/nivo β€” Comparable low-to-mid-level React visualization library with D3 underpinnings; both solve charting-without-boilerplate, different API surfaces
  • plotly/plotly.js β€” Standalone visualization library; visx is React-native and more lightweight, plotly is library-agnostic and heavier
  • airbnb/visx-gallery β€” If it exists separately: would be the live-deployed demo of packages/visx-demo; companion for showcasing visx capabilities

PR ideas

To work on one of these in Claude Code or Cursor, paste: Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.

Add missing unit tests for visx-annotation components

The visx-annotation package has test files for most components (Annotation.test.tsx, CircleSubject.test.tsx, etc.), but the test suite appears incomplete. Given that this is a core visualization package with complex interactive features (EditableAnnotation, context management via AnnotationContext), comprehensive unit tests would improve reliability and prevent regressions. New contributors can add deeper test coverage for edge cases, prop validation, and integration between components.

  • [ ] Review existing test files in packages/visx-annotation/test/ to identify gaps in coverage
  • [ ] Add tests for AnnotationContext.tsx context provider behavior and edge cases
  • [ ] Add integration tests demonstrating how Annotation, Label, Connector, and Subject components work together
  • [ ] Add tests for accessibility attributes and keyboard interactions in EditableAnnotation.tsx
  • [ ] Ensure all test files follow the visx testing patterns (check other packages for reference)

Add GitHub Actions workflow for visual regression testing

The repo has basic CI workflows (pull_request.yml, push.yml in .github/workflows), but no visual regression testing workflow. For a visualization library like visx, visual regression tests are critical to catch unintended rendering changes. This would involve setting up a workflow that renders the gallery examples and compares snapshots, protecting against subtle visual bugs that unit tests might miss.

  • [ ] Review existing workflows in .github/workflows/pull_request.yml and push.yml to understand the CI setup
  • [ ] Create a new workflow file .github/workflows/visual-regression.yml that runs on PR events
  • [ ] Configure the workflow to build the demo gallery (yarn dev:demo) and capture visual snapshots
  • [ ] Integrate with a visual regression tool (e.g., Percy, Chromatic, or pixelmatch-based approach)
  • [ ] Document the visual regression testing process in CONTRIBUTING.md

Complete missing test files for visx-axis package and add type coverage

The visx-axis package exists at packages/visx-axis/src/axis/Axis.tsx but the file structure shows no test/ directory listed, unlike visx-annotation. This is a fundamental package for chart axes that likely has complex prop combinations and edge cases. Adding a comprehensive test suite would be high-value, especially since axis components interact with scales and margins in non-obvious ways.

  • [ ] Create packages/visx-axis/test/ directory if it doesn't exist
  • [ ] Create packages/visx-axis/test/Axis.test.tsx with tests for horizontal/vertical axes
  • [ ] Add tests for scale type handling (linear, time, band, etc.) following visx-annotation test patterns
  • [ ] Add tests for label rendering, tick formatting, and margin calculations
  • [ ] Create packages/visx-axis/vitest.config.ts following the pattern from visx-annotation
  • [ ] Ensure tests are included in the main test suite (check package.json test script)

Good first issues

  • Add TypeScript tests for packages/visx-annotation/src/components/CircleSubject.tsx and LineSubject.tsx (no visible tests for these subject types). Pattern: examine packages/visx-shape/src/tests for test structure.
  • Add JSDoc examples to packages/visx-scale/src/scales/*.ts scale factories (scaleLinear, scaleBand, etc.)β€”would improve auto-generated docs. Copy pattern from existing examples in Readme.md usage section.
  • Create a simple example in packages/visx-demo/src showing EditableAnnotation from @visx/annotationβ€”Readme mentions Annotation but no demo of editable variant visible in file list.

Top contributors

Recent commits

  • 98f5312 β€” v4.0.0-alpha.11 (invalid-email-address)
  • 6bae78d β€” docs(migration): note broken alpha.10 and upcoming alpha.11 re-publish (#2000) (hshoff)
  • fd4726b β€” v4.0.0-alpha.10 (invalid-email-address)
  • 26697c8 β€” docs(readme): modernize README for v4 alpha (#1999) (hshoff)
  • 449b5e9 β€” v4.0.0-alpha.9 (invalid-email-address)
  • 9240416 β€” fix(release): force-publish all packages during alpha releases (#1998) (hshoff)
  • e38d404 β€” v4.0.0-alpha.8 (invalid-email-address)
  • cba3343 β€” build(f6309d634bf9d5401f54f1c87fc4d6cb73e63b6a): auto-commit package sizes (invalid-email-address)
  • f6309d6 β€” feat(responsive): support custom ref in useParentSize (#1997) (hshoff)
  • da50a0f β€” v4.0.0-alpha.7 (invalid-email-address)

Security observations

The visx visualization library demonstrates a generally secure codebase structure with no critical vulnerabilities detected from static analysis. The primary concerns are medium-severity items related to XSS risks in the HtmlLabel component (which requires code review), lack of a security policy document, and restrictive Node.js engine constraints. The project uses modern tooling (TypeScript, linting, testing) which aids security. Recommendations include: (1) audit HtmlLabel.tsx for proper HTML sanitization, (2) establish a SECURITY.md file for responsible disclosure, (3) relax Node.js version constraints to support more LTS releases, (4) implement dependency audit tooling in CI/CD, and (5) review release scripts for credential handling. No hardcoded secrets, SQL injection risks, or Docker misconfigurations were identified in the visible file structure.

  • Medium Β· Missing Security Policy β€” Repository root. No SECURITY.md file found in the repository root. This makes it difficult for security researchers to report vulnerabilities responsibly. Fix: Create a SECURITY.md file documenting the security policy and responsible disclosure process, following the GitHub security policy format.
  • Medium Β· Potential XSS Risk in Annotation Components β€” packages/visx-annotation/src/components/HtmlLabel.tsx. The HtmlLabel component in visx-annotation may render HTML content. Without proper sanitization verification, this could be vulnerable to XSS attacks if user-controlled data is passed to the component. Fix: Audit HtmlLabel.tsx to ensure all HTML rendering uses safe sanitization methods (e.g., DOMPurify). Avoid dangerouslySetInnerHTML without strict input validation. Document security considerations in component props.
  • Low Β· Node Engine Constraint May Exclude Security Updates β€” package.json - engines field. The package.json specifies 'node': '>=22.0.0', which is very restrictive. This may prevent users from benefiting from security patches in Node.js LTS versions (like v20.x) if vulnerabilities are found. Fix: Consider supporting Node.js LTS versions (e.g., '>=18.0.0' or '>=20.0.0') to allow wider adoption and ensure users can apply security patches across stable releases.
  • Low Β· Build Script Token Injection Risk β€” package.json - build:release script. The 'build:release' script uses TypeScript to execute './scripts/performRelease/index.ts' without visible input validation. If this script handles credentials or API tokens, there's potential for injection. Fix: Review scripts/performRelease/index.ts to ensure all external inputs are validated and sanitized. Use environment variables for secrets, never pass tokens as script arguments. Ensure the script uses secure API authentication methods.
  • Low Β· Missing Dependency Audit Configuration β€” package.json - scripts section. No visible npm audit configuration, yarn audit policy, or SBOM generation in package.json scripts. This makes it harder to track and manage known vulnerabilities in dependencies. Fix: Add audit scripts and consider using tools like 'yarn audit' or 'npm audit' in CI/CD pipelines. Configure yarn workspaces to use lockfile integrity checks. Generate and maintain a Software Bill of Materials (SBOM).
  • Low Β· Lerna Monorepo Dependency Management β€” lerna.json and packages/*/package.json. The repo uses Lerna for monorepo management. While individual packages have .npmrc files, there's potential risk if package versions across the monorepo are not properly coordinated or if internal package references use weak version constraints. Fix: Review lerna.json configuration for security best practices. Ensure internal package dependencies use exact versions or tight ranges (e.g., 1.0.0 or ~1.0.0, not *). Use 'yarn workspaces' integrity checks.

LLM-derived; treat as a starting point, not a security audit.

Where to read next


Generated by RepoPilot. Verdict based on maintenance signals β€” see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals Β· airbnb/visx β€” RepoPilot