Skip to content
Updated continuously

Changelog

Every release of @topokit/* packages, with new features, behavior changes, and bug fixes. We follow Semantic Versioning.

v0.9.0

Latest

New `combo-force` layout for graphs with combos (groups) — extends the existing force-directed simulation with a centroid spring that pulls combo siblings together and centroid-to-centroid repulsion that translates whole combos as rigid clusters. Combo rectangles are visibly tighter than under `force`, with no other rendering changes. Plus a rendering tweak so combo boundaries stay visible at every zoom level, not just when zoomed in.

Added
  • combo-force layout — physics-based variant of force tuned for combo-heavy graphs. Per-combo centroid spring (default comboStrength: 0.15) pulls members toward their combo centroid each iteration; inter-combo centroid-to-centroid Coulomb repulsion (default comboRepelStrength: 0.5) is applied uniformly to every member of each combo, so whole combos translate apart as rigid clusters instead of deforming. Opt in with layout: 'combo-force'; the existing force layout is byte-identical (the new behavior runs through subclass hooks, not edits to force-layout.ts). Selectable from /play's Layout dropdown and from the in-canvas Layout selector buttons. On a representative production topo (156 nodes / 16 combos), average per-combo bounding-box area shrinks ~58% vs. force
Changed
  • Combo (group) boundary rectangles now render at every zoom level. Previously they were gated behind the same level-of-detail threshold as node strokes and dropped at zoom < 0.3 — which is roughly where the SDK's auto-fit lands for large topos, so on first paint you saw a node soup until you scrolled in. Boundaries are now always painted; only the combo label text is suppressed at the lower zoom levels where it would be illegible
Fixed
  • The in-canvas Layout selector (the row of buttons rendered inside the graph view) now lists every registered layout, not just the seven shipped before. Previously the selector kept its own hardcoded layout list that drifted from the OPTIONS.layouts manifest used by /play's topbar dropdown — so newly-registered layouts like combo-force appeared in /play but were missing from the in-canvas buttons

v0.8.0

Viewport auto-fits when you change what's visible — toggle a legend category, hide orphans, pin focus on a node, and the camera reframes to the new extent (unless you've been zooming or panning by hand). Plus two overlay-collision fixes: the legend no longer overlaps the minimap (whether they're stacked at the same corner or on opposite vertical edges), and the "Made with TopoKit" badge no longer hides behind the toolbar buttons.

Added
  • autoFitOnChange: true (default) — viewport re-fits to the visible graph extent on structural changes: legend node/edge category toggles, hideOrphans flips, focus:pin / focus:release, edge-type filters. The re-fit is suppressed while you've manually moved the camera (wheel zoom, drag pan, pinch) since the last fit, so navigation isn't fought. Pass autoFitOnChange: false to opt out. Surfaced in /play's Data-features strip
  • computeLegendBodyMaxHeight() helper — exported pure function that computes the max-height a legend body should use to avoid a same-side minimap, given container height + minimap height + header height. Used internally by Legend.applyMinimapClearance() (called on attach, after every renderItems, and on container resize)
Fixed
  • Legend and minimap **at the same corner** (e.g. both bottom-left) no longer stack on top of each other. The legend's top or bottom offset is shifted by 16 + minimapHeight + 16 so it sits cleanly above (or below) the minimap. Body max-height is capped to the remaining vertical space so the offset-pushed legend still fits within the container. Common cause: a topo that explicitly pins legend.position: "bottom-left" while minimap: true defaults the minimap to the same corner
  • Legend and minimap on the **same vertical edge but opposite horizontal edges** (e.g. legend top-left + minimap bottom-left, the SDK defaults) no longer overlap on short containers. The legend body caps its own max-height with a 16px safety gap above the minimap, floored at 80px (legend scrolls rather than minimap getting clipped). A self-correction measurement pass after the analytical cap shrinks further if the rendered rect still encroaches — handles dynamic legend content, padding/border quirks, and the case where the CSS default lets the body grow into the minimap
  • "Made with TopoKit" badge on /play and /t/<hash> no longer hides behind the SDK toolbar buttons. The badge's z-index was below the toolbar's 40, and both were anchored to the same bottom-right corner. The badge now lifts above the toolbar and slides 68px left when a bottom-right toolbar is mounted; otherwise it stays in its corner

v0.7.0

Levers for bVDA-shape graphs (lots of edge types, a few tethered leaves, manually pre-collapsed clusters): an edge-type filter section in the legend, an opt-in `hideOrphans` toggle, and a `force` variant of auto-collapse that ignores user pre-collapses. Plus a rebuilt `/play` with a separate Data-features strip and a JSON drawer, automatic license-on-domain for `topokit.io`-hosted renders, and overlay-collision fixes for stacked SDK UI.

Added
  • Edge-type filtering in the legend — pass legend: { groupEdgesBy: "type" } (or any data field path) to render a second legend section grouped by edge category. Click to hide/show edges of that type; cross-category edges hide if either endpoint is hidden. Nodes left with zero visible edges by the filter dim to fadedNodeOpacity (default 0.25) so the spatial structure stays. New legend.toggleEdgeCategory() method and focus:edge-filter event. Auto-detect probes data.type → category → role → kind → class and suppresses hex-only edge legends with a one-time console.warn
  • hideOrphans: true — hides nodes with zero incident edges in the currently-rendered graph (dynamic — recomputes after combo collapse, legend toggles, and edge filters). Combo containers are never treated as orphans. Off by default — the SDK still doesn't decide visibility for you
  • autoCollapseCombosForce: true — overrides the user-intent guard so auto-collapse fires even when the topo arrives with manual pre-collapses already in place. The default behavior (preserve user intent) is unchanged
  • /play Data-features strip — boolean and segment controls for data-aware features (edge bundling, expand combos, minimap mode, click-to-pin, auto-collapse threshold, hideOrphans, autoCollapseCombosForce) generated from the SDK options manifest. Adding a control to /play is now one manifest entry — no /play code changes needed for new boolean or numeric options
  • /play JSON drawer — the editor collapses to a 44px tab at the bottom so the render takes the full viewport. Toggle to expand. Bidirectional binding: edit the JSON and the controls reflect; click a control and the JSON updates with the leaf scrubbed back to default when toggled off
Changed
  • /play layout rebuilt — topbar (theme, layout, share) → Rendering-features strip (legend, minimap, toolbar, search, info-panel, layout-selector, theme-selector) → Data-features strip → render canvas (full height) → JSON drawer. The Rendering and Data strips stay visible while you work
  • Legend default position is now top-left (was top-right) so it stops fighting the bottom-right toolbar and the minimap. Set legend: { position: "top-right" } to restore
  • The UNLICENSED watermark on the canvas now lifts above the bottom-right toolbar when one is attached (measured at render time) instead of being obscured by it
  • SDK IIFE bundle is now versioned — bundle URL carries a ?v=<semver>+<sha>[-dirty] cache-bust query (e.g. /demos/topokit.js?v=0.7.0+ad82245), and window.GraphKit.VERSION exposes the same string at runtime for in-browser debugging. sdk/VERSION is the single source of truth; pnpm build:iife bakes the value in via esbuild banner + auto-generates the URL manifest consumed by every Astro page that loads the SDK. All nine @graphkit/* packages bumped 0.1.0-alpha.0 → 0.7.0 to align with marketing reality
Fixed
  • /play and /t/<hash> now self-license against topokit.io so the canvas renders without the watermark on our own site. The SDK's domain-binding check is unchanged — only topokit.io, *.topokit.io, and localhost are covered; your own embeds still need a customer license
  • /play UI toggles now boot from each component's defaultEnabled so unchecking a toggle that defaulted on actually hides the component on first render (previously the UI showed an out-of-sync state on initial load)
  • Dark-theme styling for the theme-selector dropdown — the open dropdown was hard to read against dark backgrounds

v0.6.0

Readability for dense, hub-heavy, and compound graphs — a smart `auto` layout, auto-collapsing containers with synthesized cross-boundary edges, zoom-aware labels, click-to-toggle legend, pinned focus mode, an edge-bundling algorithm that picks itself based on graph size, and a minimap heatmap mode. Plus a smarter auto-legend that infers the right grouping field and a rewritten AI-agent doc page.

Added
  • layout: "auto" — picks the right algorithm from the graph's topology (edge density, hierarchy depth, hub concentration, compound containers). An exported analyzeGraph() helper from @topokit/layouts returns the same stats for tooling and AI introspection
  • Auto-collapsing compound containers — graphs that declare lots of parent containers but no manual collapse state now collapse non-essential containers on first render to surface the high-level shape. Cross-container edges are aggregated into synthesized connections with stable IDs (__combo_edge_*), counts, and sample edge types
  • Zoom-aware labels — per-label minZoom (node default 0.4, edge default 0.6) replaces the all-or-nothing LOD gate; labels reveal progressively as you zoom in
  • Pinned focus mode — hoverFocus: { clickToPin: true, hops: 1..3 } pins a node and its N-hop neighborhood on click and dims the rest. Press Esc to release. New app.pinFocus(nodeId, hops?) and app.releaseFocus() APIs plus focus:pin / focus:release events
  • Minimap heatmap mode — minimap.mode: "heatmap" | "dots" | "both" renders node density as a 5-stop color gradient instead of dots. both overlays the heatmap under the dots
Changed
  • Legend items are clickable by default — legend.clickToToggle: true toggles a category's visibility (and its incident edges) on click; click again to restore. Explicit legend.onItemClick handlers still win for back-compat
  • Edge bundling now auto-pivots between algorithms — edgeBundling: true picks FDEB for graphs with up to 150 edges and a fast merge algorithm (collapses parallel edges between cluster pairs) above that. Set algorithm: "fdeb" | "merge" explicitly to override. Synthesized cross-container edges are excluded from bundling (they already aggregate)
  • Auto-legend smarter — when legend: true is passed without groupBy, TopoKit now probes data.type, data.category, data.role, data.group, data.kind, and data.class in order and picks the first field with 2–20 distinct values. Hex-only legends are suppressed and emit a one-time console.warn pointing to groupBy
  • /docs/ai-instructions rewritten — drops the misleading "set legend: true for category nodes" guidance, adds a "common mistakes" callout for hex-label legends, and links to per-component option pages so agents can fetch detailed schemas
Fixed
  • /play?from=<hash> redirects now preserve the query string — the short-URL form again correctly opens the editor pre-loaded with the stored topo

v0.5.0

TopoKit Play — hosted JSON playground with shareable short URLs, rich Open Graph previews, chrome-less iframe embeds, and bring-your-own-license rendering on customer domains. Plus three new doc pages, an SDK options manifest for tooling and AI introspection, and an in-place theme/layout fast path that ends the remount flicker.

Added
  • TopoKit Play — hosted JSON playground at topokit.io/play. Paste TopoKit JSON, see it render live, click *Generate share link* and get a short topokit.io/t/<hash> URL anyone can open
  • Share previews — topokit.io/t/<hash>.png returns a 1200×630 Open Graph image of the rendered topo; share links unfurl with a real preview on Slack, X, Discord, LinkedIn, etc. (previews currently include the Unlicensed watermark for v1)
  • Embed mode — append ?embed to any /t/<hash> URL for a chrome-less render with no nav, no edit button, and no surrounding page chrome — drop it straight into an <iframe>
  • Bring-your-own-license iframe embeds — pass your license as ?license=tk_... or #license=tk_... on the iframe URL to render without the Unlicensed watermark on your own domain. The SDK validates against your page origin (via ancestorOrigins / document.referrer), so a leaked key only works on the domains it was minted for
  • SDK options manifest — public OPTIONS export from @topokit/core and window.GraphKit.options on the IIFE bundle, enumerating every supported config field with types, defaults, and enum values. Powers /play selectors, AI introspection, and third-party tooling
  • /docs/data-format — full reference for the TopoKit JSON config, generated from the options manifest
  • /docs/ai-instructions — one-prompt template for pointing any LLM at TopoKit Play; the agent fetches /docs/data-format and a sample, converts your raw data to TopoKit JSON, POSTs it, and hands back a share URL
  • /docs/embedding — iframe embed guide, bring-your-own-license flow, browser-compat caveats, and the domain-binding security model
Changed
  • Theme and layout changes are now applied in place via app.setTheme() / app.setLayout() — no more full remount flicker when switching themes or layouts in /play or in your own integrations
  • Attached SDK UI components (minimap, legend, toolbar, search, layout-selector, info-panel) now receive theme updates automatically when setTheme is called — no more mismatched component chrome
  • POST /api/topos is now content-addressable — saving the same canonical JSON twice returns the existing hash instead of writing a new row; editor whitespace and key-order changes don't defeat dedup

v0.4.0

Full-text search, redesigned minimap, and a 12% smaller renderer bundle. Stability fixes across React 18+ StrictMode and high-DPI displays.

Added
  • graph.search(query) — full-text search across node labels and data fields with fuzzy matching
  • Search-driven highlight: matched nodes are spotlighted while the rest dim
  • Minimap viewport drag — click-and-drag the viewport rectangle to pan the main canvas
  • New feature-explorer showcase covering 30+ APIs in a single interactive demo
Changed
  • @topokit/renderer-canvas is now < 80KB gzipped (was ~91KB) after dead-code elimination
  • Default dark theme tokens adjusted for AAA contrast on node labels
  • Minimap rebuilt to share the LOD cache with the main renderer (less GC churn)
Fixed
  • React 18+ StrictMode double-mount no longer leaks the canvas context
  • High-DPI rendering on Windows scaling > 125% (was rendering at logical pixels)
  • Edge labels could overlap on tightly curved edges in dense graphs

v0.3.1

Maintenance release. Touch interaction fixes and minor API additions to the badges component.

Added
  • NodeBadge.icon accepts built-in icon names (alert, check, info, lock, star)
  • graph.batch(fn) — coalesce multiple mutations into a single render
Fixed
  • Pinch-zoom on iOS Safari now respects minZoom / maxZoom
  • Two-finger pan no longer fires nodeClick on accidental tap
  • Legend auto-generation skipped categories with zero visible nodes

v0.3.0

Clustering, progressive expand, and the first-class `@topokit/react` package. Five new built-in themes.

Added
  • Clustering API — cluster.by(field) groups nodes, aggregates edges, and supports collapse/expand
  • Progressive expand — start with a seed node and expand neighbors on demand for huge graphs
  • @topokit/react package with <GraphCanvas> component and useGraph hook
  • Five new built-in themes: solarized, nord, dracula, tokyo-night, github
  • Animated layout transitions when switching between force, hierarchical, dagre, etc.
Changed
  • Layout algorithms moved to @topokit/layouts and are now tree-shakable
  • create() now accepts a partial config and fills in safe defaults
Fixed
  • Force layout settled with NaN positions when two nodes started at the same coordinates
  • Dagre layout failed for graphs with a single node

v0.2.1

Hotfix release for the canvas renderer and the legend component.

Fixed
  • Canvas renderer cleared the device-pixel transform when the container resized
  • Legend component swallowed pointer events on the underlying canvas

v0.2.0

Force-directed edge bundling, off-main-thread layout computation, and the new minimap, legend, and badges components.

Added
  • Force-Directed Edge Bundling (FDEB) — edges.bundling = "fdeb" for dense graphs
  • Web Worker support for force and dagre layouts (layout.worker = true)
  • Minimap component with viewport sync
  • Legend component (manual and auto-generated)
  • Badges component with multiple badges, custom slots, and dynamic updates
  • Filtering & highlighting APIs (graph.filter, graph.highlight)
Changed
  • Renderer split into @topokit/renderer-canvas (alpha SVG renderer removed)
  • Public type surface stabilized; no more any in exported signatures

v0.1.0

Public beta

First public beta. Seven layout algorithms, canvas LOD rendering, and the core data-mapping API.

Added
  • Seven layout algorithms: force, hierarchical, circular, dagre, radial, concentric, grid
  • Canvas renderer with level-of-detail (LOD) culling and spatial indexing
  • Data-mapping API with dot-path resolvers and function resolvers
  • Theme system with dark, light, and high-contrast presets
  • Stress-test showcase rendering up to 20,000 nodes
  • Telecom topology, org-chart, social-network, and dependency-tree showcases

Looking for upgrade notes? See Getting Started or the API Reference.