This proposal outlines the design and implementation of a disciplined, structure-first UI framework for CRUD applications with complex business processes. The goal is to eliminate UI clutter by enforcing a consistent three-pane layout that scales across all business use cases while maintaining simplicity and developer productivity.
Modern web applications suffer from:
- UI Clutter: Undisciplined placement of UI elements creates cognitive overload
- Inconsistent Patterns: Each feature introduces new layouts and interaction patterns
- Poor Scalability: Complex workflows become unwieldy without structure
- Developer Friction: Lack of conventions leads to reinvention and technical debt
A structured three-pane layout with disciplined separation of concerns:
┌─────────────────────────────────────────────────────────┐
│ Application Header / Title Bar │
├───────┬─────────────────────────────────────┬───────────┤
│ │ │ │
│ L │ Middle Pane │ R │
│ E │ │ I │
│ F │ ┌─────────────────────────────┐ │ G │
│ T │ │ Input Tab │ Output Tab │ │ H │
│ │ ├─────────────────────────────┤ │ T │
│ S │ │ │ │ │
│ I │ │ Form / CRUD Operations │ │ S │
│ D │ │ or │ │ I │
│ E │ │ Markdown Rendered View │ │ D │
│ B │ │ │ │ E │
│ A │ │ │ │ B │
│ R │ └─────────────────────────────┘ │ A │
│ │ │ R │
│ │ │ │
└───────┴─────────────────────────────────────┴───────────┘
-
Left Sidebar (Navigation)
- Menu links only
- Application navigation
- Context switching
- Workflow state indicators
-
Middle Pane (Primary Workspace)
- Input Tab: CRUD operations, form inputs, data entry
- Output Tab: Read-only markdown-rendered results
- Tab switching for input vs output modes
- Structured data flow from input → processing → output
-
Right Sidebar (Metadata & Notifications)
- Real-time notifications
- Activity logs
- Contextual metadata
- Status indicators
- Process/workflow state
Core Technologies:
- HTML5: Semantic structure
- CSS3: Modern styling with CSS Grid and Flexbox
- Vanilla JavaScript: No framework bloat
- Datastar.dev: Hypermedia-driven, 2-way SSE streaming
Why Datastar.dev?
- Lightweight (~9KB minified)
- Native SSE support for real-time updates
- Declarative attribute-based reactivity
- Server-driven UI updates
- No build step required
- Plays well with Go backends
Components:
- Chi Router: Lightweight, idiomatic Go HTTP router
- Restate Go SDK: Durable execution primitives
- github.com/pithomlabs/rea: Resilient application framework on top of Restate
Architecture Pattern:
HTTP Request (Datastar SSE)
↓
Chi Router (HTTP Handler)
↓
Rea Framework (Business Logic Layer)
↓
Restate SDK (Durable Execution)
↓
HTTP Response (SSE Stream)
Create a semantic three-pane layout:
- Header with app title and global actions
- Left sidebar with navigation menu
- Middle pane with tab system (Input/Output)
- Right sidebar with notification panel
- Responsive grid layout
- CSS custom properties for theming
- Responsive grid system
- Component-level styles
- Dark mode support
- Accessibility considerations
- Tab switching logic
- Datastar.dev initialization
- SSE connection management
- Form serialization utilities
- Markdown renderer (e.g., marked.js)
package main
import (
"github.com/go-chi/chi/v5"
"github.com/go-chi/chi/v5/middleware"
)
func main() {
r := chi.NewRouter()
r.Use(middleware.Logger)
r.Use(middleware.Recoverer)
// Static files
r.Get("/", serveIndex)
r.Get("/static/*", serveStatic)
// SSE endpoints
r.Get("/stream/notifications", streamNotifications)
r.Post("/api/crud/*", handleCRUD)
http.ListenAndServe(":8080", r)
}import (
restate "github.com/restatedev/sdk-go"
"github.com/pithomlabs/rea"
)
// Define Restate services
type CRUDService struct{}
func (s *CRUDService) Create(ctx restate.ObjectContext, entity Entity) (string, error) {
// Durable CRUD operation
id := restate.UUID(ctx).String()
restate.Set(ctx, id, entity)
return id, nil
}
func (s *CRUDService) Read(ctx restate.ObjectSharedContext, id string) (Entity, error) {
return restate.Get[Entity](ctx, id)
}func streamNotifications(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/event-stream")
w.Header().Set("Cache-Control", "no-cache")
w.Header().Set("Connection", "keep-alive")
flusher, _ := w.(http.Flusher)
for {
select {
case notification := <-notificationChan:
fmt.Fprintf(w, "data: %s\n\n", notification)
flusher.Flush()
case <-r.Context().Done():
return
}
}
}<div data-on-load="$get('/stream/notifications')">
<div data-text="$notification.message"></div>
</div>
<form data-on-submit="$post('/api/crud/create')">
<input name="name" data-model="name" />
<button type="submit">Create</button>
</form>func handleCreate(w http.ResponseWriter, r *http.Request) {
// Process CRUD operation
result := processCreate(r)
// Send SSE update
w.Header().Set("Content-Type", "text/event-stream")
fmt.Fprintf(w, "event: datastar-merge\n")
fmt.Fprintf(w, "data: {\"fragments\": [{\"selector\": \"#output\", \"html\": \"%s\"}]}\n\n", result)
}Create a flexible form system supporting:
- Text inputs, textareas, selects
- File uploads
- Validation rules
- Dynamic field addition
- Form state persistence
Markdown-based rendering supporting:
- Tables for list views
- Code blocks for technical data
- Headings for structure
- Links for navigation
- Custom rendering hooks
{
"entity": "Product",
"fields": [
{"name": "name", "type": "text", "required": true},
{"name": "price", "type": "number", "min": 0},
{"name": "description", "type": "textarea"}
],
"actions": ["create", "update", "delete"]
}Backend renders forms and output based on schema.
Use Restate workflows for complex processes:
type OrderWorkflow struct{}
func (w *OrderWorkflow) Run(ctx restate.WorkflowContext, order Order) (string, error) {
// Step 1: Validate
err := restate.Run(ctx, func(ctx restate.RunContext) (any, error) {
return nil, validateOrder(order)
})
// Step 2: Process payment
promise := restate.Promise[PaymentResult](ctx, "payment")
paymentResult, err := promise.Result()
// Step 3: Fulfill
// ... more steps
return "completed", nil
}- Left sidebar shows current step
- Right sidebar shows step history
- Middle pane shows current step form
- Output tab shows workflow progress
- Reduced Decision Fatigue: One layout for all features
- Faster Development: Reusable patterns and components
- Type Safety: Go backend with strong typing
- Resilience: Restate provides durable execution
- Real-time Updates: SSE streaming without polling
- Consistency: Same layout everywhere
- Predictability: Always know where to find things
- Clear Workflow: Input → Process → Output is explicit
- Live Updates: No manual refresh needed
- Maintainability: Conventions reduce bugs
- Scalability: Structure handles complexity
- Extensibility: Add features without layout changes
- Training: Easier onboarding with consistent patterns
- SSE-First: Built for server-driven real-time updates
- Lightweight: Minimal JavaScript footprint
- Hypermedia: Server controls UI state
- Progressive Enhancement: Works without JS (graceful degradation)
- Go-Friendly: Natural fit with Chi router patterns
- Idiomatic Go: Leverages standard library patterns
- Middleware Composition: Clean request pipeline
- Lightweight: No magic, no overhead
- Testable: Easy to unit test handlers
- Durable Execution: Automatic retry and recovery
- State Management: Built-in persistence
- Workflow Primitives: Complex processes made simple
- Type Safety: Go's strong typing throughout
- Observability: Built-in tracing and logging
zeroapp/prototype/
├── PROPOSAL.md (this file)
├── README.md (setup and usage instructions)
├── frontend/
│ ├── index.html (main layout)
│ ├── css/
│ │ ├── reset.css (CSS reset)
│ │ ├── variables.css (design tokens)
│ │ ├── layout.css (grid system)
│ │ ├── components.css (reusable components)
│ │ └── themes.css (light/dark modes)
│ ├── js/
│ │ ├── main.js (initialization)
│ │ ├── tabs.js (tab switching)
│ │ ├── forms.js (form handling)
│ │ └── markdown.js (output rendering)
│ └── vendor/
│ ├── datastar.min.js (datastar.dev library)
│ └── marked.min.js (markdown parser)
├── backend/
│ ├── main.go (server entry point)
│ ├── go.mod
│ ├── handlers/
│ │ ├── static.go (serve frontend)
│ │ ├── sse.go (SSE streaming)
│ │ └── crud.go (CRUD operations)
│ ├── services/
│ │ ├── crud_service.go (Restate CRUD service)
│ │ └── workflow_service.go (Restate workflows)
│ └── models/
│ ├── entity.go (data models)
│ └── schema.go (form schema)
└── examples/
├── simple-crud/ (basic CRUD example)
├── multi-step-workflow/ (complex workflow)
└── real-time-dashboard/ (live updates)
- CRUD Operations: Create, read, update, delete entities
- SSE Streaming: Verify real-time updates in right sidebar
- Tab Switching: Smooth transition between input and output
- Markdown Rendering: Proper display of formatted output
- Workflow Execution: Multi-step process completion
- Performance: <100ms response time for CRUD ops
- Concurrency: Handle 100+ simultaneous SSE connections
- Accessibility: WCAG 2.1 AA compliance
- Responsiveness: Mobile-friendly layout
- Browser Support: Chrome, Firefox, Safari, Edge (latest 2 versions)
- Left sidebar navigation works
- Input tab form submission succeeds
- Output tab displays markdown correctly
- Right sidebar shows live notifications
- SSE connection recovers from network interruption
- Dark mode toggle works
- Mobile layout is usable
- Keyboard navigation is functional
| Risk | Impact | Mitigation |
|---|---|---|
| SSE connection stability | High | Implement automatic reconnection logic |
| Browser compatibility | Medium | Polyfills for older browsers, progressive enhancement |
| Datastar.dev ecosystem maturity | Medium | Keep vanilla JS fallback, monitor library updates |
| Restate learning curve | Medium | Comprehensive examples, clear documentation |
| Schema rigidity | Low | Make schema optional, allow custom layouts |
- Schema Definition: Should we use JSON, YAML, or Go structs for defining form schemas?
- Authentication: Should we include auth in the prototype or keep it minimal?
- Multi-Tenancy: Does the prototype need tenant isolation?
- File Uploads: How should we handle file storage with Restate?
- Validation: Client-side, server-side, or both?
- Error Handling: How should errors display in the UI?
- Command Palette: Keyboard-driven navigation (Cmd+K)
- Breadcrumbs: Show navigation path in header
- Quick Actions: Context menu for common tasks
- Search: Global search across all entities
- Undo/Redo: Leverage Restate's durable state for history
- Approval Chains: Multi-step approval workflows
- Parallel Tasks: Fan-out/fan-in patterns
- Scheduled Actions: Delayed execution with Restate sleep
- Event-Driven: React to external events via awakeables
- Code Generation: CLI to generate CRUD boilerplate
- Hot Reload: Auto-refresh on file changes (development mode)
- API Documentation: Auto-generated from schema
- Testing Utilities: Helpers for testing SSE endpoints
- Keyboard Shortcuts: Power user efficiency
- Customizable Layout: Adjustable sidebar widths
- Saved Views: User-specific layouts and filters
- Export: Download output as PDF, CSV, JSON
| Phase | Duration | Deliverable |
|---|---|---|
| Phase 1: Frontend Foundation | 2-3 hours | Static HTML/CSS/JS prototype |
| Phase 2: Backend Foundation | 3-4 hours | Chi server with basic endpoints |
| Phase 3: Datastar Integration | 2-3 hours | Live SSE streaming |
| Phase 4: Generic CRUD | 3-4 hours | Schema-driven forms and output |
| Phase 5: Workflow Support | 4-5 hours | Complex process orchestration |
| Total | 14-19 hours | Fully functional prototype |
The prototype is considered successful if:
- ✅ All CRUD operations work end-to-end
- ✅ SSE streaming provides real-time updates
- ✅ Layout is consistent and responsive
- ✅ Markdown rendering displays correctly
- ✅ At least one complex workflow is demonstrated
- ✅ Code is documented and understandable
- ✅ Performance meets benchmarks (<100ms CRUD ops)
This proposal outlines a disciplined, structured approach to building CRUD applications with complex workflows. By enforcing a consistent three-pane layout and leveraging modern technologies (Datastar.dev, Chi, Restate, Rea), we can eliminate UI clutter while maintaining developer productivity and application resilience.
The prototype will serve as a foundational pattern for future business applications, providing:
- Clear conventions that reduce decision fatigue
- Proven patterns that scale with complexity
- Resilient architecture that handles failures gracefully
- Real-time capabilities without polling overhead
Next steps: Review this proposal, address open questions, and proceed with Phase 1 implementation.
Author: Claude (Gemini Agent)
Date: 2025-12-02
Version: 1.0