Flow Results & Widgets

When a Flow run completes, lensless stores the execution state containing:

  1. input — the user’s initial input.
  2. results — output objects from each step, keyed by step ID.
  3. ui — optional UI configuration, including ui.results.widgets that control how results are displayed.

By configuring ui.results.widgets, you create a user-friendly results page that organizes outputs into images, JSON objects, or downloadable links.

Defining widgets

In your Flow’s top-level JSON, use the ui.results field:

{
  title: 'Example Flow',
  description: 'Demonstrates final results config',
  ui: {
    results: {
      widgets: [
        {
          type: 'Images',
          sources: ['imageGeneratorStep', 'secondImageGenerator'],
        },
        { type: 'Objects', sources: ['myObjectStep'] },
        { type: 'Download', sources: ['zipOutput'] },
      ],
    },
  },
  steps: [],
}

This tells the front-end to display:

  1. Images from imageGeneratorStep and secondImageGenerator.
  2. JSON objects from myObjectStep.
  3. A download link from zipOutput.

Widget types

Each entry in widgets is an object with a type and sources:

Images

When type: "Images", lensless collects images from each source step (typically ImageGenerator steps) and displays them as a gallery. Each image URL is signed for secure viewing.

Objects

When type: "Objects", the front-end fetches the JSON output from each listed step and displays it in a collapsible JSON viewer. Useful for showing structured data generated by ObjectGenerator or ObjectTransformer.

Download

When type: "Download", lensless renders download links using the .url field from each listed step. Typically used with Zipper steps, but works with any step that returns a URL.

How it all fits together

Here’s the full picture of how results flow from execution to display:

  1. Steps execute — each step writes its output to results.[stepId].
  2. Widgets reference stepsui.results.widgets maps step IDs to display types.
  3. Front-end renders — for each widget, it gathers data from the relevant steps and renders the appropriate view.

Progress and status

During execution, a Flow run can be RUNNING, PENDING, or eventually SUCCEEDED/FAILED. The UI shows a progress bar based on how many steps are complete.

During peak times, a Flow might stay in the Pending state (or 0% progress) for a while. If it’s stuck in Pending for more than 2 hours, lensless automatically cancels it.

Best practices

Always add a Zipper step with a Download widget if your Flow produces more than 10 images. Users want to download everything at once — saving images individually gets tedious fast. The same applies to Flows with lots of JSON results.

  • Plan your widgets — decide which steps produce “viewable” data and add those step IDs to ui.results.widgets.
  • Use multiple widgets — if you want to show different categories of images, create separate Images entries with different sources.
  • Combine results — add multiple step IDs to the sources array of the same widget to combine them. They should be of the same type.
  • Always include Download — if your Flow has a .zip or other file output, make sure it’s in a Download widget.
  • Fallback behavior — if you omit ui.results.widgets, the system shows a plain fallback with all raw result data.

Last updated on March 19, 2026