faizee07 commited on
Commit
c7bb72d
·
verified ·
1 Parent(s): 2ed3448

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +335 -0
app.py ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests
3
+ import json
4
+ import re
5
+ from typing import Dict, List, Tuple
6
+ import os
7
+
8
+ class UIDesignAgent:
9
+ def __init__(self, api_key: str):
10
+ self.api_key = api_key
11
+ self.base_url = "https://openrouter.ai/api/v1/chat/completions"
12
+ self.design_system = {}
13
+ self.color_palette = {}
14
+ self.typography = {}
15
+
16
+ def extract_design_system(self, prompt: str) -> Dict:
17
+ """Extract and maintain consistent design system across pages"""
18
+
19
+ system_prompt = """You are an expert UI/UX designer. Extract and define a consistent design system including:
20
+ 1. Color Palette (primary, secondary, accent, neutral colors)
21
+ 2. Typography (font families, sizes, weights)
22
+ 3. Spacing system
23
+ 4. Component styles
24
+
25
+ Return as JSON format."""
26
+
27
+ headers = {
28
+ "Authorization": f"Bearer {self.api_key}",
29
+ "Content-Type": "application/json"
30
+ }
31
+
32
+ data = {
33
+ "model": "google/gemini-pro",
34
+ "messages": [
35
+ {"role": "system", "content": system_prompt},
36
+ {"role": "user", "content": f"Create a design system for: {prompt}"}
37
+ ]
38
+ }
39
+
40
+ try:
41
+ response = requests.post(self.base_url, headers=headers, json=data)
42
+ result = response.json()
43
+ design_system_text = result['choices'][0]['message']['content']
44
+
45
+ # Extract JSON from response
46
+ json_match = re.search(r'\{.*\}', design_system_text, re.DOTALL)
47
+ if json_match:
48
+ self.design_system = json.loads(json_match.group())
49
+
50
+ return self.design_system
51
+ except Exception as e:
52
+ print(f"Error extracting design system: {e}")
53
+ return self.get_default_design_system()
54
+
55
+ def get_default_design_system(self) -> Dict:
56
+ """Return default design system"""
57
+ return {
58
+ "colors": {
59
+ "primary": "#2563eb",
60
+ "secondary": "#7c3aed",
61
+ "accent": "#06b6d4",
62
+ "background": "#ffffff",
63
+ "surface": "#f8fafc",
64
+ "text": "#1e293b",
65
+ "textLight": "#64748b"
66
+ },
67
+ "typography": {
68
+ "fontFamily": "'Inter', -apple-system, sans-serif",
69
+ "h1": "48px",
70
+ "h2": "36px",
71
+ "h3": "24px",
72
+ "body": "16px",
73
+ "small": "14px"
74
+ },
75
+ "spacing": {
76
+ "xs": "4px",
77
+ "sm": "8px",
78
+ "md": "16px",
79
+ "lg": "24px",
80
+ "xl": "32px"
81
+ }
82
+ }
83
+
84
+ def generate_page_html(self, page_description: str, page_number: int) -> str:
85
+ """Generate HTML for a specific page using consistent design system"""
86
+
87
+ design_context = f"""
88
+ Use this exact design system for consistency:
89
+ Colors: {json.dumps(self.design_system.get('colors', {}))}
90
+ Typography: {json.dumps(self.design_system.get('typography', {}))}
91
+ Spacing: {json.dumps(self.design_system.get('spacing', {}))}
92
+ """
93
+
94
+ system_prompt = f"""You are an expert UI developer. Create a complete HTML page with inline CSS.
95
+ {design_context}
96
+
97
+ Rules:
98
+ 1. Use ONLY the provided color values
99
+ 2. Use ONLY the provided typography settings
100
+ 3. Create responsive, modern design
101
+ 4. Include all CSS inline
102
+ 5. Make it interactive with hover effects
103
+ 6. Ensure consistency with the design system"""
104
+
105
+ headers = {
106
+ "Authorization": f"Bearer {self.api_key}",
107
+ "Content-Type": "application/json"
108
+ }
109
+
110
+ data = {
111
+ "model": "google/gemini-pro",
112
+ "messages": [
113
+ {"role": "system", "content": system_prompt},
114
+ {"role": "user", "content": f"Create page {page_number}: {page_description}. Return ONLY the HTML code."}
115
+ ]
116
+ }
117
+
118
+ try:
119
+ response = requests.post(self.base_url, headers=headers, json=data)
120
+ result = response.json()
121
+ html_content = result['choices'][0]['message']['content']
122
+
123
+ # Extract HTML from code blocks if present
124
+ html_match = re.search(r'```html\n(.*?)\n```', html_content, re.DOTALL)
125
+ if html_match:
126
+ html_content = html_match.group(1)
127
+
128
+ # Inject design system CSS
129
+ html_content = self.inject_design_system_css(html_content)
130
+
131
+ return html_content
132
+ except Exception as e:
133
+ return f"<div style='color: red;'>Error generating page: {str(e)}</div>"
134
+
135
+ def inject_design_system_css(self, html: str) -> str:
136
+ """Inject consistent CSS variables into HTML"""
137
+
138
+ css_variables = f"""
139
+ <style>
140
+ :root {{
141
+ --primary: {self.design_system.get('colors', {}).get('primary', '#2563eb')};
142
+ --secondary: {self.design_system.get('colors', {}).get('secondary', '#7c3aed')};
143
+ --accent: {self.design_system.get('colors', {}).get('accent', '#06b6d4')};
144
+ --background: {self.design_system.get('colors', {}).get('background', '#ffffff')};
145
+ --surface: {self.design_system.get('colors', {}).get('surface', '#f8fafc')};
146
+ --text: {self.design_system.get('colors', {}).get('text', '#1e293b')};
147
+ --text-light: {self.design_system.get('colors', {}).get('textLight', '#64748b')};
148
+ --font-family: {self.design_system.get('typography', {}).get('fontFamily', 'Inter, sans-serif')};
149
+ }}
150
+
151
+ * {{
152
+ margin: 0;
153
+ padding: 0;
154
+ box-sizing: border-box;
155
+ }}
156
+
157
+ body {{
158
+ font-family: var(--font-family);
159
+ background-color: var(--background);
160
+ color: var(--text);
161
+ line-height: 1.6;
162
+ }}
163
+
164
+ .primary-btn {{
165
+ background-color: var(--primary);
166
+ color: white;
167
+ padding: 12px 24px;
168
+ border: none;
169
+ border-radius: 8px;
170
+ cursor: pointer;
171
+ transition: all 0.3s ease;
172
+ }}
173
+
174
+ .primary-btn:hover {{
175
+ transform: translateY(-2px);
176
+ box-shadow: 0 4px 12px rgba(37, 99, 235, 0.3);
177
+ }}
178
+ </style>
179
+ """
180
+
181
+ # Insert CSS after <head> tag or at the beginning
182
+ if '<head>' in html:
183
+ html = html.replace('<head>', f'<head>{css_variables}')
184
+ else:
185
+ html = css_variables + html
186
+
187
+ return html
188
+
189
+ def generate_multi_page_design(self, prompt: str) -> Tuple[List[str], Dict]:
190
+ """Generate multiple pages with consistent design"""
191
+
192
+ # First, extract pages from prompt
193
+ pages = self.extract_pages_from_prompt(prompt)
194
+
195
+ # Extract and set design system
196
+ self.design_system = self.extract_design_system(prompt)
197
+
198
+ # Generate HTML for each page
199
+ generated_pages = []
200
+ for i, page_desc in enumerate(pages, 1):
201
+ html = self.generate_page_html(page_desc, i)
202
+ generated_pages.append(html)
203
+
204
+ return generated_pages, self.design_system
205
+
206
+ def extract_pages_from_prompt(self, prompt: str) -> List[str]:
207
+ """Extract individual page descriptions from prompt"""
208
+
209
+ system_prompt = """Extract individual page descriptions from the user's request.
210
+ Return as a JSON array of page descriptions."""
211
+
212
+ headers = {
213
+ "Authorization": f"Bearer {self.api_key}",
214
+ "Content-Type": "application/json"
215
+ }
216
+
217
+ data = {
218
+ "model": "google/gemini-pro",
219
+ "messages": [
220
+ {"role": "system", "content": system_prompt},
221
+ {"role": "user", "content": prompt}
222
+ ]
223
+ }
224
+
225
+ try:
226
+ response = requests.post(self.base_url, headers=headers, json=data)
227
+ result = response.json()
228
+ pages_text = result['choices'][0]['message']['content']
229
+
230
+ # Extract JSON array
231
+ json_match = re.search(r'\[.*\]', pages_text, re.DOTALL)
232
+ if json_match:
233
+ pages = json.loads(json_match.group())
234
+ return pages
235
+ else:
236
+ # Default to single page if extraction fails
237
+ return [prompt]
238
+ except Exception as e:
239
+ print(f"Error extracting pages: {e}")
240
+ return [prompt]
241
+
242
+ # Gradio Interface
243
+ def create_ui_design(prompt: str, api_key: str):
244
+ """Main function to create UI designs"""
245
+
246
+ if not api_key:
247
+ return ["<div style='color: red;'>Please provide OpenRouter API key</div>"], "No design system"
248
+
249
+ agent = UIDesignAgent(api_key)
250
+ pages, design_system = agent.generate_multi_page_design(prompt)
251
+
252
+ # Format design system for display
253
+ design_system_display = json.dumps(design_system, indent=2)
254
+
255
+ # Ensure we have at least 3 pages for the interface
256
+ while len(pages) < 3:
257
+ pages.append("<div style='padding: 20px;'>Page placeholder</div>")
258
+
259
+ return pages[0], pages[1] if len(pages) > 1 else "", pages[2] if len(pages) > 2 else "", design_system_display
260
+
261
+ # Create Gradio interface
262
+ with gr.Blocks(title="AI UI Designer - Stitch Clone", theme=gr.themes.Soft()) as demo:
263
+ gr.Markdown("""
264
+ # 🎨 AI UI Designer (Stitch-like)
265
+ ### Generate consistent multi-page website designs with AI
266
+
267
+ This tool ensures consistent colors, typography, and styling across all generated pages.
268
+ """)
269
+
270
+ with gr.Row():
271
+ with gr.Column(scale=1):
272
+ api_key_input = gr.Textbox(
273
+ label="OpenRouter API Key",
274
+ placeholder="Enter your OpenRouter API key",
275
+ type="password"
276
+ )
277
+
278
+ prompt_input = gr.Textbox(
279
+ label="Design Prompt",
280
+ placeholder="Describe your multi-page website (e.g., 'Create a 3-page website for a tech startup with: 1) Landing page with hero section, 2) About page with team section, 3) Contact page with form')",
281
+ lines=5
282
+ )
283
+
284
+ generate_btn = gr.Button("🚀 Generate Design", variant="primary")
285
+
286
+ design_system_output = gr.Code(
287
+ label="Design System",
288
+ language="json",
289
+ lines=10
290
+ )
291
+
292
+ with gr.Column(scale=2):
293
+ with gr.Tabs():
294
+ with gr.TabItem("Page 1"):
295
+ page1_output = gr.HTML(label="Page 1 Preview")
296
+
297
+ with gr.TabItem("Page 2"):
298
+ page2_output = gr.HTML(label="Page 2 Preview")
299
+
300
+ with gr.TabItem("Page 3"):
301
+ page3_output = gr.HTML(label="Page 3 Preview")
302
+
303
+ gr.Markdown("""
304
+ ### Features:
305
+ - ✅ Consistent color scheme across all pages
306
+ - ✅ Unified typography and spacing
307
+ - ✅ Responsive design
308
+ - ✅ Modern UI components
309
+ - ✅ Design system extraction
310
+
311
+ ### How to use:
312
+ 1. Get your API key from [OpenRouter](https://openrouter.ai/)
313
+ 2. Describe your multi-page website
314
+ 3. Click Generate Design
315
+ 4. View consistent designs across all pages
316
+ """)
317
+
318
+ generate_btn.click(
319
+ fn=create_ui_design,
320
+ inputs=[prompt_input, api_key_input],
321
+ outputs=[page1_output, page2_output, page3_output, design_system_output]
322
+ )
323
+
324
+ # Example prompts
325
+ gr.Examples(
326
+ examples=[
327
+ ["Create a 3-page SaaS website: 1) Landing page with pricing cards, 2) Features page with grid layout, 3) Contact page with form"],
328
+ ["Design a portfolio website: 1) Home with hero section, 2) Projects gallery page, 3) About me page with skills"],
329
+ ["Build an e-commerce site: 1) Homepage with product grid, 2) Product detail page, 3) Shopping cart page"],
330
+ ],
331
+ inputs=prompt_input
332
+ )
333
+
334
+ if __name__ == "__main__":
335
+ demo.launch()