import gradio as gr import json import re from typing import Dict, List, Tuple import os # Important: Make sure you have python-dotenv installed (`pip install python-dotenv`) # and a .env file if you run locally. On HF Spaces, use secrets. from dotenv import load_dotenv # Try to import CrewAI libraries. If they fail, it means they are not installed. try: from crewai import Agent, Task, Crew, Process from langchain_openai import ChatOpenAI except ImportError: raise ImportError( "CrewAI or LangChain not installed. Please ensure your requirements.txt is correct and dependencies are installed." ) load_dotenv() # --- Configuration --- # You can change the model here. Claude 3 Haiku is fast, cheap, and very capable. DEFAULT_MODEL = "minimax/minimax-m2:free" # --- Agent Definitions --- # 1. Color Specialist Agent color_specialist = Agent( role='Expert Color Palette Designer', goal="""Select a visually appealing and contextually appropriate color palette based on the user's website description. The palette must include primary, secondary, background, surface, and text colors.""", backstory="""You are a world-renowned graphic designer with a deep understanding of color theory and its psychological impact. You create palettes that are not only beautiful but also functional and accessible.""", verbose=True, allow_delegation=False ) # 2. Typography Specialist Agent typography_specialist = Agent( role='Master Typographer for Digital Interfaces', goal="""Define a complete and harmonious typography system, including a web-safe font family and a responsive size scale (h1, h2, body, small).""", backstory="""With decades of experience, you excel at choosing fonts that are readable, stylish, and appropriate for a brand's voice. You create clear typographic hierarchies that work perfectly on the web.""", verbose=True, allow_delegation=False ) # 3. Design System Architect Agent (The "Stitcher") design_system_architect = Agent( role='Senior UI Design System Architect', goal="""Consolidate the color and typography schemes into a single, comprehensive, and developer-friendly JSON design system. Also add standard 'spacing' and 'borderRadius' systems.""", backstory="""You are a meticulous senior UI designer who creates robust and scalable design systems. Your work ensures absolute consistency and serves as the single source of truth for the entire development team.""", verbose=True, allow_delegation=False ) # 4. Web UI Developer Agent web_developer = Agent( role='Expert Frontend Developer specializing in Web UI', goal="""Generate a complete, single HTML file for a given page description, strictly adhering to the provided design system. The code must be clean, responsive, and modern.""", backstory="""You are a pixel-perfect frontend developer who translates design systems into clean, responsive, and maintainable HTML and CSS. You never deviate from the design specifications.""", verbose=True, allow_delegation=False ) # --- Task Definitions --- def create_design_tasks(prompt): task_colors = Task( description=f"""Analyze the user's prompt: '{prompt}'. Generate a JSON object for the color palette. The JSON must contain keys: 'primary', 'secondary', 'background', 'surface', 'text'.""", expected_output="A single, valid JSON object containing the color palette.", agent=color_specialist ) task_typography = Task( description=f"""Analyze the user's prompt: '{prompt}'. Generate a JSON object for the typography system. It must include 'fontFamily', and sizes for 'h1', 'h2', 'body', 'small'.""", expected_output="A single, valid JSON object for the typography system.", agent=typography_specialist ) task_architect = Task( description="""Take the color palette and typography system from the specialists. Combine them into a single, final JSON object. Also, add standard 'spacing' (sm, md, lg) and 'borderRadius' (md, lg) systems. Your final output must be ONLY this complete JSON object and nothing else.""", expected_output="A single, valid JSON object representing the complete design system.", agent=design_system_architect, context=[task_colors, task_typography] ) return task_colors, task_typography, task_architect def create_developer_task(design_system_json, page_description): return Task( description=f"""Using the final design system provided below, create a complete HTML file for the following page: '{page_description}'. All CSS must be in a single `""" html += "

Color Palette

" for name, hex_val in colors.items(): try: r,g,b=int(hex_val[1:3],16),int(hex_val[3:5],16),int(hex_val[5:7],16); text_color='#fff' if (0.299*r+0.587*g+0.114*b)/255<0.5 else '#000' except: text_color='#000' html+=f'
{name.capitalize()}{hex_val}
' html += "
" font_family = typography.get('fontFamily', 'sans-serif') html += f"

Typography

Font: {font_family}

" for name, sample_text in {'h1':'Heading 1','h2':'Heading 2','body':'This is a paragraph of body text.'}.items(): html+=f'
{sample_text}
' html += "
" return html # --- Gradio Interface --- def create_interface(): with gr.Blocks(title="CrewAI UI Designer", theme=gr.themes.Soft()) as demo: gr.Markdown("# 🤖 CrewAI Powered UI Designer") with gr.Row(): with gr.Column(scale=1): api_key_input = gr.Textbox(label="OpenRouter API Key", placeholder="sk-or-...", type="password") prompt_input = gr.Textbox(label="Website Description", placeholder="e.g., A dark-mode, futuristic site for a synthwave musician: 1) landing page, 2) music, 3) tour dates", lines=4) generate_btn = gr.Button("🚀 Assemble the Crew!", variant="primary") with gr.Tabs(): with gr.TabItem("Visualizer"): design_system_visualizer = gr.HTML() with gr.TabItem("JSON"): design_system_output = gr.Code(language="json", lines=15) with gr.Column(scale=2): with gr.Tabs(): with gr.TabItem("📄 Page 1"): page1_output = gr.HTML() with gr.TabItem("📄 Page 2"): page2_output = gr.HTML() with gr.TabItem("📄 Page 3"): page3_output = gr.HTML() generate_btn.click(fn=create_ui_design, inputs=[prompt_input, api_key_input], outputs=[page1_output, page2_output, page3_output, design_system_output, design_system_visualizer]) return demo if __name__ == "__main__": demo = create_interface() demo.launch()