Guidance for AI coding agents working in the Plotly.NET repo. This is a first draft — please update it as conventions evolve.
Plotly.NET is an interactive charting library for .NET, built on top of plotly.js. The core is written in F# and wraps the plotly.js JSON schema with multiple API layers (high-level type-safe Chart API down to low-level object manipulation). See README.md for user-facing docs and the F1000Research paper for design rationale.
Currently targeted plotly.js version: 2.27.1 (bundled at src/Plotly.NET/plotly-2.27.1.min.js).
All shipped packages live under src/:
- Plotly.NET — core F# library. Everything else depends on this.
- Plotly.NET.CSharp — idiomatic C# wrapper around the core API.
- Plotly.NET.Interactive — formatter extensions for .NET Interactive / Polyglot Notebooks.
- Plotly.NET.ImageExport — static image (PNG/SVG/JPEG/PDF) rendering.
- Plotly.NET.Verso — Verso integration.
Inside src/Plotly.NET/, the core is organized by concern:
- ChartAPI/ — high-level
ChartAPI (Chart2D,Chart3D,ChartMap,ChartPolar, etc.) andGenericChart. - Traces/ — trace types (
Trace2D,Trace3D,TraceGeo, …) matching plotly.js trace categories. - Layout/ — layout objects (axes, legends, annotations, shapes, …).
- CommonAbstractions/ — shared enums, style objects, and types used across traces/layouts.
- Config/, DisplayOptions/, Templates/ — render-time configuration.
- Globals.fs, Defaults.fs, InternalUtils.fs — globals and helpers.
The build is a FAKE script defined as an executable F# project at build/build.fsproj. It controls project ordering, version injection from RELEASE_NOTES.md, packing, and test execution. Do not use dotnet build directly — always go through the build project:
# Windows
./build.cmd # default target: Build
./build.cmd runTestsCore # run a specific target
# Linux / macOS
./build.sh
./build.sh runTestsAll
# Or invoke the build project directly
dotnet run --project ./build/build.fsproj
dotnet run --project ./build/build.fsproj -- RunTestsExtensionLibsKey build files:
- build/ProjectInfo.fs — registry of all projects (library + test). New projects must be added here, both in the
projectslist and in the relevant test-project lists. - build/Build.fs — main build targets,
sourceFilesglob. New projects may also need to be registered in the glob. - build/TestTasks.fs — test build and run targets (see below).
- build/PackageTasks.fs, build/ReleaseTasks.fs — pack and release pipeline.
- build/DocumentationTasks.fs — docs build targets.
Every shipped project needs its own RELEASE_NOTES.md — the build parses the top entry to derive the package version and assembly version.
See tests/README.md for the authoritative overview. Short version:
- F# test projects: Expecto (majority) or xUnit.
- C# test projects: xUnit.
- JS test projects: Mocha (run in node; primarily validate generated JSON against
Plotly.validate).
Layout (tests/)
- Common/ —
FSharpTestBaseandCSharpTestBaseclass libraries containing sharedTestUtils,TestCharts, and helpers (substringIsInChart,chartGeneratedContains,getFullPlotlyJS, …). Test projects reference these. - CoreTests/ — largest suite. Tests HTML generation, JSON serialization, object validity for the core
Plotly.NETlibrary. IncludesCoreTests.fsprojandCSharpInteroperabilityTests.csproj. - ExtensionLibsTests/ — tests for
Plotly.NET.CSharp,Plotly.NET.ImageExport, etc. - InteractiveTests/ — tests for
Plotly.NET.Interactive. - JSTests/ — node/Mocha tests validating generated JSON with plotly.js.
- VersoTests/ — tests for
Plotly.NET.Verso. - ConsoleApps/ — manual-test playgrounds, not unit tests.
./build.cmd runTestsAll # everything
./build.cmd runTestsCore # CoreTests
./build.cmd runTestsExtensionLibs # extension lib tests
./build.cmd runTestsJSTests # JS / Mocha tests- Use
FSharpTestBasehelpers:substringIsInChart,chartGeneratedContains,getFullPlotlyJS, etc. - Set
UseDefaults = falseon test charts to avoid dumping the large default template HTML into test output and making diffs unreadable. - When overriding
PlotlyJSReferencein tests, preferChart.withDisplayOptions(full replacement) overChart.withDisplayOptionsStyle(merge) — the merge form doesn't reliably override CDN defaults.
Docs live in docs/ as .fsx and .md files, organized by chart family (3D-charts/, categorical-charts/, distribution-charts/, …). They are rendered with FSharp.Formatting. To run a local dev server with hot reload:
./build.cmd watchdocs # or ./build.sh watchdocsWhen adding a new chart type or API surface, add or update the corresponding .fsx in the appropriate subfolder.
- Create the project under src/ or tests/.
- Add a
RELEASE_NOTES.mdat the project root (for shipped projects). - Register it in build/ProjectInfo.fs (projects list + any relevant test-project lists).
- Update the
sourceFilesglob in build/Build.fs if needed. - Add the project to the appropriate
.sln(Plotly.NET.sln, Plotly.NET.Core.sln, or Plotly.NET.TestSuite.sln). - Run
./build.cmd(orbuild.sh) and the relevant test target to verify.
- F# file order matters — new
.fsfiles must be added to the.fsprojin the correct position. - The core library is designed for C# interop — when adding public API, consider how it looks from C# (see the FAQ in README.md and issue #285).
- Release targets (
release,prerelease) expect aNUGET_KEYenvironment variable. Don't run these unless you actually intend to publish. - Main branch for PRs is
dev, notmain/master.
MIT — see LICENSE.