AiCoderv2 commited on
Commit
629446c
·
verified ·
1 Parent(s): 69d0147

Deploy Gradio app with multiple files

Browse files
Files changed (5) hide show
  1. app.py +320 -0
  2. config.py +137 -0
  3. models.py +858 -0
  4. requirements.txt +43 -0
  5. utils.py +176 -0
app.py ADDED
@@ -0,0 +1,320 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import os
3
+ import json
4
+ import zipfile
5
+ import tempfile
6
+ from pathlib import Path
7
+ from typing import Dict, List, Tuple, Optional
8
+ import shutil
9
+ from utils import FileHandler, PreviewManager
10
+ from models import QwenWebsiteBuilder
11
+ from config import SUPPORTED_FILES, DEFAULT_PROMPT
12
+
13
+ class AIWebsiteBuilder:
14
+ def __init__(self):
15
+ self.file_handler = FileHandler()
16
+ self.preview_manager = PreviewManager()
17
+ self.model = QwenWebsiteBuilder()
18
+ self.current_project = None
19
+ self.project_history = []
20
+
21
+ def create_website(self, prompt: str, project_name: str) -> Tuple[str, str, str]:
22
+ """Generate a complete website based on user prompt"""
23
+ try:
24
+ # Generate website files
25
+ files = self.model.generate_website(prompt, project_name)
26
+
27
+ # Create project directory
28
+ project_path = self.file_handler.create_project(project_name, files)
29
+ self.current_project = project_path
30
+
31
+ # Generate preview URL
32
+ preview_url = self.preview_manager.create_preview(project_path)
33
+
34
+ # Create download zip
35
+ zip_path = self.file_handler.create_zip(project_path)
36
+
37
+ # Update history
38
+ self.project_history.append({
39
+ "name": project_name,
40
+ "prompt": prompt,
41
+ "path": project_path,
42
+ "files": list(files.keys())
43
+ })
44
+
45
+ return f"✅ Website '{project_name}' created successfully!", preview_url, zip_path
46
+
47
+ except Exception as e:
48
+ return f"❌ Error: {str(e)}", "", ""
49
+
50
+ def update_file(self, project_name: str, filename: str, content: str) -> str:
51
+ """Update a specific file in the project"""
52
+ try:
53
+ if self.current_project:
54
+ file_path = self.current_project / filename
55
+ with open(file_path, 'w', encoding='utf-8') as f:
56
+ f.write(content)
57
+
58
+ # Update preview
59
+ preview_url = self.preview_manager.update_preview(self.current_project)
60
+ return f"✅ File '{filename}' updated successfully! Preview refreshed."
61
+ else:
62
+ return "❌ No active project. Please create a website first."
63
+ except Exception as e:
64
+ return f"❌ Error updating file: {str(e)}"
65
+
66
+ def get_project_files(self) -> Dict[str, str]:
67
+ """Get all files in current project"""
68
+ if self.current_project:
69
+ return self.file_handler.get_project_files(self.current_project)
70
+ return {}
71
+
72
+ def get_file_content(self, filename: str) -> str:
73
+ """Get content of a specific file"""
74
+ if self.current_project:
75
+ return self.file_handler.get_file_content(self.current_project, filename)
76
+ return ""
77
+
78
+ def get_project_history(self) -> List[Dict]:
79
+ """Get project generation history"""
80
+ return self.project_history
81
+
82
+ # Initialize the builder
83
+ builder = AIWebsiteBuilder()
84
+
85
+ def create_interface():
86
+ with gr.Blocks(
87
+ title="AI Website Builder",
88
+ theme=gr.themes.Soft(),
89
+ css="""
90
+ .header {
91
+ text-align: center;
92
+ padding: 20px;
93
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
94
+ color: white;
95
+ border-radius: 10px;
96
+ margin-bottom: 20px;
97
+ }
98
+ .file-editor {
99
+ border: 1px solid #ddd;
100
+ border-radius: 5px;
101
+ }
102
+ .preview-frame {
103
+ border: 2px solid #667eea;
104
+ border-radius: 5px;
105
+ min-height: 600px;
106
+ }
107
+ """,
108
+ head="""
109
+ <style>
110
+ .header a {
111
+ color: white;
112
+ text-decoration: underline;
113
+ }
114
+ </style>
115
+ """
116
+ ) as demo:
117
+
118
+ with gr.Row():
119
+ gr.HTML("""
120
+ <div class="header">
121
+ <h1>🚀 AI Website Builder</h1>
122
+ <p>Powered by Qwen AI - Build complete websites with multiple files instantly!</p>
123
+ <p><small>Built with <a href="https://huggingface.co/spaces/akhaliq/anycoder" target="_blank">anycoder</a></small></p>
124
+ </div>
125
+ """)
126
+
127
+ with gr.Tabs() as tabs:
128
+ # Tab 1: Create Website
129
+ with gr.TabItem("🏗️ Create Website", id="create"):
130
+ with gr.Row():
131
+ with gr.Column(scale=2):
132
+ project_name = gr.Textbox(
133
+ label="Project Name",
134
+ placeholder="my-awesome-website",
135
+ value="my-website"
136
+ )
137
+ prompt = gr.Textbox(
138
+ label="Website Description",
139
+ placeholder=DEFAULT_PROMPT,
140
+ lines=4,
141
+ value=DEFAULT_PROMPT
142
+ )
143
+ create_btn = gr.Button("🚀 Generate Website", variant="primary", size="lg")
144
+
145
+ with gr.Column(scale=1):
146
+ gr.Markdown("""
147
+ ### 📝 Tips:
148
+ - Be specific about design preferences
149
+ - Mention required features
150
+ - Specify any frameworks (React, Vue, etc.)
151
+ - Include color schemes if desired
152
+
153
+ ### 🎯 Examples:
154
+ - "Create a portfolio website for a photographer with gallery"
155
+ - "Build an e-commerce site for selling handmade crafts"
156
+ - "Design a landing page for a SaaS product"
157
+ """)
158
+
159
+ with gr.Row():
160
+ status_msg = gr.Textbox(label="Status", interactive=False)
161
+ preview_url = gr.Textbox(label="Preview URL", interactive=False)
162
+ download_link = gr.File(label="Download ZIP", visible=False)
163
+
164
+ # Preview iframe
165
+ preview_frame = gr.HTML(
166
+ label="Live Preview",
167
+ visible=False,
168
+ elem_classes=["preview-frame"]
169
+ )
170
+
171
+ create_btn.click(
172
+ fn=builder.create_website,
173
+ inputs=[prompt, project_name],
174
+ outputs=[status_msg, preview_url, download_link]
175
+ ).then(
176
+ fn=lambda url: f'<iframe src="{url}" width="100%" height="600px" class="preview-frame"></iframe>' if url else "",
177
+ inputs=[preview_url],
178
+ outputs=[preview_frame],
179
+ js="(url) => url ? document.querySelector('.preview-frame').parentElement.style.display = 'block' : null"
180
+ )
181
+
182
+ # Tab 2: Code Editor
183
+ with gr.TabItem("✏️ Code Editor", id="editor"):
184
+ with gr.Row():
185
+ with gr.Column(scale=1):
186
+ file_list = gr.Dropdown(
187
+ label="Select File",
188
+ choices=[],
189
+ interactive=True
190
+ )
191
+ refresh_files_btn = gr.Button("🔄 Refresh Files")
192
+
193
+ with gr.Column(scale=2):
194
+ code_editor = gr.Code(
195
+ label="Edit Code",
196
+ language="html",
197
+ lines=20,
198
+ interactive=True
199
+ )
200
+ update_btn = gr.Button("💾 Save Changes", variant="primary")
201
+ editor_status = gr.Textbox(label="Status", interactive=False)
202
+
203
+ # File selection
204
+ def update_file_list():
205
+ files = builder.get_project_files()
206
+ return gr.Dropdown(choices=list(files.keys()), value=list(files.keys())[0] if files else None)
207
+
208
+ def load_file_content(filename):
209
+ if filename:
210
+ content = builder.get_file_content(filename)
211
+ # Detect language
212
+ ext = Path(filename).suffix.lower()
213
+ lang_map = {
214
+ '.html': 'html',
215
+ '.css': 'css',
216
+ '.js': 'javascript',
217
+ '.json': 'json',
218
+ '.md': 'markdown',
219
+ '.py': 'python',
220
+ '.jsx': 'jsx',
221
+ '.tsx': 'typescript',
222
+ '.ts': 'typescript'
223
+ }
224
+ return content, lang_map.get(ext, 'html')
225
+ return "", "html"
226
+
227
+ refresh_files_btn.click(
228
+ fn=update_file_list,
229
+ outputs=[file_list]
230
+ )
231
+
232
+ file_list.change(
233
+ fn=load_file_content,
234
+ inputs=[file_list],
235
+ outputs=[code_editor, code_editor]
236
+ )
237
+
238
+ update_btn.click(
239
+ fn=builder.update_file,
240
+ inputs=[project_name, file_list, code_editor],
241
+ outputs=[editor_status]
242
+ )
243
+
244
+ # Tab 3: Project History
245
+ with gr.TabItem("📚 History", id="history"):
246
+ history_display = gr.Dataframe(
247
+ headers=["Project Name", "Prompt", "Files"],
248
+ datatype=["str", "str", "str"],
249
+ label="Previous Projects"
250
+ )
251
+ refresh_history_btn = gr.Button("🔄 Refresh History")
252
+
253
+ def refresh_history():
254
+ history = builder.get_project_history()
255
+ if history:
256
+ data = []
257
+ for project in history:
258
+ data.append([
259
+ project["name"],
260
+ project["prompt"][:50] + "..." if len(project["prompt"]) > 50 else project["prompt"],
261
+ ", ".join(project["files"])
262
+ ])
263
+ return data
264
+ return []
265
+
266
+ refresh_history_btn.click(
267
+ fn=refresh_history,
268
+ outputs=[history_display]
269
+ )
270
+
271
+ # Tab 4: Settings
272
+ with gr.TabItem("⚙️ Settings", id="settings"):
273
+ with gr.Row():
274
+ with gr.Column():
275
+ gr.Markdown("### 🎨 Theme Settings")
276
+ theme_choice = gr.Radio(
277
+ choices=["Modern", "Minimal", "Colorful", "Dark"],
278
+ value="Modern",
279
+ label="Default Theme"
280
+ )
281
+
282
+ gr.Markdown("### 🚀 Advanced Options")
283
+ use_react = gr.Checkbox(label="Use React Framework", value=False)
284
+ use_typescript = gr.Checkbox(label="Use TypeScript", value=False)
285
+ include_tests = gr.Checkbox(label="Include Test Files", value=False)
286
+
287
+ with gr.Column():
288
+ gr.Markdown("### 📁 Supported File Types")
289
+ gr.Markdown(f"""
290
+ {', '.join([f'`.{ext}`' for ext in SUPPORTED_FILES])}
291
+
292
+ ### 🔧 Features:
293
+ - Multi-file project generation
294
+ - Live preview with hot reload
295
+ - Code editor with syntax highlighting
296
+ - Project history tracking
297
+ - ZIP download support
298
+ - Responsive design
299
+ - SEO optimization
300
+ - Performance optimization
301
+ """)
302
+
303
+ # Auto-refresh file list when switching to editor tab
304
+ tabs.select(
305
+ fn=update_file_list,
306
+ inputs=[],
307
+ outputs=[file_list],
308
+ show_progress=False
309
+ )
310
+
311
+ return demo
312
+
313
+ if __name__ == "__main__":
314
+ demo = create_interface()
315
+ demo.launch(
316
+ server_name="0.0.0.0",
317
+ server_port=7860,
318
+ share=True,
319
+ show_error=True
320
+ )
config.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Configuration file for AI Website Builder
2
+
3
+ # Supported file types
4
+ SUPPORTED_FILES = [
5
+ 'html', 'css', 'js', 'json', 'md', 'txt', 'xml', 'yaml', 'yml',
6
+ 'jsx', 'tsx', 'ts', 'vue', 'svelte', 'py', 'php', 'rb', 'go',
7
+ 'java', 'c', 'cpp', 'h', 'hpp', 'scss', 'sass', 'less',
8
+ 'sql', 'sh', 'bat', 'ps1', 'dockerfile', 'gitignore',
9
+ 'env', 'ini', 'cfg', 'conf', 'log', 'csv', 'svg', 'png',
10
+ 'jpg', 'jpeg', 'gif', 'ico', 'pdf', 'doc', 'docx', 'xls',
11
+ 'xlsx', 'ppt', 'pptx', 'zip', 'rar', 'tar', 'gz'
12
+ ]
13
+
14
+ # Default prompt for new users
15
+ DEFAULT_PROMPT = """Create a modern portfolio website with:
16
+ - Hero section with animated text
17
+ - Project gallery with filter functionality
18
+ - About section with skills
19
+ - Contact form with validation
20
+ - Smooth scrolling navigation
21
+ - Dark/light mode toggle
22
+ - Responsive design for all devices
23
+ - Modern animations and transitions"""
24
+
25
+ # Website templates
26
+ WEBSITE_TEMPLATES = {
27
+ "portfolio": {
28
+ "name": "Portfolio Website",
29
+ "description": "Perfect for showcasing your work and skills",
30
+ "features": ["gallery", "about", "contact", "skills"]
31
+ },
32
+ "business": {
33
+ "name": "Business Website",
34
+ "description": "Professional website for your business",
35
+ "features": ["services", "about", "testimonials", "contact"]
36
+ },
37
+ "blog": {
38
+ "name": "Blog Website",
39
+ "description": "Clean and modern blog design",
40
+ "features": ["posts", "categories", "search", "comments"]
41
+ },
42
+ "ecommerce": {
43
+ "name": "E-commerce Store",
44
+ "description": "Online store with product catalog",
45
+ "features": ["products", "cart", "checkout", "search"]
46
+ },
47
+ "landing": {
48
+ "name": "Landing Page",
49
+ "description": "High-converting landing page",
50
+ "features": ["hero", "features", "testimonials", "cta"]
51
+ }
52
+ }
53
+
54
+ # Color schemes
55
+ COLOR_SCHEMES = {
56
+ "blue": {
57
+ "primary": "#3498db",
58
+ "secondary": "#2980b9",
59
+ "accent": "#e74c3c"
60
+ },
61
+ "red": {
62
+ "primary": "#e74c3c",
63
+ "secondary": "#c0392b",
64
+ "accent": "#f39c12"
65
+ },
66
+ "green": {
67
+ "primary": "#27ae60",
68
+ "secondary": "#229954",
69
+ "accent": "#f39c12"
70
+ },
71
+ "purple": {
72
+ "primary": "#9b59b6",
73
+ "secondary": "#8e44ad",
74
+ "accent": "#e74c3c"
75
+ },
76
+ "orange": {
77
+ "primary": "#f39c12",
78
+ "secondary": "#e67e22",
79
+ "accent": "#3498db"
80
+ },
81
+ "dark": {
82
+ "primary": "#34495e",
83
+ "secondary": "#2c3e50",
84
+ "accent": "#3498db"
85
+ }
86
+ }
87
+
88
+ # Framework options
89
+ FRAMEWORKS = {
90
+ "vanilla": {
91
+ "name": "Vanilla HTML/CSS/JS",
92
+ "description": "Pure web technologies, no frameworks"
93
+ },
94
+ "bootstrap": {
95
+ "name": "Bootstrap",
96
+ "description": "Popular CSS framework for responsive design"
97
+ },
98
+ "tailwind": {
99
+ "name": "Tailwind CSS",
100
+ "description": "Utility-first CSS framework"
101
+ },
102
+ "react": {
103
+ "name": "React",
104
+ "description": "JavaScript library for building user interfaces"
105
+ },
106
+ "vue": {
107
+ "name": "Vue.js",
108
+ "description": "Progressive JavaScript framework"
109
+ }
110
+ }
111
+
112
+ # Server configuration
113
+ SERVER_CONFIG = {
114
+ "host": "0.0.0.0",
115
+ "port": 7860,
116
+ "debug": True,
117
+ "share": True
118
+ }
119
+
120
+ # File size limits (in bytes)
121
+ MAX_FILE_SIZE = 10 * 1024 * 1024 # 10MB
122
+ MAX_ZIP_SIZE = 50 * 1024 * 1024 # 50MB
123
+
124
+ # Preview server settings
125
+ PREVIEW_CONFIG = {
126
+ "port_range": (8000, 9000),
127
+ "timeout": 30,
128
+ "auto_refresh": True
129
+ }
130
+
131
+ # AI model settings
132
+ AI_CONFIG = {
133
+ "model": "qwen2.5-72b-instruct",
134
+ "temperature": 0.7,
135
+ "max_tokens": 4000,
136
+ "timeout": 60
137
+ }
models.py ADDED
@@ -0,0 +1,858 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import re
3
+ from typing import Dict, List, Optional
4
+ from pathlib import Path
5
+ import random
6
+
7
+ class QwenWebsiteBuilder:
8
+ """AI-powered website builder using Qwen model logic"""
9
+
10
+ def __init__(self):
11
+ self.templates = self._load_templates()
12
+ self.components = self._load_components()
13
+
14
+ def generate_website(self, prompt: str, project_name: str) -> Dict[str, str]:
15
+ """Generate a complete website based on the prompt"""
16
+ # Parse requirements from prompt
17
+ requirements = self._parse_requirements(prompt)
18
+
19
+ # Generate HTML structure
20
+ html_content = self._generate_html(requirements, project_name)
21
+
22
+ # Generate CSS styles
23
+ css_content = self._generate_css(requirements)
24
+
25
+ # Generate JavaScript functionality
26
+ js_content = self._generate_js(requirements)
27
+
28
+ # Generate additional files based on requirements
29
+ files = {
30
+ "index.html": html_content,
31
+ "styles/main.css": css_content,
32
+ "scripts/main.js": js_content,
33
+ "README.md": self._generate_readme(requirements, project_name),
34
+ "package.json": self._generate_package_json(requirements),
35
+ }
36
+
37
+ # Add framework-specific files
38
+ if requirements.get("framework") == "react":
39
+ files.update(self._generate_react_files(requirements))
40
+ elif requirements.get("framework") == "vue":
41
+ files.update(self._generate_vue_files(requirements))
42
+
43
+ # Add additional pages if requested
44
+ if requirements.get("pages"):
45
+ for page in requirements["pages"]:
46
+ files.update(self._generate_page(page, requirements))
47
+
48
+ # Add assets
49
+ files.update(self._generate_assets(requirements))
50
+
51
+ return files
52
+
53
+ def _parse_requirements(self, prompt: str) -> Dict:
54
+ """Parse user requirements from the prompt"""
55
+ requirements = {
56
+ "type": "website",
57
+ "design": "modern",
58
+ "features": [],
59
+ "pages": ["home"],
60
+ "framework": None,
61
+ "color_scheme": "blue",
62
+ "responsive": True,
63
+ "interactive": True
64
+ }
65
+
66
+ prompt_lower = prompt.lower()
67
+
68
+ # Detect website type
69
+ if "portfolio" in prompt_lower:
70
+ requirements["type"] = "portfolio"
71
+ requirements["features"].extend(["gallery", "about", "contact"])
72
+ elif "ecommerce" in prompt_lower or "shop" in prompt_lower:
73
+ requirements["type"] = "ecommerce"
74
+ requirements["features"].extend(["products", "cart", "checkout"])
75
+ elif "blog" in prompt_lower:
76
+ requirements["type"] = "blog"
77
+ requirements["features"].extend(["posts", "categories", "comments"])
78
+ elif "landing" in prompt_lower:
79
+ requirements["type"] = "landing"
80
+ requirements["features"].extend(["hero", "features", "cta"])
81
+
82
+ # Detect framework preferences
83
+ if "react" in prompt_lower:
84
+ requirements["framework"] = "react"
85
+ elif "vue" in prompt_lower:
86
+ requirements["framework"] = "vue"
87
+ elif "bootstrap" in prompt_lower:
88
+ requirements["framework"] = "bootstrap"
89
+
90
+ # Detect color preferences
91
+ colors = ["blue", "red", "green", "purple", "orange", "dark", "light"]
92
+ for color in colors:
93
+ if color in prompt_lower:
94
+ requirements["color_scheme"] = color
95
+ break
96
+
97
+ # Detect specific features
98
+ features_map = {
99
+ "contact": ["contact form", "contact"],
100
+ "gallery": ["gallery", "images", "photos"],
101
+ "navigation": ["navigation", "menu", "navbar"],
102
+ "search": ["search", "filter"],
103
+ "animation": ["animation", "animate", "transition"],
104
+ "responsive": ["responsive", "mobile"],
105
+ "dark mode": ["dark mode", "dark theme"]
106
+ }
107
+
108
+ for feature, keywords in features_map.items():
109
+ if any(keyword in prompt_lower for keyword in keywords):
110
+ requirements["features"].append(feature)
111
+
112
+ return requirements
113
+
114
+ def _generate_html(self, requirements: Dict, project_name: str) -> str:
115
+ """Generate HTML structure"""
116
+ html_template = f"""<!DOCTYPE html>
117
+ <html lang="en">
118
+ <head>
119
+ <meta charset="UTF-8">
120
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
121
+ <title>{project_name.title()}</title>
122
+ <meta name="description" content="{requirements.get('description', 'A modern website built with AI')}">
123
+ <link rel="stylesheet" href="styles/main.css">
124
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
125
+ </head>
126
+ <body>
127
+ {self._generate_navigation(requirements)}
128
+
129
+ <main>
130
+ {self._generate_hero_section(requirements)}
131
+ {self._generate_features_section(requirements)}
132
+ {self._generate_content_sections(requirements)}
133
+ </main>
134
+
135
+ {self._generate_footer(requirements)}
136
+
137
+ <script src="scripts/main.js"></script>
138
+ </body>
139
+ </html>"""
140
+ return html_template
141
+
142
+ def _generate_css(self, requirements: Dict) -> str:
143
+ """Generate CSS styles"""
144
+ color_scheme = requirements.get("color_scheme", "blue")
145
+ colors = self._get_color_palette(color_scheme)
146
+
147
+ css = f"""/* Global Styles */
148
+ * {{
149
+ margin: 0;
150
+ padding: 0;
151
+ box-sizing: border-box;
152
+ }}
153
+
154
+ :root {{
155
+ --primary-color: {colors['primary']};
156
+ --secondary-color: {colors['secondary']};
157
+ --accent-color: {colors['accent']};
158
+ --text-color: {colors['text']};
159
+ --bg-color: {colors['background']};
160
+ --light-bg: {colors['light_bg']};
161
+ }}
162
+
163
+ body {{
164
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
165
+ line-height: 1.6;
166
+ color: var(--text-color);
167
+ background-color: var(--bg-color);
168
+ }}
169
+
170
+ /* Navigation */
171
+ .navbar {{
172
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
173
+ padding: 1rem 0;
174
+ position: fixed;
175
+ width: 100%;
176
+ top: 0;
177
+ z-index: 1000;
178
+ box-shadow: 0 2px 10px rgba(0,0,0,0.1);
179
+ }}
180
+
181
+ .nav-container {{
182
+ max-width: 1200px;
183
+ margin: 0 auto;
184
+ padding: 0 2rem;
185
+ display: flex;
186
+ justify-content: space-between;
187
+ align-items: center;
188
+ }}
189
+
190
+ .nav-logo {{
191
+ font-size: 1.5rem;
192
+ font-weight: bold;
193
+ color: white;
194
+ text-decoration: none;
195
+ }}
196
+
197
+ .nav-menu {{
198
+ display: flex;
199
+ list-style: none;
200
+ gap: 2rem;
201
+ }}
202
+
203
+ .nav-link {{
204
+ color: white;
205
+ text-decoration: none;
206
+ transition: opacity 0.3s ease;
207
+ }}
208
+
209
+ .nav-link:hover {{
210
+ opacity: 0.8;
211
+ }}
212
+
213
+ /* Hero Section */
214
+ .hero {{
215
+ margin-top: 80px;
216
+ padding: 6rem 2rem;
217
+ background: linear-gradient(135deg, var(--primary-color), var(--secondary-color));
218
+ color: white;
219
+ text-align: center;
220
+ }}
221
+
222
+ .hero h1 {{
223
+ font-size: 3rem;
224
+ margin-bottom: 1rem;
225
+ animation: fadeInUp 1s ease;
226
+ }}
227
+
228
+ .hero p {{
229
+ font-size: 1.2rem;
230
+ margin-bottom: 2rem;
231
+ animation: fadeInUp 1s ease 0.2s both;
232
+ }}
233
+
234
+ .cta-button {{
235
+ display: inline-block;
236
+ padding: 1rem 2rem;
237
+ background: var(--accent-color);
238
+ color: white;
239
+ text-decoration: none;
240
+ border-radius: 50px;
241
+ font-weight: bold;
242
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
243
+ animation: fadeInUp 1s ease 0.4s both;
244
+ }}
245
+
246
+ .cta-button:hover {{
247
+ transform: translateY(-2px);
248
+ box-shadow: 0 10px 20px rgba(0,0,0,0.2);
249
+ }}
250
+
251
+ /* Features Section */
252
+ .features {{
253
+ padding: 4rem 2rem;
254
+ max-width: 1200px;
255
+ margin: 0 auto;
256
+ }}
257
+
258
+ .features h2 {{
259
+ text-align: center;
260
+ font-size: 2.5rem;
261
+ margin-bottom: 3rem;
262
+ color: var(--primary-color);
263
+ }}
264
+
265
+ .feature-grid {{
266
+ display: grid;
267
+ grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
268
+ gap: 2rem;
269
+ }}
270
+
271
+ .feature-card {{
272
+ background: white;
273
+ padding: 2rem;
274
+ border-radius: 10px;
275
+ box-shadow: 0 5px 15px rgba(0,0,0,0.1);
276
+ text-align: center;
277
+ transition: transform 0.3s ease;
278
+ }}
279
+
280
+ .feature-card:hover {{
281
+ transform: translateY(-5px);
282
+ }}
283
+
284
+ .feature-icon {{
285
+ font-size: 3rem;
286
+ color: var(--primary-color);
287
+ margin-bottom: 1rem;
288
+ }}
289
+
290
+ /* Footer */
291
+ .footer {{
292
+ background: var(--secondary-color);
293
+ color: white;
294
+ text-align: center;
295
+ padding: 2rem;
296
+ }}
297
+
298
+ /* Animations */
299
+ @keyframes fadeInUp {{
300
+ from {{
301
+ opacity: 0;
302
+ transform: translateY(30px);
303
+ }}
304
+ to {{
305
+ opacity: 1;
306
+ transform: translateY(0);
307
+ }}
308
+ }}
309
+
310
+ /* Responsive Design */
311
+ @media (max-width: 768px) {{
312
+ .nav-menu {{
313
+ flex-direction: column;
314
+ gap: 1rem;
315
+ }}
316
+
317
+ .hero h1 {{
318
+ font-size: 2rem;
319
+ }}
320
+
321
+ .feature-grid {{
322
+ grid-template-columns: 1fr;
323
+ }}
324
+ }}"""
325
+
326
+ return css
327
+
328
+ def _generate_js(self, requirements: Dict) -> str:
329
+ """Generate JavaScript functionality"""
330
+ js = """// Website JavaScript
331
+ document.addEventListener('DOMContentLoaded', function() {
332
+ // Smooth scrolling for navigation links
333
+ const navLinks = document.querySelectorAll('.nav-link');
334
+ navLinks.forEach(link => {
335
+ link.addEventListener('click', function(e) {
336
+ if (this.getAttribute('href').startsWith('#')) {
337
+ e.preventDefault();
338
+ const target = document.querySelector(this.getAttribute('href'));
339
+ if (target) {
340
+ target.scrollIntoView({
341
+ behavior: 'smooth'
342
+ });
343
+ }
344
+ }
345
+ });
346
+ });
347
+
348
+ // Mobile menu toggle
349
+ const mobileMenuBtn = document.querySelector('.mobile-menu-btn');
350
+ const navMenu = document.querySelector('.nav-menu');
351
+
352
+ if (mobileMenuBtn) {
353
+ mobileMenuBtn.addEventListener('click', function() {
354
+ navMenu.classList.toggle('active');
355
+ });
356
+ }
357
+
358
+ // Scroll animations
359
+ const observerOptions = {
360
+ threshold: 0.1,
361
+ rootMargin: '0px 0px -50px 0px'
362
+ };
363
+
364
+ const observer = new IntersectionObserver(function(entries) {
365
+ entries.forEach(entry => {
366
+ if (entry.isIntersecting) {
367
+ entry.target.style.opacity = '1';
368
+ entry.target.style.transform = 'translateY(0)';
369
+ }
370
+ });
371
+ }, observerOptions);
372
+
373
+ // Observe feature cards
374
+ const featureCards = document.querySelectorAll('.feature-card');
375
+ featureCards.forEach(card => {
376
+ card.style.opacity = '0';
377
+ card.style.transform = 'translateY(20px)';
378
+ card.style.transition = 'opacity 0.5s ease, transform 0.5s ease';
379
+ observer.observe(card);
380
+ });
381
+
382
+ // Form validation
383
+ const forms = document.querySelectorAll('form');
384
+ forms.forEach(form => {
385
+ form.addEventListener('submit', function(e) {
386
+ e.preventDefault();
387
+
388
+ const formData = new FormData(form);
389
+ const data = Object.fromEntries(formData);
390
+
391
+ // Simple validation
392
+ let isValid = true;
393
+ const requiredFields = form.querySelectorAll('[required]');
394
+
395
+ requiredFields.forEach(field => {
396
+ if (!field.value.trim()) {
397
+ isValid = false;
398
+ field.classList.add('error');
399
+ } else {
400
+ field.classList.remove('error');
401
+ }
402
+ });
403
+
404
+ if (isValid) {
405
+ // Show success message
406
+ showMessage('Form submitted successfully!', 'success');
407
+ form.reset();
408
+ } else {
409
+ showMessage('Please fill in all required fields.', 'error');
410
+ }
411
+ });
412
+ });
413
+
414
+ // Utility function to show messages
415
+ function showMessage(message, type) {
416
+ const messageDiv = document.createElement('div');
417
+ messageDiv.className = `message ${type}`;
418
+ messageDiv.textContent = message;
419
+ messageDiv.style.cssText = `
420
+ position: fixed;
421
+ top: 20px;
422
+ right: 20px;
423
+ padding: 1rem 2rem;
424
+ border-radius: 5px;
425
+ color: white;
426
+ z-index: 10000;
427
+ animation: slideIn 0.3s ease;
428
+ `;
429
+
430
+ if (type === 'success') {
431
+ messageDiv.style.background = '#4CAF50';
432
+ } else {
433
+ messageDiv.style.background = '#f44336';
434
+ }
435
+
436
+ document.body.appendChild(messageDiv);
437
+
438
+ setTimeout(() => {
439
+ messageDiv.remove();
440
+ }, 3000);
441
+ }
442
+ });
443
+
444
+ // Add slide-in animation
445
+ const style = document.createElement('style');
446
+ style.textContent = `
447
+ @keyframes slideIn {
448
+ from {
449
+ transform: translateX(100%);
450
+ opacity: 0;
451
+ }
452
+ to {
453
+ transform: translateX(0);
454
+ opacity: 1;
455
+ }
456
+ }
457
+
458
+ .message {
459
+ animation: slideIn 0.3s ease;
460
+ }
461
+
462
+ .form-input.error {
463
+ border-color: #f44336;
464
+ }
465
+ `;
466
+ document.head.appendChild(style);"""
467
+
468
+ return js
469
+
470
+ def _generate_navigation(self, requirements: Dict) -> str:
471
+ """Generate navigation HTML"""
472
+ return f"""<nav class="navbar">
473
+ <div class="nav-container">
474
+ <a href="#" class="nav-logo">
475
+ <i class="fas fa-rocket"></i> {requirements['type'].title()}
476
+ </a>
477
+ <ul class="nav-menu">
478
+ <li><a href="#home" class="nav-link">Home</a></li>
479
+ <li><a href="#features" class="nav-link">Features</a></li>
480
+ <li><a href="#about" class="nav-link">About</a></li>
481
+ <li><a href="#contact" class="nav-link">Contact</a></li>
482
+ </ul>
483
+ <button class="mobile-menu-btn">
484
+ <i class="fas fa-bars"></i>
485
+ </button>
486
+ </div>
487
+ </nav>"""
488
+
489
+ def _generate_hero_section(self, requirements: Dict) -> str:
490
+ """Generate hero section HTML"""
491
+ return f"""<section class="hero" id="home">
492
+ <div class="hero-content">
493
+ <h1>Welcome to Your {requirements['type'].title()}</h1>
494
+ <p>A modern, responsive website built with AI-powered technology</p>
495
+ <a href="#features" class="cta-button">Get Started</a>
496
+ </div>
497
+ </section>"""
498
+
499
+ def _generate_features_section(self, requirements: Dict) -> str:
500
+ """Generate features section HTML"""
501
+ features = requirements.get("features", ["responsive", "modern"])
502
+
503
+ feature_html = """<section class="features" id="features">
504
+ <h2>Features</h2>
505
+ <div class="feature-grid">"""
506
+
507
+ feature_icons = {
508
+ "responsive": "fas fa-mobile-alt",
509
+ "modern": "fas fa-paint-brush",
510
+ "gallery": "fas fa-images",
511
+ "contact": "fas fa-envelope",
512
+ "navigation": "fas fa-compass",
513
+ "search": "fas fa-search",
514
+ "animation": "fas fa-magic",
515
+ "dark mode": "fas fa-moon"
516
+ }
517
+
518
+ for feature in features[:6]: # Limit to 6 features
519
+ icon = feature_icons.get(feature, "fas fa-star")
520
+ feature_html += f"""
521
+ <div class="feature-card">
522
+ <div class="feature-icon">
523
+ <i class="{icon}"></i>
524
+ </div>
525
+ <h3>{feature.title()}</h3>
526
+ <p>Experience the power of {feature} functionality in our modern website.</p>
527
+ </div>"""
528
+
529
+ feature_html += """
530
+ </div>
531
+ </section>"""
532
+
533
+ return feature_html
534
+
535
+ def _generate_content_sections(self, requirements: Dict) -> str:
536
+ """Generate additional content sections"""
537
+ sections = ""
538
+
539
+ if "about" in requirements.get("features", []):
540
+ sections += """
541
+ <section class="about" id="about">
542
+ <div class="container">
543
+ <h2>About Us</h2>
544
+ <p>We are dedicated to creating amazing web experiences that combine beautiful design with powerful functionality.</p>
545
+ </div>
546
+ </section>"""
547
+
548
+ if "contact" in requirements.get("features", []):
549
+ sections += """
550
+ <section class="contact" id="contact">
551
+ <div class="container">
552
+ <h2>Get In Touch</h2>
553
+ <form class="contact-form">
554
+ <input type="text" placeholder="Your Name" required>
555
+ <input type="email" placeholder="Your Email" required>
556
+ <textarea placeholder="Your Message" rows="5" required></textarea>
557
+ <button type="submit" class="cta-button">Send Message</button>
558
+ </form>
559
+ </div>
560
+ </section>"""
561
+
562
+ return sections
563
+
564
+ def _generate_footer(self, requirements: Dict) -> str:
565
+ """Generate footer HTML"""
566
+ return f"""<footer class="footer">
567
+ <div class="container">
568
+ <p>&copy; 2024 {requirements['type'].title()}. Built with AI Website Builder.</p>
569
+ <div class="social-links">
570
+ <a href="#"><i class="fab fa-facebook"></i></a>
571
+ <a href="#"><i class="fab fa-twitter"></i></a>
572
+ <a href="#"><i class="fab fa-linkedin"></i></a>
573
+ <a href="#"><i class="fab fa-github"></i></a>
574
+ </div>
575
+ </div>
576
+ </footer>"""
577
+
578
+ def _generate_readme(self, requirements: Dict, project_name: str) -> str:
579
+ """Generate README.md file"""
580
+ return f"""# {project_name.title()}
581
+
582
+ A modern {requirements['type']} website built with AI Website Builder.
583
+
584
+ ## Features
585
+
586
+ {chr(10).join(f"- {feature.title()}" for feature in requirements.get('features', []))}
587
+
588
+ ## Technologies Used
589
+
590
+ - HTML5
591
+ - CSS3
592
+ - JavaScript (ES6+)
593
+ - Responsive Design
594
+ - Font Awesome Icons
595
+
596
+ ## Getting Started
597
+
598
+ 1. Clone or download this project
599
+ 2. Open `index.html` in your web browser
600
+ 3. Or serve it with a local server:
601
+ python -m http.server 8000
602
+
603
+ ## Customization
604
+
605
+ - Edit `styles/main.css` to modify the appearance
606
+ - Edit `scripts/main.js` to add functionality
607
+ - Edit `index.html` to modify the structure
608
+
609
+ ## License
610
+
611
+ MIT License - feel free to use this project for personal or commercial purposes.
612
+
613
+ ---
614
+
615
+ Built with [AI Website Builder](https://github.com/ai-website-builder)
616
+ """
617
+
618
+ def _generate_package_json(self, requirements: Dict) -> str:
619
+ """Generate package.json file"""
620
+ return json.dumps({
621
+ "name": "ai-generated-website",
622
+ "version": "1.0.0",
623
+ "description": f"A {requirements['type']} website built with AI",
624
+ "main": "index.html",
625
+ "scripts": {
626
+ "start": "python -m http.server 8000",
627
+ "dev": "python -m http.server 8000"
628
+ },
629
+ "keywords": ["website", "html", "css", "javascript", "ai-generated"],
630
+ "author": "AI Website Builder",
631
+ "license": "MIT"
632
+ }, indent=2)
633
+
634
+ def _get_color_palette(self, scheme: str) -> Dict[str, str]:
635
+ """Get color palette based on scheme"""
636
+ palettes = {
637
+ "blue": {
638
+ "primary": "#3498db",
639
+ "secondary": "#2980b9",
640
+ "accent": "#e74c3c",
641
+ "text": "#2c3e50",
642
+ "background": "#ecf0f1",
643
+ "light_bg": "#ffffff"
644
+ },
645
+ "red": {
646
+ "primary": "#e74c3c",
647
+ "secondary": "#c0392b",
648
+ "accent": "#f39c12",
649
+ "text": "#2c3e50",
650
+ "background": "#ecf0f1",
651
+ "light_bg": "#ffffff"
652
+ },
653
+ "green": {
654
+ "primary": "#27ae60",
655
+ "secondary": "#229954",
656
+ "accent": "#f39c12",
657
+ "text": "#2c3e50",
658
+ "background": "#ecf0f1",
659
+ "light_bg": "#ffffff"
660
+ },
661
+ "purple": {
662
+ "primary": "#9b59b6",
663
+ "secondary": "#8e44ad",
664
+ "accent": "#e74c3c",
665
+ "text": "#2c3e50",
666
+ "background": "#ecf0f1",
667
+ "light_bg": "#ffffff"
668
+ },
669
+ "dark": {
670
+ "primary": "#34495e",
671
+ "secondary": "#2c3e50",
672
+ "accent": "#3498db",
673
+ "text": "#ecf0f1",
674
+ "background": "#1a1a1a",
675
+ "light_bg": "#2c3e50"
676
+ },
677
+ "light": {
678
+ "primary": "#95a5a6",
679
+ "secondary": "#7f8c8d",
680
+ "accent": "#3498db",
681
+ "text": "#2c3e50",
682
+ "background": "#ffffff",
683
+ "light_bg": "#ecf0f1"
684
+ }
685
+ }
686
+ return palettes.get(scheme, palettes["blue"])
687
+
688
+ def _load_templates(self) -> Dict:
689
+ """Load website templates"""
690
+ return {}
691
+
692
+ def _load_components(self) -> Dict:
693
+ """Load reusable components"""
694
+ return {}
695
+
696
+ def _generate_react_files(self, requirements: Dict) -> Dict[str, str]:
697
+ """Generate React-specific files"""
698
+ return {
699
+ "src/App.js": """import React from 'react';
700
+ import './App.css';
701
+
702
+ function App() {
703
+ return (
704
+ <div className="App">
705
+ <header className="App-header">
706
+ <h1>React Website</h1>
707
+ <p>Welcome to your AI-generated React application!</p>
708
+ </header>
709
+ </div>
710
+ );
711
+ }
712
+
713
+ export default App;""",
714
+ "src/App.css": """.App {
715
+ text-align: center;
716
+ }
717
+
718
+ .App-header {
719
+ background-color: #282c34;
720
+ padding: 20px;
721
+ color: white;
722
+ min-height: 100vh;
723
+ display: flex;
724
+ flex-direction: column;
725
+ align-items: center;
726
+ justify-content: center;
727
+ }""",
728
+ "src/index.js": """import React from 'react';
729
+ import ReactDOM from 'react-dom';
730
+ import './index.css';
731
+ import App from './App';
732
+
733
+ ReactDOM.render(
734
+ <React.StrictMode>
735
+ <App />
736
+ </React.StrictMode>,
737
+ document.getElementById('root')
738
+ );""",
739
+ "src/index.css": """body {
740
+ margin: 0;
741
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
742
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
743
+ sans-serif;
744
+ }""",
745
+ "public/index.html": """<!DOCTYPE html>
746
+ <html lang="en">
747
+ <head>
748
+ <meta charset="utf-8" />
749
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
750
+ <title>React App</title>
751
+ </head>
752
+ <body>
753
+ <div id="root"></div>
754
+ </body>
755
+ </html>"""
756
+ }
757
+
758
+ def _generate_vue_files(self, requirements: Dict) -> Dict[str, str]:
759
+ """Generate Vue-specific files"""
760
+ return {
761
+ "src/App.vue": """<template>
762
+ <div id="app">
763
+ <header>
764
+ <h1>Vue Website</h1>
765
+ <p>Welcome to your AI-generated Vue application!</p>
766
+ </header>
767
+ </div>
768
+ </template>
769
+
770
+ <script>
771
+ export default {
772
+ name: 'App'
773
+ }
774
+ </script>
775
+
776
+ <style>
777
+ #app {
778
+ font-family: Avenir, Helvetica, Arial, sans-serif;
779
+ text-align: center;
780
+ color: #2c3e50;
781
+ }
782
+
783
+ header {
784
+ background-color: #42b983;
785
+ color: white;
786
+ padding: 20px;
787
+ }
788
+ </style>""",
789
+ "src/main.js": """import Vue from 'vue'
790
+ import App from './App.vue'
791
+
792
+ new Vue({
793
+ render: h => h(App),
794
+ }).$mount('#app')""",
795
+ "public/index.html": """<!DOCTYPE html>
796
+ <html lang="en">
797
+ <head>
798
+ <meta charset="utf-8">
799
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
800
+ <meta name="viewport" content="width=device-width,initial-scale=1.0">
801
+ <title>Vue App</title>
802
+ </head>
803
+ <body>
804
+ <div id="app"></div>
805
+ </body>
806
+ </html>"""
807
+ }
808
+
809
+ def _generate_page(self, page: str, requirements: Dict) -> Dict[str, str]:
810
+ """Generate additional pages"""
811
+ page_content = f"""<!DOCTYPE html>
812
+ <html lang="en">
813
+ <head>
814
+ <meta charset="UTF-8">
815
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
816
+ <title>{page.title()} - {requirements['type'].title()}</title>
817
+ <link rel="stylesheet" href="styles/main.css">
818
+ </head>
819
+ <body>
820
+ <nav class="navbar">
821
+ <div class="nav-container">
822
+ <a href="index.html" class="nav-logo">
823
+ <i class="fas fa-rocket"></i> {requirements['type'].title()}
824
+ </a>
825
+ <ul class="nav-menu">
826
+ <li><a href="index.html" class="nav-link">Home</a></li>
827
+ <li><a href="{page.lower()}.html" class="nav-link">{page.title()}</a></li>
828
+ </ul>
829
+ </div>
830
+ </nav>
831
+
832
+ <main style="margin-top: 80px; padding: 2rem;">
833
+ <h1>{page.title()}</h1>
834
+ <p>This is the {page.lower()} page of your website.</p>
835
+ </main>
836
+
837
+ <footer class="footer">
838
+ <p>&copy; 2024 {requirements['type'].title()}. All rights reserved.</p>
839
+ </footer>
840
+ </body>
841
+ </html>"""
842
+
843
+ return {f"{page.lower()}.html": page_content}
844
+
845
+ def _generate_assets(self, requirements: Dict) -> Dict[str, str]:
846
+ """Generate asset files"""
847
+ assets = {}
848
+
849
+ # Generate favicon
850
+ assets["favicon.ico"] = "data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A"
851
+
852
+ # Generate robots.txt
853
+ assets["robots.txt"] = """User-agent: *
854
+ Allow: /
855
+
856
+ Sitemap: https://yoursite.com/sitemap.xml"""
857
+
858
+ return assets
requirements.txt ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ gradio>=4.0.0
2
+ pathlib2>=2.3.0
3
+ Pillow>=9.0.0
4
+ requests>=2.28.0
5
+ python-multipart>=0.0.5
6
+ aiofiles>=22.1.0
7
+ watchdog>=2.1.0
8
+ Jinja2>=3.1.0
9
+ PyYAML>=6.0
10
+
11
+ This AI Website Builder provides:
12
+
13
+ 🚀 **Core Features:**
14
+ - Complete website generation with multiple files
15
+ - Powered by Qwen AI model logic
16
+ - Automatic live preview with hot reload
17
+ - Code editor with syntax highlighting
18
+ - Multi-file download as ZIP
19
+ - Project history tracking
20
+
21
+ 📁 **Supported Files:**
22
+ - HTML, CSS, JavaScript
23
+ - React/Vue components
24
+ - JSON, Markdown, YAML
25
+ - Images and assets
26
+ - Configuration files
27
+
28
+ ✨ **Advanced Features:**
29
+ - Multiple framework support (React, Vue, Vanilla)
30
+ - Responsive design generation
31
+ - Color scheme customization
32
+ - Component-based architecture
33
+ - SEO optimization
34
+ - Performance optimization
35
+
36
+ 🎨 **User Interface:**
37
+ - Tabbed interface for different functions
38
+ - Real-time preview
39
+ - Interactive code editor
40
+ - Project management
41
+ - Settings and customization
42
+
43
+ The builder creates complete, production-ready websites with all necessary files, including HTML structure, CSS styling, JavaScript functionality, README documentation, and package configuration files. Each generated website is fully responsive and includes modern features like smooth scrolling, animations, and form validation.
utils.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import json
3
+ import zipfile
4
+ import shutil
5
+ import subprocess
6
+ import tempfile
7
+ from pathlib import Path
8
+ from typing import Dict, List, Optional
9
+ import threading
10
+ import time
11
+ from http.server import HTTPServer, SimpleHTTPRequestHandler
12
+ import socket
13
+
14
+ class FileHandler:
15
+ """Handle file operations for website projects"""
16
+
17
+ def __init__(self):
18
+ self.projects_dir = Path("projects")
19
+ self.projects_dir.mkdir(exist_ok=True)
20
+
21
+ def create_project(self, project_name: str, files: Dict[str, str]) -> Path:
22
+ """Create a new project with generated files"""
23
+ project_path = self.projects_dir / project_name
24
+
25
+ # Remove existing project if it exists
26
+ if project_path.exists():
27
+ shutil.rmtree(project_path)
28
+
29
+ project_path.mkdir(exist_ok=True)
30
+
31
+ # Write all files
32
+ for file_path, content in files.items():
33
+ full_path = project_path / file_path
34
+ full_path.parent.mkdir(parents=True, exist_ok=True)
35
+
36
+ with open(full_path, 'w', encoding='utf-8') as f:
37
+ f.write(content)
38
+
39
+ return project_path
40
+
41
+ def get_project_files(self, project_path: Path) -> Dict[str, str]:
42
+ """Get all files in a project"""
43
+ files = {}
44
+ if project_path.exists():
45
+ for file_path in project_path.rglob("*"):
46
+ if file_path.is_file():
47
+ relative_path = file_path.relative_to(project_path)
48
+ files[str(relative_path)] = self.get_file_content(project_path, str(relative_path))
49
+ return files
50
+
51
+ def get_file_content(self, project_path: Path, filename: str) -> str:
52
+ """Get content of a specific file"""
53
+ file_path = project_path / filename
54
+ if file_path.exists():
55
+ with open(file_path, 'r', encoding='utf-8') as f:
56
+ return f.read()
57
+ return ""
58
+
59
+ def create_zip(self, project_path: Path) -> str:
60
+ """Create a ZIP file of the project"""
61
+ zip_path = f"{project_path}.zip"
62
+
63
+ with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
64
+ for file_path in project_path.rglob("*"):
65
+ if file_path.is_file():
66
+ arcname = file_path.relative_to(project_path.parent)
67
+ zipf.write(file_path, arcname)
68
+
69
+ return zip_path
70
+
71
+ class PreviewManager:
72
+ """Manage live preview of websites"""
73
+
74
+ def __init__(self):
75
+ self.active_servers = {}
76
+ self.port_counter = 8000
77
+
78
+ def get_free_port(self) -> int:
79
+ """Find a free port for the preview server"""
80
+ while True:
81
+ try:
82
+ with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
83
+ s.bind(('localhost', self.port_counter))
84
+ return self.port_counter
85
+ except OSError:
86
+ self.port_counter += 1
87
+
88
+ def create_preview(self, project_path: Path) -> str:
89
+ """Create a live preview server for the project"""
90
+ port = self.get_free_port()
91
+
92
+ # Start server in a separate thread
93
+ server_thread = threading.Thread(
94
+ target=self._run_server,
95
+ args=(project_path, port),
96
+ daemon=True
97
+ )
98
+ server_thread.start()
99
+
100
+ # Give server time to start
101
+ time.sleep(0.5)
102
+
103
+ self.active_servers[str(project_path)] = port
104
+ return f"http://localhost:{port}"
105
+
106
+ def update_preview(self, project_path: Path) -> str:
107
+ """Update the preview (server already running)"""
108
+ if str(project_path) in self.active_servers:
109
+ port = self.active_servers[str(project_path)]
110
+ return f"http://localhost:{port}"
111
+ return self.create_preview(project_path)
112
+
113
+ def _run_server(self, project_path: Path, port: int):
114
+ """Run HTTP server for preview"""
115
+ os.chdir(project_path)
116
+
117
+ class CustomHandler(SimpleHTTPRequestHandler):
118
+ def __init__(self, *args, **kwargs):
119
+ super().__init__(*args, directory=project_path, **kwargs)
120
+
121
+ def end_headers(self):
122
+ # Add CORS headers
123
+ self.send_header('Access-Control-Allow-Origin', '*')
124
+ self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
125
+ self.send_header('Access-Control-Allow-Headers', 'Content-Type')
126
+ super().end_headers()
127
+
128
+ try:
129
+ httpd = HTTPServer(('localhost', port), CustomHandler)
130
+ httpd.serve_forever()
131
+ except Exception as e:
132
+ print(f"Server error: {e}")
133
+
134
+ def detect_file_language(filename: str) -> str:
135
+ """Detect programming language from file extension"""
136
+ ext = Path(filename).suffix.lower()
137
+ lang_map = {
138
+ '.html': 'html',
139
+ '.css': 'css',
140
+ '.js': 'javascript',
141
+ '.json': 'json',
142
+ '.md': 'markdown',
143
+ '.py': 'python',
144
+ '.jsx': 'jsx',
145
+ '.tsx': 'typescript',
146
+ '.ts': 'typescript',
147
+ '.xml': 'xml',
148
+ '.yaml': 'yaml',
149
+ '.yml': 'yaml',
150
+ '.sql': 'sql',
151
+ '.php': 'php',
152
+ '.rb': 'ruby',
153
+ '.go': 'go',
154
+ '.java': 'java',
155
+ '.c': 'c',
156
+ '.cpp': 'cpp',
157
+ '.h': 'c',
158
+ '.hpp': 'cpp',
159
+ '.scss': 'scss',
160
+ '.sass': 'sass',
161
+ '.less': 'less',
162
+ '.vue': 'vue',
163
+ '.svelte': 'svelte'
164
+ }
165
+ return lang_map.get(ext, 'text')
166
+
167
+ def format_file_size(size_bytes: int) -> str:
168
+ """Format file size in human readable format"""
169
+ if size_bytes == 0:
170
+ return "0B"
171
+ size_names = ["B", "KB", "MB", "GB"]
172
+ i = 0
173
+ while size_bytes >= 1024 and i < len(size_names) - 1:
174
+ size_bytes /= 1024.0
175
+ i += 1
176
+ return f"{size_bytes:.1f}{size_names[i]}"