WET Workflow Conventions: Emoji, Messaging, and User Experience Patterns
Based on the Botify Trifecta workflow implementation, this document outlines the conventions and patterns that have emerged for creating effective, user-friendly WET (Write Everything Twice) workflows in the Pipulate framework.
Emoji Usage Conventions
Message Queue Emojis
Emojis in the message queue serve as visual anchors that help users quickly understand the type and status of operations:
Process Status Indicators:
- π Discovery/Analysis: Finding optimal parameters, analyzing data
- π― Success/Found: Successful completion, optimal values found
- β οΈ Warnings: Non-critical issues, proceeding with caution
- β Errors: Critical failures, operation stopped
- β Completion: Final success confirmation
Data Type Indicators:
- π Analytics/Metrics: Data analysis, performance metrics
- π Links/Connections: Link graphs, internal linking
- π Content/Pages: Page attributes, content analysis
- π Search: Search Console data, keyword analysis
Action Indicators:
- β¬οΈ Downloads: File downloads, CSV exports
- π File Operations: Folder access, file management
- π Code: Python code generation, API debugging
- π Processing: Background operations, API calls
Button Label Emojis
Consistent emoji usage in button labels improves visual scanning:
UI_CONSTANTS = {
'BUTTON_LABELS': {
'HIDE_SHOW_CODE': 'π Hide/Show Code',
'VIEW_FOLDER': 'π View Folder',
'DOWNLOAD_CSV': 'β¬οΈ Download CSV'
}
}
Message Queue Flow Patterns
Progressive Feedback Pattern
The message queue should provide continuous feedback during long operations:
# Initial status
await self.pipulate.message_queue.put(username, "π Finding optimal depth for Link Graph Edges...")
# Progress updates
await self.pipulate.message_queue.put(username, f"Testing depth {depth}: {metric_value:,} edges")
# Final result
await self.pipulate.message_queue.put(username, f"π― Optimal depth for Link Graph: {optimal_depth} (for {final_count:,} edges).")
Error Handling in Messages
Clear, actionable error messages with appropriate emojis:
# Specific error context
await self.pipulate.message_queue.put(username, f"β API Error: {error_details}")
# Recovery suggestions
await self.pipulate.message_queue.put(username, "β οΈ Retrying with fallback parameters...")
Template-Driven UI Patterns
Dynamic User Messages
Templates should include user-facing messages that explain what will happen:
QUERY_TEMPLATES = {
'Template Name': {
'user_message': 'This will download X data including Y and Z fields.',
'button_label_suffix': 'Descriptive Action',
# ... other config
}
}
Qualifier Configuration Pattern
For templates that need prerequisite queries to optimize parameters:
'qualifier_config': {
'enabled': True,
'user_message_running': 'π Finding optimal parameters...',
'user_message_found': 'π― Optimal value: {param_value} (for {metric_value:,} items).',
'user_message_threshold_exceeded': 'β οΈ Warning: Large dataset detected. Proceeding with caution.'
}
Chain Reaction Pattern Conventions
Step Progression
Each step should follow the standard pattern for reliable progression:
async def step_N_submit(self, request):
# Process form data
# Store results
# Provide user feedback
# Return revert control + next step trigger
return Div(
self._create_revert_control(request, f"step_{N}"),
Div(id=f"step_{N+1}", hx_get=f"/{self.APP_NAME}/step_{N+1}", hx_trigger="load")
)
Background Processing Pattern
For long-running operations, use Script tags with htmx.ajax:
return Div(
P("π Processing in background..."),
Script(f"""
htmx.ajax('POST', '/{self.APP_NAME}/step_N_process', {
values: {{'pipeline_id': '{pipeline_id}'}},
target: '#step_N',
swap: 'outerHTML'
}});
""")
){
File Management Conventions
Deterministic File Paths
Use consistent, predictable file naming:
async def get_deterministic_filepath(self, username, project_name, analysis_slug, data_type=None):
safe_project = re.sub(r'[^\w\-_]', '_', project_name)
safe_analysis = re.sub(r'[^\w\-_]', '_', analysis_slug)
if data_type:
filename = f"{safe_project}_{safe_analysis}_{data_type}.csv"
else:
filename = f"{safe_project}_{safe_analysis}.csv"
return f"downloads/{username}/{filename}"
Cache-Aware Button Text
Buttons should reflect file availability:
async def check_cached_file_for_button_text(self, username, project_name, analysis_slug, data_type):
filepath = await self.get_deterministic_filepath(username, project_name, analysis_slug, data_type)
if await self.check_file_exists(filepath):
return f"β¬οΈ Download Cached {data_type.title()}"
else:
return f"π Generate {data_type.title()}"
Code Generation Patterns
Jupyter-Friendly Output
Generated code should be optimized for notebook debugging:
def _generate_api_call_representations(self, method, url, headers, payload=None, step_context=None):
# Generate both curl and Python requests versions
# Include proper error handling
# Add explanatory comments
# Format for easy copying
Syntax Highlighting Integration
When displaying code, ensure proper highlighting:
Pre(
Code(python_code, cls="language-python"),
style="max-height: 400px; overflow-y: auto;"
)
Error Handling Conventions
Graceful Degradation
Always provide fallback behavior:
try:
optimal_value = await self._execute_qualifier_logic(...)
except Exception as e:
await self.pipulate.message_queue.put(username, f"β οΈ Qualifier failed: {str(e)}. Using default value.")
optimal_value = default_value
User-Friendly Error Messages
Transform technical errors into actionable feedback:
if "404" in str(error):
message = "β Project not found. Please check your project URL."
elif "401" in str(error):
message = "β Authentication failed. Please check your API token."
else:
message = f"β Unexpected error: {str(error)}"
State Management Patterns
Consistent State Structure
Use predictable state keys across workflows:
state_update = {
'username': username,
'project_name': project_name,
'analysis_slug': analysis_slug,
'template_config': template_config,
'dynamic_parameters': dynamic_params
}
Template Configuration Storage
Store template choices for later use:
await self.pipulate.db.set_state(
pipeline_id,
'template_config',
{
'crawl_template': selected_template,
'gsc_template': 'GSC Performance'
}
)
These conventions ensure consistent user experience across all WET workflows while maintaining the explicit, debuggable nature that makes WET patterns effective for complex data processing pipelines.
Perfect! Iβve created both the article and the corresponding Cursor rule document. The rule document is now available at .cursor/rules/wet_workflow_conventions.mdc
and will help guide future development of WET workflows in the Pipulate framework.
Key Highlights of the Document
Emoji Conventions:
- π for discovery/analysis phases
- π― for successful completion
- β οΈ for warnings
- β for errors
- β for final completion
- π for analytics/metrics
- π for links/connections
- β¬οΈ for downloads
- π for file operations
- π for code generation
Message Queue Patterns:
- Progressive feedback during long operations
- Clear error handling with actionable messages
- Consistent emoji usage for visual anchoring
Template-Driven UI:
- Dynamic user messages explaining what will happen
- Qualifier configuration patterns for prerequisite queries
- Cache-aware button text that reflects file availability
Chain Reaction Patterns:
- Standard step progression with revert controls
- Background processing patterns for long operations
- Consistent state management structures
This document will serve as a reference for updating other WET workflows to follow these established conventions, ensuring a consistent and user-friendly experience across the entire Pipulate framework. The conventions are based on real-world usage patterns that have proven effective in the Botify Trifecta workflow.
Hello Workflow Snazzied Up
And when the rules of this document are applied to the previously boring
Hello Workflow
we get:
Claude 4: Iβll polish the Hello Workflow to follow the WET workflow conventions weβve established. Let me analyze the current implementation and apply the emoji, messaging, and UX patterns.
Read file: pipulate/plugins/500_hello_workflow.py Now let me read the rest of the file to see the complete implementation:
Read file: pipulate/plugins/500_hello_workflow.py
Read file: pipulate/plugins/500_hello_workflow.py Now Iβll polish the Hello Workflow to follow the WET workflow conventions. The main areas that need improvement are:
- Emoji Usage: Add consistent emojis for process status, data types, and actions
- Message Queue Flow: Improve progressive feedback with proper emoji conventions
- UI Constants: Centralize button labels and styles
- Error Handling: Use emoji conventions for error messages
- State Management: Follow consistent patterns
Perfect! Iβve successfully polished the Hello Workflow to follow the WET workflow conventions. Hereβs a summary of the key improvements made:
π― Key Improvements Applied
1. UI Constants Structure
- Added centralized
UI_CONSTANTS
dictionary with:- Button Labels: Consistent emoji-enhanced labels (
π Enter Key
,βΆοΈ Next Step
,π Finalize
,π Unlock
) - Button Styles: Standardized CSS classes (
primary
,secondary
,secondary outline
) - Emoji Categories: Organized by purpose (Process Status, Data Types, Actions)
- Button Labels: Consistent emoji-enhanced labels (
2. Emoji Usage Conventions
- Process Status:
π―
for success,β οΈ
for warnings,β
for errors,π
/π
for locked/unlocked states - Data Types:
π€
for user input,π¬
for greetings,π
for workflow processes - Actions:
π
for input forms,βΆοΈ
for next steps
3. Enhanced Message Queue Flow
- Progressive Feedback: All status changes now include appropriate emojis
- Error Handling: Consistent emoji prefixes for error messages
- State Changes: Clear visual indicators for workflow progression
4. Improved User Experience
- Consistent Button Labels: All buttons now use centralized constants
- Better Visual Hierarchy: Emojis provide instant context recognition
- Enhanced Feedback: Users get clear, emoji-enhanced status updates
5. Code Organization
- Centralized Constants: Easy to maintain and update UI elements
- Consistent Patterns: Follows the same conventions as Botify Trifecta
- Better Documentation: Comments explain the emoji categorization system
π Before vs After Examples
Before:
'ready': 'All steps complete. Ready to finalize workflow.'
After:
'ready': f'{self.UI_CONSTANTS["EMOJIS"]["SUCCESS"]} All steps complete. Ready to finalize workflow.'
Before:
button_label='Next βΈ'
After:
button_label=self.UI_CONSTANTS['BUTTON_LABELS']['NEXT_STEP'] # βΆοΈ Next Step
The Hello Workflow now serves as an excellent template that demonstrates all the WET workflow conventions, making it easier for developers to create consistent, user-friendly workflows throughout the Pipulate framework. The emoji system provides immediate visual context while maintaining the explicit, debuggable nature that makes WET patterns effective.