nyxcore-systems
5 min read

Building Better Workflow UIs: From Collapsed Cards to Full Markdown Rendering

How we transformed our workflow execution interface by ditching collapsed cards for full markdown rendering, added export features, and integrated expert team creation into our prompt templates.

ui-uxworkflow-automationmarkdownreactnextjs

Building Better Workflow UIs: From Collapsed Cards to Full Markdown Rendering

When building workflow automation tools, one of the biggest challenges is presenting complex, multi-step outputs in a way that's both readable and actionable. Recently, I spent a development session completely overhauling our workflow execution UI, and the results were transformative.

The Problem: Information Hiding

Our original interface used collapsed prompt section cards to display workflow step outputs. While this seemed like a good idea for managing screen real estate, it created a frustrating user experience:

  • Users had to constantly expand/collapse sections to read content
  • The truncated previews were often misleading
  • Context switching between sections broke the flow of understanding
  • No easy way to export or work with the generated content

The Solution: Embrace Full Rendering

Instead of fighting against the natural length of AI-generated content, we decided to embrace it. Here's what we implemented:

1. Full Markdown Rendering

We completely removed the parsePromptSections() function and PromptSectionCard components, replacing them with full inline MarkdownRenderer for all completed step outputs:

typescript
// Before: Collapsed cards with truncated content
<PromptSectionCard 
  title={section.title} 
  content={truncate(section.content, 200)} 
  isExpanded={false} 
/>

// After: Full markdown rendering
<MarkdownRenderer content={step.output} />

2. Action-Packed Toolbars

Each completed step now features a comprehensive action toolbar:

  • .md Download - Export content as markdown files
  • Copy - One-click clipboard copying
  • Edit - Inline editing capabilities
  • Retry - Re-run individual steps

The download functionality was particularly satisfying to implement:

typescript
const downloadMarkdown = (content: string, filename: string) => {
  const blob = new Blob([content], { type: 'text/markdown' });
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = `${sanitizeFilename(filename)}.md`;
  a.click();
  URL.revokeObjectURL(url);
};

3. Expert Team Integration

We enhanced our prompt templates with "Step 0: Assemble the Expert Team" sections. Now, every workflow automatically generates 3-5 domain experts matched to the project's tech stack:

markdown
## Step 0: Assemble the Expert Team

Based on the target repository's stack, assemble 3-5 domain experts:
- **Sarah Chen** (Full-Stack Developer) - React, Node.js, TypeScript
- **Marcus Rodriguez** (Database Architect) - PostgreSQL, Redis, data modeling
- **Alex Kim** (Frontend Specialist) - UI/UX, component libraries, accessibility

Lessons Learned: The Pain Points That Made Us Stronger

Every development session has its challenges. Here are the key lessons that emerged:

Authentication Environment Variables

The Issue: Spent time debugging JWT generation because I assumed the auth secret was stored in NEXTAUTH_SECRET. The Reality: This project uses AUTH_SECRET, not NEXTAUTH_SECRET. The Lesson: Always check the actual environment variable names in your project, don't assume standard conventions.

Workflow Execution Architecture

The Issue: Created workflows that stayed perpetually "running" with all steps "pending". The Discovery: The start mutation only sets database status - actual execution requires consuming the Server-Sent Events (SSE) endpoint. The Solution: After calling start, connect to /api/v1/events/workflows/[id] via fetch + ReadableStream to drive the AsyncGenerator execution.

typescript
// Don't just start the workflow
await workflowStart.mutateAsync({ id: workflowId });

// You need to consume the SSE endpoint too
const response = await fetch(`/api/v1/events/workflows/${workflowId}`);
const reader = response.body?.getReader();
// ... handle the stream to actually execute steps

Input Validation Gotchas

The Issue: Passing workflow input as a simple string caused Zod validation errors. The Reality: The schema expects z.record(z.string()) - an object, not a string. The Workaround: Wrap string inputs in an object: input: { text: "..." }

Development Environment Dependencies

The Issue: Tried running a Playwright screenshot script from /tmp/ and hit module resolution errors. The Lesson: Node.js module resolution is relative to where you run the script, not where it's located. Keep automation scripts in your project root or handle dependencies explicitly.

The Results: A More Usable Interface

After implementing these changes, we tested everything end-to-end with a new "Expert Team Test" workflow. The results were immediately apparent:

  1. Better Readability - Full markdown rendering made complex outputs much easier to scan and understand
  2. Improved Workflow - Users could export individual steps as markdown files for documentation or further processing
  3. Enhanced Context - Expert team assignments gave every prompt template more personality and domain-specific guidance
  4. Reduced Friction - No more clicking through collapsed sections to find the information you need

What's Next?

While this session accomplished its core goals, it also revealed some areas for future improvement:

  • Smart Navigation - For very long outputs (10k+ tokens), a table of contents or section navigation could help
  • Cost Estimation - Update the estimateWorkflowCost function to account for the generateCount multiplier
  • Input Flexibility - Consider making the template resolver handle string inputs directly instead of requiring object wrapping

Key Takeaways

  1. Don't hide information - If your users need to see content, show it to them fully rather than forcing interaction to reveal it
  2. Make content actionable - Export and copy functionality turns your UI from a display into a productivity tool
  3. Test the full flow - Database mutations might succeed while the actual execution pipeline fails silently
  4. Environment setup matters - Small details like auth variable names and module resolution can derail debugging sessions

The best UIs get out of your users' way. By moving from collapsed, hidden content to full, actionable displays, we transformed our workflow interface from a barrier into a bridge - connecting users directly with the AI-generated content they need to move their projects forward.