--- title: "AI Collaboration in Action: Implementing HTMX Widgets for Pipulate Workflows" permalink: /futureproof/htmx-workflow-widgets/ description: In this post, I'm walking through the process of planning and building a set of diverse UI widgets for Pipulate workflows, detailing how I used a comprehensive "super-prompt" with Gemini 2.5 to generate an implementation plan, and then worked with Claude 3.7 to code it using HTMX and FastHTML. We've successfully established the core framework for four widget types—basic HTMX, a Python Rich table, JavaScript execution, and Markdown rendering—getting the fundamental JavaScript injection via HTMX working. I also reflect on the resulting UX pattern that combines input and display in single steps and document this significant progress as a "banked win" before diving into the remaining JavaScript library activation nuances in the next stage. meta_description: Implementing HTMX widgets (Rich table, JS execution, Markdown) in Pipulate workflows using FastHTML, AI planning (Gemini/Claude), and super-prompts. Discusses architecture and UX. meta_keywords: Pipulate, HTMX, widget, FastHTML, JavaScript execution, Rich table widget, Markdown widget, workflow UI, super-prompt, AI collaboration, Gemini 2.5, Claude 3.7, Context Foo, widget_container, HX-Trigger, dynamic content injection, client-side rendering, UX design, separated steps pattern, Python Rich library, server.py, step-by-step workflow, AI-driven development, FastHTML to_xml layout: post sort_order: 1 --- {% raw %} ## Understanding Pipulate Widget Development with AI This article documents a developer's process of adding new user interface components, called "widgets," to a custom software project named Pipulate. Pipulate aims to simplify complex, step-by-step tasks (workflows), particularly in the field of Search Engine Optimization (SEO), presenting them as web applications. The developer is using modern web techniques like HTMX to create dynamic interfaces efficiently and Python for the backend logic. A unique aspect detailed here is the heavy reliance on collaboration with Artificial Intelligence (AI) models (Gemini and Claude). The author uses large, detailed prompts ("super-prompts") containing code and instructions to get AI assistance in planning the architecture and writing the code for these new widgets, which include things like data tables, text formatters, and interactive elements. The piece captures the real-time progress, challenges, and design decisions involved in this AI-assisted development approach. --- ## Required Widget Types for Pipulate I need a variety of widget types in Pipulate now. This opens the door to so many things! I need: - A d3js-style force-graph that loads in very small link-graphs for visualization. - A JSON-object explorer-style accordion surfer - Color-coded JavaScript with an easy copy-link that copies as plan text - A Markdown renderer (possibly related to the JavaScript one) - A little directory-tree to show where a file is located - Mermaid diagrams ## Understanding the Widget Architecture Okay, so the theme here appears to be non-interactive JavaScript widgets for pure visualization. This alleviates the 2-way communication protocol integration need of AnyWidgets while still allowing some nifty and impressive data-visualizations. In theory, this should allow me to incorporate anything that has a client-side JavaScript visualizer that doesn't demand opening communication protocols. ## JavaScript Library Loading Strategy The most efficient way to tackle this is to make a generic way of including just whatever JavaScript visualization library is needed, from either the CDN link or preferably from the local static resources directory — the way we're doing `htmx.js`, `mermaid.min.js` and other libraries from the workflows. Pipulate Workflows can have an area where you just provide a list of the paths to the files. I think I will have to think about whether things are loaded as modules or not. But the idea is straight forward enough. No particular JavaScript library need be global to the system templates, but any can be optionally loaded into a particular Workflow from either CDN or local. ## HTMX Integration Challenges Now the things that are going to be the targets for these JavaScript libraries are actually going to be HTML fragments inserted into the DOM by FastHTML's HTMX attributes, which will bring up certain scope, context and permission issues. Doing a positive proof of concept of a Pipulate Workflow JavaScript Widget that requires a JavaScript library provided at the initial page-load is probably the objective here. While I'm at it, I will toss a non-JavaScript fragment made by the Python Rich library as a sort of control — taking me a step closer to the back-end controlled Rich HTMX DataGrids that I want. ## Leveraging Context Foo for Development This looks like a job for Context Foo! First, let's define what goes into this AI prompt besides this article: ```python FILES_TO_INCLUDE = """\ README.md flake.nix server.py plugins/500_hello_workflow.py plugins/50_botify_export.py .cursorrules /home/mike/repos/MikeLev.in/_posts/2025-04-21-fasthtml-anywidget-host.md """.splitlines()[:-1] ``` ## Simplifying the Widget Approach And so I will make a special emphasis since I'm giving the whole widget story that I'm going for a vastly simplified version of this geared towards things like `chart.js` and other things that don't need the 2-way communication with Python. All Python needs to do is get the JavaScript library or module loaded into the browser through the initial page-load and to generate code that creates the HTMX container element, and (through FastHTML) provide a way to issue HTMX commands that will replace the container contents with JavaScript — which needs to execute despite it having just been dynamically injected into the DOM! ## Four Widget Types for Proof of Concept To bank a success, we will actually do 4 simultaneous widgets: 1. A Hello World widget that creates Hello World with traditional HTMX (no JavaScript execution required) 2. A Rich-generated HTML table - to test that we can 3. A Hello World widget that creates Hello World with JavaScript in an HTMX-injected HTML fragment 4. The using of a very basic client-side renderer, whatever is easiest. We can do Markdown or a JSON explorer. I want to minimize issues and maximize the odds of success. ## Implementation Strategy So the prompt after having read all that is to create a new template using what you learn from `500_hello_workflow.py` and `50_botify_export.py` to create `60_widget_examples.py` that has a step for each of the above types of widgets. You can look at the current implementation of `widget_container` and `tree_display` in `server.py` to see how this works in general. ```bash python prompt_foo.py --article-mode --article-path /home/mike/repos/MikeLev.in/_posts/2025-04-25-htmx-workflow-widgets.md ``` ## Gemini 2.5 Experimental Takes Super-Prompt > Hopefully, I can do more than just this this weekend, but this is the critical > blocker. I need to just be able to slam out different kind of widgets in > workflows. What is ***Context Foo*** you may ask. Well, I can't show you the entire prompt I pasted into Gemini because that would be 337K or 7.8K lines of text in a giant XML file wrapped with Anthropic's recommended schema for such things. But I can show you this bit that gives you an idea of what's in it. ## The Super-Prompt ```plaintext [mike@nixos:~/repos/pipulate/precursors]$ python prompt_foo.py --article-mode --article-path /home/mike/repos/MikeLev.in/_posts/2025-04-25-htmx-workflow-widgets.md === Prompt Structure === --- Pre-Prompt --- System Information: You are about to review a codebase in preparation for implementing changes requested in an article. Please study and understand the codebase thoroughly, as you will need this context to provide meaningful implementation suggestions based on the article's requirements. Key things to know about this codebase: - It uses a hybrid approach with Nix for system dependencies and virtualenv for Python packages - Always run `nix develop` before any commands in a new terminal - FastHTML objects must be converted with to_xml() before returning responses - The project is organized as a server with plugin-based workflows Key Points: • Focus on understanding how the codebase currently implements related functionality • Note any existing patterns that could be leveraged for the requested changes • Consider how the requested changes would integrate with the current architecture --- Files Included --- • README.md (6,571 tokens) • flake.nix (2,000 tokens) • server.py (25,265 tokens) • plugins/500_hello_workflow.py (6,617 tokens) • plugins/50_botify_export.py (25,123 tokens) • .cursorrules (688 tokens) • /home/mike/repos/MikeLev.in/_posts/2025-04-25-htmx-workflow-widgets.md (903 tokens) --- Post-Prompt --- Introduction: Now that you understand the codebase, please review the article's requirements and provide specific implementation suggestions. Focus on how to modify the codebase to meet these requirements while maintaining its architectural integrity and existing patterns. Implementation Areas: • Required Changes • Integration Strategy • Implementation Plan Focus Areas: • Practical implementation of the article's requirements • Maintenance of codebase integrity and patterns • Clear, actionable implementation steps --- Token Summary --- Total tokens: 67,659 tokens (≈$2.03 at GPT-4 rates) Maximum allowed: 2,087,152 tokens (≈$62.61 at GPT-4 rates) Remaining: 2,019,493 tokens (≈$60.58 at GPT-4 rates) === End Prompt Structure === --- Clipboard Instructions --- Complete XML content successfully copied to clipboard using pyperclip. You can now paste it. Script finished. ``` ## Gemini's Implementation Plan **Gemini 2.5 Experimental**: Okay, I have reviewed the codebase and the article's requirements for implementing various workflow widgets. Here’s a breakdown of the required changes, integration strategy, and implementation plan, keeping the project's architecture and conventions in mind. **1. Required Changes** * **New Workflow Plugin (`plugins/60_widget_examples.py`):** * Create this new file, using `plugins/500_hello_workflow.py` and `plugins/50_botify_export.py` as templates. * Define a class (e.g., `WidgetExamples`) with appropriate `APP_NAME` ("widgets"), `DISPLAY_NAME` ("Widget Examples"), `ENDPOINT_MESSAGE`, and `TRAINING_PROMPT`. * Define four steps in the `steps` list within `__init__`, one for each widget type requested in the article. * Implement `step_XX` (GET) and `step_XX_submit` (POST) handlers for each of the four steps. * **Step Implementations:** * **Step 1 (Simple HTMX):** * `step_01`: Display a simple input form within a `Card`. * `step_01_submit`: Validate input, update state, and return the standard `pip.revert_control` component along with an HTMX trigger (`Div`) for the next step (`step_02`). This step serves as a baseline and won't use the `widget_container`. * **Step 2 (Rich Table Widget):** * `step_02`: Display an input form (e.g., asking for data to put in the table). * `step_02_submit`: * Validate input. * Import necessary `rich` components (`Table`, `Console`). * Create a `rich.table.Table` instance with some data. * Use `rich.console.Console(record=True)` and `console.export_html(inline_styles=True)` to capture the table as an HTML string. * Wrap the captured HTML string in `fasthtml.common.HTML` to treat it as raw HTML. * Update the workflow state. * Use `pip.widget_container` passing the `HTML` object as the `widget` parameter. * Return the resulting container and the trigger `Div` for `step_03`. * **Step 3 (JavaScript Execution Widget):** * `step_03`: Display an input form. * `step_03_submit`: * Validate input. * Update workflow state. * Define the JavaScript to execute (e.g., `alert('Hello from HTMX-injected script!');` or something that modifies the widget's container). * Create the widget container `Div` using `pip.widget_container`. The `widget` parameter will be a `Div` containing a `