Welcome, Guest | Browse

Software Factory Archive

← Previous Work All Works Next Work →

Custom Renderers

Rating:
General Audiences
Fandom:
StrongDM Software Factory
Characters:
Navan Chauhan Jay Taylor Justin McCarthy
Tags:
CXDB Custom Renderers Sandbox Hot Swap CDN Visualization
Words:
475
Published:
2025-11-26

The generic renderer was fine. It handled any turn type by displaying the typed JSON as a formatted, collapsible tree. Fields were labeled, values were syntax-highlighted, nested objects could be expanded or collapsed. It worked for everything.

But "works for everything" is another way of saying "optimized for nothing," and Navan wanted more.

"A tool call isn't a JSON tree," he told Jay. "It's a function invocation. It has a name, inputs, and outputs. It should look like a function call, not like a dictionary."

"So build a custom renderer for tool calls."

"I already did. But here's the thing—I want anyone to be able to build renderers. I want them sandboxed so they can't access the rest of the DOM. I want them hot-swappable so you can update a renderer without redeploying the whole UI. And I want them loaded from a CDN so they don't increase the bundle size."

Jay whistled low. "That's a plugin system."

"It's a renderer plugin system." Navan pulled up his design. Each custom renderer was a JavaScript module conforming to a minimal interface: a function that received typed JSON and returned a DOM fragment. The module was loaded dynamically from a URL—typically a CDN endpoint—and executed inside an iframe sandbox with no access to the parent page's DOM, cookies, or JavaScript context.

"The iframe sandbox is the critical piece," Navan explained. "A renderer can draw anything it wants inside its own frame. Charts, tables, interactive visualizations. But it can't read the user's session token. It can't make network requests to arbitrary endpoints. It can't modify the turn data."

"And hot-swapping?"

"The UI checks the CDN for renderer module updates on a configurable interval. If a new version is available, it loads the new module and replaces the old one. No page reload. The turn re-renders with the new visualization automatically."

Navan demonstrated with the chart renderer he'd been building. It was designed for turns that contained metric payloads—time-series data from agent performance monitoring. The generic renderer showed these as arrays of numbers. Navan's chart renderer showed them as line graphs with labeled axes, hover tooltips, and a time range selector.

He loaded a conversation that tracked an agent's token usage over fifty turns. The generic renderer: a wall of numbers. Navan's chart renderer: a line curving upward, with a clear spike at turn thirty-seven where the agent had hit an error and pasted an entire stack trace into the context.

"I can see the problem," Jay said, staring at the spike. "Turn thirty-seven. That's where the agent's context window started getting heavy."

"You couldn't see that in the JSON view. You needed the chart." Navan switched back to the generic renderer. The same data, now an incomprehensible column of numbers. He switched back to the chart. The spike was obvious.

"How long did the chart renderer take to build?" Justin asked from the doorway.

"Ninety lines of JavaScript," Navan said. "Two hours, including the tooltip behavior."

"And it's already on the CDN?"

"It's been on the CDN since lunch."

Justin nodded and walked away. Ninety lines. Two hours. A visualization that made an invisible problem visible. That was the pitch for custom renderers, and Navan hadn't even had to make it.

Kudos: 71

iframe_enjoyer 2025-11-28

Sandboxed renderers loaded from CDN with hot-swapping is a genuinely elegant plugin architecture. The security model is right—renderers can draw but can't steal.

dataviz_dev 2025-11-29

The before/after with the chart renderer showing the token spike vs. the raw JSON wall is the perfect argument for custom visualization. Data is useless if you can't see the shape.

← Previous Work All Works Next Work →