A professional desktop application for generating AI video prompts with an integrated history system and resizable layout.
- Professional Appearance - Clean, modern interface with proper visual hierarchy
- Functional Layout - Logical flow from configuration → input → generation → output
- Responsive Design - Graceful handling of window resizing without element disappearance
- Visual Clarity - Clear separation between functional areas with appropriate borders and spacing
┌─────────────────────────────────────────────────────────────┐
│ Wan 2.2 Prompt Crafter │
├─────────────────────────────────────────────────────────────┤
│ CONFIG FRAME (Fixed Height, Compact) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ LLM Service: [LM Studio ☑] [Ollama ☐] │ │
│ │ API Endpoint: [http://localhost:11434 ] │ │
│ │ Model: [llama3.2:latest ▼] [⟳ Refresh] │ │
│ │ Creativity: [Moderate Freedom ☑] [High Freedom ☐] │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ INPUT FRAME (Resizable) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Your Idea or Basic Prompt │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ [Scrollable text area for user input] │ │ │
│ │ │ [Minimum 4 lines, expands with frame] │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ [✨ Inspire Me] [Generate Wan 2.2 Prompt] [📚 History] │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ OUTPUT FRAME (Resizable, Largest) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Generated Prompt │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ [Scrollable text area for AI output] │ │ │
│ │ │ [Expands with frame, shows full prompts] │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ [Copy to Clipboard] │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ NEGATIVE PROMPT FRAME (Resizable) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Negative Prompt (for Wan 2.2) │ │
│ │ ┌─────────────────────────────────────────────────────┐ │ │
│ │ │ [Scrollable text area for negative prompt] │ │ │
│ │ │ [Minimum 3 lines, expands with frame] │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ │ [Unlock to Edit ☑] │ │
│ └─────────────────────────────────────────────────────────┘ │
├─────────────────────────────────────────────────────────────┤
│ HISTORY PANEL (Toggleable, Resizable) │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Prompt History (42) │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ 🔍 Search: [Search prompts and inputs...] │ │
│ │ 🎛️ Filters: │ │
│ │ Model: [All Models ▼] │ │
│ │ Creativity: [All ▼] │ │
│ │ Service: [All Services ▼] │ │
│ │ [🗑️ Clear Filters] │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ [Scrollable list of history items] │ │
│ │ ├─────────────────────────────────────────────────────┤ │ │
│ │ │ 12/15/2024 2:30 PM │ │ │
│ │ │ llama3.2:latest • High Freedom • Ollama │ │ │
│ │ │ Input: A serene lake at sunset... │ │ │
│ │ │ A cinematic wide shot of a tranquil lake... │ │ │
│ │ │ [Use Prompt] [Copy] [Delete] │ │ │
│ │ └─────────────────────────────────────────────────────┘ │ │
│ ├─────────────────────────────────────────────────────────┤ │
│ │ [📄 Export JSON] [📊 Export CSV] [🗑️ Clear All History] │ │
│ └─────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
- Height: Fixed at ~120px (3 rows of controls)
- Width: Expands with window but maintains compact layout
- Behavior: Never shrinks below minimum readable size
- Controls: All buttons and inputs maintain readable sizes
- Height: Resizable with window and each other
- Width: Always full width of main content area
- Minimum Heights:
- Input: 120px
- Output: 200px
- Negative: 100px
- Text Areas: Always fit within their frames, no overflow
- Width: Resizable 300-500px range
- Height: Full height when visible
- Toggle: Smooth show/hide animation
- Content: Scrollable list with fixed-size items
- Minimum Window Size: 900x650px (prevents cramping)
- Config Frame: Maintains fixed height, width adjusts
- Content Frames: Heights adjust proportionally
- History Panel: Width adjusts within limits
- Text Areas: Always fit their containers
- Buttons: Never shrink below readable sizes
- Fonts: Scale appropriately but never below 10pt
- Input Frame: 20% of content area
- Output Frame: 50% of content area (largest)
- Negative Frame: 30% of content area
- Primary: Dark theme with professional appearance
- Text: White/light gray on dark backgrounds
- Borders: Subtle gray borders for frame separation
- Buttons: Consistent sizing with clear visual feedback
- Headers: 14pt bold for section titles
- Body Text: 12pt for input/output text
- Buttons: 11-12pt for button text
- Labels: 12pt for form labels
- Frame Padding: 15px internal, 10px external
- Element Spacing: 10-15px between related elements
- Section Spacing: 15px between major sections
- Generate Button: Most prominent, central placement
- History Toggle: Context-aware (shows panel state)
- Action Buttons: Consistent sizing and placement
- Hover States: Clear visual feedback
- Input: Multi-line with scroll when needed
- Output: Read-only with copy functionality
- Negative: Editable when unlocked
- History: Expandable previews with full text option
- Visibility: Clearly visible but not obtrusive
- Responsiveness: Smooth resizing without lag
- Constraints: Prevent unusable layouts
- No Element Disappearance: All elements remain visible during resize
- Minimum Sizes: Prevent buttons/text from becoming unreadable
- Proportional Scaling: Maintain visual balance
- Content Preservation: No text truncation or overflow
- Intuitive Controls: Clear button labels and functions
- Visual Feedback: Loading states and progress indicators
- Error Handling: Clear error messages with recovery options
- Accessibility: Sufficient contrast and readable fonts
- Separation of Concerns: UI layout separate from business logic
- Modular Design: Reusable components and consistent patterns
- Responsive Layout: Grid and paned window systems
- State Management: Proper handling of UI state changes
- Efficient Rendering: Minimize redraws during resize
- Memory Management: Clean up unused UI elements
- Smooth Animation: Fluid transitions for panel toggles
This blueprint serves as the definitive guide for the UI implementation, ensuring consistency and preventing the layout issues experienced previously.
This appendix captures the exact, final UI and behavior that the current application implements. Handing only this file to a new engineer should be sufficient to recreate the app in a single pass.
References to concrete code locations:
- Core window and layout construction: Wan2PromptApp.init(), Wan2PromptApp.create_widgets()
- Service-dependent UI behavior: Wan2PromptApp.update_ui_for_service()
- Threaded actions (refresh, pull, generate, inspire): Wan2PromptApp.refresh_models(), Wan2PromptApp.pull_model(), Wan2PromptApp.run_generation(), Wan2PromptApp.run_inspiration()
- Backend API calls and history: backend.py, generate_prompt(), get_inspiration(), history helpers
- Python 3.10+
- customtkinter (dark theme, Tk-based; not Qt)
- requests (HTTP)
- clipboard (for system clipboard integration)
- Packaging: PyInstaller (Windows .exe), with icon and splash
- Base window width: 800px to avoid truncation. See Wan2PromptApp.init() and width fields in app.py.
- History panel: accordion-style side panel. Default collapsed so the main content stays focused. Expand shrinks/grows overall window width programmatically to keep content legible. See toggle_history_panel().
The main content is a single column containing:
- Config Frame (compact, fixed-height with three internal rows)
- Input Frame (blue section, high vertical priority)
- Generate Button (primary CTA)
- Output Frame (shares vertical space with Input)
- Negative Prompt Frame (compact)
Grid fundamentals:
- The main frame fixes a content width and uses grid weights to distribute height primarily between Input and Output: app.py, app.py
- All inner frames use sticky="ew" for full-width behavior, and appropriate row/column weights for flexible text areas.
Column scheme inside config_frame (0..4):
- 0: Labels (LLM Service, API Endpoint label, Model:, Creativity:)
- 1: Large control cell (segmented button, model dropdown, creativity pills)
- 2: Compact action (Refresh)
- 3: Large control cell on the right (API entry or Pull entry)
- 4: Compact action (Pull Model button)
Row 0 (Services & Endpoint):
- “LLM Service” label, segmented switch [LM Studio | Ollama] in column 1
- “API Endpoint:” label in column 2, URL entry in column 3
- Snug padding. See app.py–app.py
Row 1 (Model + Pull: single dense row, no truncation):
- Label “Model:” in column 0 (very tight left padding)
- Model dropdown in column 1 (expands)
- “⟳ Refresh” button in column 2 (compact)
- Pull entry (placeholder: “e.g., llama3:latest”) in column 3 (expands)
- “Pull Model” button in column 4 (compact)
- This row is intentionally dense; keep label very close to dropdown. See app.py–app.py
- Service-specific visibility of pull section: shown for “Ollama”, hidden for “LM Studio”: update_ui_for_service()
Row 2 (Creativity):
- Label “Creativity:” in column 0
- Segmented button with two options: “Moderate Freedom”, “High Freedom” in column 1 (columnspan=4 so it never truncates)
- Padding remains tight but readable. See app.py–app.py
- Title left: “Your Idea or Basic Prompt”
- Action right: “✨ Inspire Me” on the same header row
- Below header: A large multiline CTkTextbox for the user input. Height and main grid weights give this section significant space, sharing vertically with Output. See app.py–app.py
- Behavior:
- If “Inspire Me” clicked with empty input, app seeds a default idea then requests inspiration: run_inspiration() → backend.get_inspiration()
- Big centered “Generate Wan 2.2 Prompt” button between Input and Output, full-width row: app.py–app.py
- Title left: “Generated Prompt”
- Action right: “Copy to Clipboard”
- Body: read-only multiline CTkTextbox; shares available height with the Input box due to weights: app.py–app.py
- Copy action reads content and sends to system clipboard: copy_output()
- Title: “Negative Prompt (for Wan 2.2)”
- Right action: checkbox “Unlock to Edit” (locked by default)
- Body: CTkTextbox seeded with a default negative prompt; disabled until unlocked: app.py–app.py
- Toggle logic: toggle_neg_prompt_edit()
- Collapsed by default. Toggle button is always visible on the right side panel.
- Expanding shows:
- Search box (live filtering)
- Dropdown filters (Service, Model, Creativity)
- Scrollable history list with item actions
- Clear/Export buttons
- Storage location: %APPDATA%/Wan2PromptGenerator/wan2_prompt_history.json
- Paths and helpers: backend.get_history_file_path(), load_history(), add_to_history()
- UI creation and item rendering: create_history_panel(), update_history_display(), create_history_item()
- Expand/Collapse implementation: toggle_history_panel()
- Creativity modes drive the system prompt template selection: get_system_prompt()
- Moderate Freedom: enrich user idea directly
- High Freedom: treat user idea as a seed and invent more
- Generate Prompt:
- LM Studio: OpenAI-compatible /v1 chat completions
- Ollama: /api/chat (non-stream), messages-based schema
- Network code: generate_prompt()
- Inspire Me:
- Produces three one-liner ideas based on the current user input: get_inspiration_prompt(), get_inspiration()
- All long-running operations run on daemon threads and marshal UI updates via .after(0, ...):
- Refresh models: refresh_models()
- Pull model: pull_model()
- Generate: run_generation()
- Inspire: run_inspiration()
- A single UI-state switch controls enabling/disabling buttons while busy: set_ui_loading()
- Model selection guardrails before generate/inspire: run_generation(), run_inspiration()
- Empty input guardrails and seed: run_inspiration()–app.py
- Robust HTTP error reporting for both services: backend.generate_prompt()–backend.py, backend.get_inspiration()–backend.py
- Tool: PyInstaller (windowed, one-file)
- Icon and splash: use the same PNG: C:\Users\WontML\Pictures\1a\icon.png
- Recommended command (Windows PowerShell):
- python -m pip install --upgrade pyinstaller
- pyinstaller --noconfirm --clean --onefile --windowed app.py --name "Wan2PromptCrafter" --icon "C:\Users\WontML\Pictures\1a\icon.png" --splash "C:\Users\WontML\Pictures\1a\icon.png" --exclude-module PyQt5 --exclude-module PyQt6
- Output: dist\Wan2PromptCrafter.exe
- pip packages required at runtime:
- customtkinter
- requests
- clipboard
- Build-time:
- pyinstaller
- Create two modules: app.py and backend.py.
- Implement UI per this spec in Wan2PromptApp with the exact 3-row Config Frame layout:
- Row 0: LLM Service segmented + API endpoint entry
- Row 1: Model label + dropdown + Refresh + Pull entry + Pull button on one dense row
- Row 2: Creativity segmented (two options)
- Implement Input/Output/Negative frames with the grid weights and read-only output behavior.
- Implement the history panel as an accordion, collapsed by default, and file-backed at %APPDATA%.
- Wrap all network and model operations in threads; synchronize back to UI using after(0, ...).
- Use backend service calls for LM Studio and Ollama exactly as defined in backend.generate_prompt() and backend.get_inspiration().
- Package with the PyInstaller command above and verify the EXE functions offline with local endpoints.