Connections (Produces & Consumes)

The produces/consumes system lets tools share computed data without tight coupling, forming a reactive data graph across your entire application.

Connections — Produces & Consumes

Tools rarely exist in isolation. A cost estimator produces a monthly burn figure that a runway calculator needs. A scoring tool produces aggregated ratings that a summary dashboard needs. The produces/consumes system wires these tools together reactively and offline-safely.

How it works

┌───────────────────────────┐   outputs:costs Y.Map   ┌──────────────────────────┐
│  cost-estimator schema    │  ─────────────────────► │  runway schema           │
│                           │                         │                          │
│  produces:                │                         │  consumes:               │
│    monthly: derived.total │                         │    upstreamCost:         │
│                           │                         │      'cost-estimator.monthly'│
└───────────────────────────┘                         └──────────────────────────┘
  1. The upstream tool's useProtoOutputs writes { monthly: 12400 } into Y.Map 'outputs:cost-estimator'
  2. The downstream tool's useProtoOutputs reads from that map and exposes it as connections.upstreamCost
  3. Downstream derived functions receive ctx.connections.upstreamCost = 12400
  4. When both tools share a Y.Doc, this happens instantly and works fully offline

Declaring produces

// cost-estimator schema
produces: {
  monthly: 'derived.monthlyTotal',     // key → dot-path in compute context
  annual:  'derived.annualTotal',
}

Supported path prefixes:

  • 'derived.keyName' — a computed derived value
  • 'fields.keyName' — a raw field value
  • 'collections.keyName' — an entire collection items array

Declaring consumes

// runway schema
consumes: {
  upstreamCost:   'cost-estimator.monthly',  // localAlias: 'sourceKey.producedKey'
  upstreamAnnual: 'cost-estimator.annual',
}

Format: 'sourceTool.sourceKey' where:

  • sourceTool — the key of the schema that declared produces
  • sourceKey — the key inside that schema's produces map

Consumed values appear in ctx.connections under the local alias.

Using connections in derived

// runway schema
derived: {
  effectiveMonthlyCost: {
    compute: ({ fields, connections }) =>
      // Use upstream value when available, fall back to local field
      connections.upstreamCost ?? fields.localMonthlyCost,
  },
  runwayMonths: {
    compute: ({ fields, derived }) =>
      derived.effectiveMonthlyCost > 0
        ? Math.floor(fields.availableFunds / derived.effectiveMonthlyCost)
        : Infinity,
    format: { type: 'number', decimals: 0, suffix: ' months' },
  },
}

Always guard against undefined connections — the upstream tool may not have run yet or may have no data.

Same-doc vs cross-doc

When all connected tools share a single Y.Doc, the produces/consumes flow is instant and fully offline-capable. useProtoOutputs reads and writes Y.Map entries in the shared document.

Y.Doc "my-workspace-xyz"
├── Y.Map "fields:cost-estimator"     ← cost-estimator fields
├── Y.Map "outputs:cost-estimator"    ← cost-estimator produces
├── Y.Map "fields:runway"             ← runway fields
└── Y.Map "outputs:runway"            ← runway produces

To share a Y.Doc across tools, pass the same doc object to each usePrototype call or use a common Pinia store that manages the shared Y.Doc.

Cross-doc (legacy watcher)

When tools have separate documents, useProtoConnections observes the source document and copies values reactively. This requires both documents to be open simultaneously. For offline use, prefer the same-doc pattern.

Example connection graph

A project management toolkit might have:

time-tracker  ──produces──► cost-estimator    (hourly totals)
cost-estimator ──produces──► runway            (monthly burn)
cost-estimator ──produces──► profitability     (monthly burn)
revenue-model  ──produces──► profitability     (monthly revenue)
profitability  ──produces──► investor-summary  (margin, breakeven)

Each tool is independently useful. The connections make them greater than the sum of their parts — and the whole graph works offline.

Building a connection map

If you have many tools, use buildConnectionMap to auto-generate the graph from schema declarations:

import { buildConnectionMap } from '~/utils/connectionMap'
import { allSchemas } from '~/schemas'

const map = buildConnectionMap(allSchemas)

const upstream   = getUpstreamTools('runway', map)    // ['cost-estimator']
const downstream = getDownstreamTools('cost-estimator', map) // ['runway', 'profitability']

Need a Landing Page?

Modern landing pages with optional modules (blog, docs, forms, i18n). Let's discuss your project.

Build Your MVP

Full-stack SaaS development. Expert in database design, multi-tenancy, and scalable architecture.

Deployment Help

Dockerize your backend, set up CI/CD pipelines, deploy to Cloudflare or Hetzner. Early-stage setup.

Suggest a SaaS Tool

Missing a calculator or tool? Suggest what you'd like to see on our site.