← Cycles
Qmap · c5

boundary-morphing

archivedcreated 2026-03-23· last activity 2026-08-15

New in this cycle: Runtime tag-based regrouping with animated boundary morphs

Goal

Explore dynamic boundary grouping based on actor tags, with animated transitions when groupings change.


Focus

  • Tag-based data model for actors (Apps, Vendors, Datasets)
  • Dynamic re-grouping at runtime
  • Animated morphing between grouping configurations
  • Visual "rug" boundaries beneath each group

Approach

  1. Each actor type has props and tags (key-value pairs)
  2. UI dropdowns let user select which tag to group by per actor type
  3. When grouping changes:
    • Compute new layout positions
    • Animate actors to new positions
    • Fade out old rugs, fade in new rugs
    • Update flow connections

Data Model

Apps

{
  id: "app-api-gateway",
  type: "app",
  name: "API Gateway",
  tags: {
    criticality: "production",
    language: "node",
    datacenter: "AWS East",
    pod: "gateway-7f8d9c",
    team: "platform",
  }
}

Vendors

{
  id: "vendor-stripe",
  type: "vendor",
  name: "Stripe",
  url: "stripe.com",
  tags: {
    securityPolicy: "critical-data",
    continent: "N. America",
  }
}

Datasets

{
  id: "db-users",
  type: "dataset",
  name: "Users DB",
  tags: {
    kind: "Postgres",
    pii: true,
    sensitiveData: true,
    criticality: "production",
  }
}

Connections

{ id: "conn-1", origin: "app-api-gateway", destination: "vendor-stripe", timestamp: 1706900000000 }

Key Files

FilePurpose
shared/testData.jsTagged actor data (8 Apps, 6 Vendors, 6 Datasets, 16 Connections)
shared/layoutEngine.jsComputes positions for grouped actors and rug bounds
shared/morphAnimation.jsAnimation system for smooth transitions
boundaries/GroupRug.jsRug boundary visualization with labels
components/GroupingControls.vueUI dropdowns for selecting groupings
entities/Reused from c3 (AppMesh, VendorMesh, DatabaseMesh)
flows/Reused from c3 (LineFlow for connections)

Test Data

Actor TypeCountGroupable Tags
Apps8criticality, language, datacenter, pod, team
Vendors6securityPolicy, continent
Datasets6kind, pii, sensitiveData, criticality

Connections: 16 (linking apps to vendors, apps to datasets, apps to apps)


Learnings

Animation System Architecture

  • Singleton AnimationController - Central controller manages all active animations via requestAnimationFrame loop; prevents multiple competing loops
  • Promise-based API - animateValue() returns Promise for clean async/await sequencing; enables "wait for X then do Y" patterns
  • Easing functions - easeInOutCubic for position morphing (smooth start/end), easeOutCubic for fades (quick start, gentle landing)

Morph Transition Coordination

  • Parallel where possible - Rug fades, actor visibility changes, and position animations run concurrently via Promise.all
  • Real-time flow updates - Flow connections update every frame during actor position animation, not just at start/end
  • Visibility-first filtering - Determine which actors have target positions; skip animating hidden elements entirely

Layout Engine Design

  • Two-pass algorithm: (1) compute each group's internal grid layout and bounds, (2) arrange groups in a row and apply global offsets
  • Grid positioning - Math.ceil(Math.sqrt(count)) columns gives roughly square grids
  • Type-specific Z offsets - Actors separated by type (datasets: -4, apps: 0, vendors: +4) for visual clarity without overlap

GroupRug Implementation

  • Actor-type coloring - Blue/purple/green by type creates instant visual association
  • Canvas label coloring - Label text uses same hex color as rug, maintaining cohesion
  • Depth buffer settings - depthWrite: false, polygonOffset: true, renderOrder hierarchy prevents z-fighting between overlapping transparent surfaces

Tag-Based Data Model

  • Flat actors + rich metadata - No nested hierarchies; grouping is derived from tag queries at runtime
  • "Unknown" fallback group - Actors missing the selected tag go to a catch-all group rather than disappearing
  • Runtime flexibility - Same data, different views—grouping by team, datacenter, or criticality without restructuring

What Worked Well

  • Reusing c3 entity meshes and c4's ContainerRug pattern saved significant time
  • Animation system is composable—can animate any value, not just specific properties
  • Layout engine is deterministic (same inputs → same outputs), which simplifies debugging

Open Questions Answered

  • Missing tags → "unknown" group (implemented)
  • "No grouping" option → not implemented, but trivial (group all by constant key)
  • Cross-boundary flows → flows animate correctly but don't yet visually emphasize boundary crossing

Relationship to Other Cycles

  • c1.border-grouping: Rug visualization patterns reused here
  • c2.entity-meshes: N/A (skipped to c3)
  • c3.data-flows: Entity meshes and flow rendering reused
  • c4.semantic-zoom: Morphing animation patterns informed by cube-to-rug transitions

Progress

  • Create cycle structure
  • Tag-based test data
  • Layout engine for grouped actors
  • GroupRug boundary visualization
  • Morph animation system
  • Grouping controls UI
  • Wire up ExperimentsApp.vue
  • Test and iterate
  • Document learnings

Open Questions

  1. How should actors with missing tags be grouped? (Currently: "unknown" group)
  2. Should there be a "no grouping" option showing all actors flat?
  3. How do flows look when they cross group boundaries?

Visual record

9 captures — heroes, page slices, and full-page renders. Click to view.

Default: apps by team, vendors by continent, datasets by kind
Default: apps by team, vendors by continent, datasets by kind
Apps regrouped by criticality — mid-morph identity
Apps regrouped by criticality — mid-morph identity
Apps by language
Apps by language
Apps by datacenter
Apps by datacenter
Apps by pod — the finest grain
Apps by pod — the finest grain
Vendors regrouped by security policy
Vendors regrouped by security policy
Datasets by sensitive-data flag
Datasets by sensitive-data flag
Curve height 8 over the regrouped field
Curve height 8 over the regrouped field
c5 legacy

Artifacts

/experiments/c5.boundary-morphing/ (local dev)

Qpoint Brand Style Guide