codeboosterstech commited on
Commit
562261d
Β·
verified Β·
1 Parent(s): b0000b8

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +562 -269
app.py CHANGED
@@ -1,6 +1,7 @@
1
  """
2
- Main application file for Hugging Face Space Creator
3
- Enterprise-grade Gradio application for converting Python code to deployable Gradio apps
 
4
  """
5
 
6
  import gradio as gr
@@ -33,7 +34,7 @@ SUPPORTED_EXTENSIONS = ['.py', '.ipynb', '.txt']
33
 
34
 
35
  class SpaceCreatorApp:
36
- """Main application class for Hugging Face Space Creator"""
37
 
38
  def __init__(self):
39
  self.temp_files = []
@@ -152,10 +153,10 @@ class SpaceCreatorApp:
152
  "info": "β„Ή"
153
  }
154
  colors = {
155
- "success": "#10B981",
156
- "error": "#EF4444",
157
- "warning": "#F59E0B",
158
- "info": "#3B82F6"
159
  }
160
 
161
  return f'''
@@ -172,117 +173,264 @@ def create_app():
172
  """Create the Gradio application interface"""
173
  app = SpaceCreatorApp()
174
 
175
- # Use a clean, professional theme
176
  theme = gr.themes.Base(
177
- primary_hue="blue",
178
  secondary_hue="gray",
179
  neutral_hue="gray",
180
  font=("Inter", "Segoe UI", "Roboto", "Helvetica", "Arial", "sans-serif")
181
  )
182
 
183
  with gr.Blocks(
184
- title="Hugging Face Space Creator",
185
  theme=theme,
186
  css="""
187
- /* Simple, clean CSS */
188
  .gradio-container {
189
- max-width: 1200px !important;
190
  margin: 20px auto !important;
191
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
 
192
  }
193
 
194
  body {
195
- background: #f8fafc;
196
  }
197
 
198
- /* Header */
199
- .header {
200
- background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
201
  color: white;
202
- padding: 2rem;
203
- border-radius: 8px 8px 0 0;
204
- margin-bottom: 20px;
 
 
 
205
  }
206
 
207
- .header h1 {
208
- margin: 0;
209
- font-size: 1.875rem;
210
- font-weight: 600;
 
 
 
 
 
 
211
  }
212
 
213
- .header p {
214
- margin: 0.5rem 0 0 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
215
  color: #cbd5e1;
216
- font-size: 1rem;
217
  }
218
 
219
- /* Layout */
220
- .main-layout {
221
  display: flex;
222
- gap: 20px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  margin-top: 20px;
224
  }
225
 
226
- .sidebar {
227
- flex: 1;
 
228
  background: white;
229
- padding: 1.5rem;
230
- border-radius: 8px;
231
- border: 1px solid #e2e8f0;
 
 
232
  }
233
 
234
- .content {
235
- flex: 3;
236
- background: white;
237
- padding: 1.5rem;
238
- border-radius: 8px;
239
- border: 1px solid #e2e8f0;
 
240
  }
241
 
242
  /* Steps */
243
- .step {
244
- padding: 1rem;
 
 
 
 
 
 
 
245
  margin-bottom: 0.75rem;
246
- background: #f8fafc;
247
- border-radius: 6px;
248
- border: 1px solid #e2e8f0;
 
 
249
  }
250
 
251
- .step.active {
252
- background: #eff6ff;
253
- border-color: #3b82f6;
254
- border-left: 4px solid #3b82f6;
 
 
 
 
 
255
  }
256
 
257
  .step-number {
258
- display: inline-block;
259
- width: 24px;
260
- height: 24px;
261
- background: #cbd5e1;
262
- color: #475569;
263
  border-radius: 50%;
264
- text-align: center;
265
- line-height: 24px;
266
- font-size: 0.875rem;
267
- font-weight: 500;
268
- margin-right: 0.75rem;
 
 
269
  }
270
 
271
- .step.active .step-number {
272
- background: #3b82f6;
273
- color: white;
 
 
 
 
274
  }
275
 
276
  .step-title {
277
  font-weight: 600;
278
- color: #1e293b;
 
 
 
 
 
279
  }
280
 
281
  .step-description {
282
  font-size: 0.875rem;
283
- color: #64748b;
284
- margin-top: 0.25rem;
285
- margin-left: 2.5rem;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
286
  }
287
 
288
  /* Form Elements */
@@ -290,338 +438,459 @@ def create_app():
290
  margin-bottom: 1.5rem;
291
  }
292
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
293
  input, textarea, select {
294
  width: 100%;
295
- padding: 0.75rem 1rem;
296
- border: 1px solid #cbd5e1;
297
- border-radius: 6px;
298
- font-size: 0.875rem;
 
 
 
299
  }
300
 
301
  input:focus, textarea:focus, select:focus {
302
  outline: none;
303
- border-color: #3b82f6;
304
- box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
 
 
 
 
305
  }
306
 
307
  /* Buttons */
308
  button {
309
- padding: 0.75rem 1.5rem !important;
310
- border-radius: 6px !important;
311
  font-weight: 500 !important;
 
 
 
 
 
312
  }
313
 
314
  button.primary {
315
- background: #3b82f6 !important;
316
- color: white !important;
317
- border: none !important;
318
  }
319
 
320
  button.primary:hover {
321
- background: #2563eb !important;
 
322
  }
323
 
324
  button.secondary {
325
  background: white !important;
326
- color: #475569 !important;
327
- border: 1px solid #cbd5e1 !important;
328
  }
329
 
330
  button.secondary:hover {
331
- background: #f8fafc !important;
 
332
  }
333
 
334
  /* Tabs */
 
 
 
 
 
335
  .tab-nav button {
336
  padding: 0.75rem 1.5rem !important;
337
  background: none !important;
338
  border: none !important;
339
- border-bottom: 2px solid transparent !important;
340
- color: #64748b !important;
 
341
  }
342
 
343
  .tab-nav button.selected {
344
- color: #3b82f6 !important;
345
- border-bottom-color: #3b82f6 !important;
346
  font-weight: 600 !important;
347
  }
348
 
349
  /* Code Editor */
350
  #code_editor {
351
- font-family: 'JetBrains Mono', 'Consolas', monospace !important;
352
- font-size: 0.875rem !important;
 
353
  background: #f8fafc !important;
354
  border: 1px solid #e2e8f0 !important;
355
- border-radius: 6px !important;
356
- padding: 1rem !important;
357
  }
358
 
359
  /* Status Messages */
360
  .status-message {
361
- padding: 1rem;
362
- border-radius: 6px;
363
- margin: 1rem 0;
364
  border-left: 4px solid;
365
  background: #f8fafc;
366
- font-size: 0.875rem;
 
 
 
367
  }
368
 
369
  .status-message.success {
370
- border-left-color: #10b981;
371
  background: #f0fdf4;
372
  }
373
 
374
  .status-message.error {
375
- border-left-color: #ef4444;
376
  background: #fef2f2;
377
  }
378
 
379
  .status-message.warning {
380
- border-left-color: #f59e0b;
381
  background: #fffbeb;
382
  }
383
 
384
  .status-message.info {
385
- border-left-color: #3b82f6;
386
  background: #eff6ff;
387
  }
388
 
389
  /* File Cards */
 
 
 
 
 
 
 
390
  .file-card {
391
- border: 1px solid #e2e8f0;
392
- border-radius: 6px;
393
- padding: 1rem;
394
- margin-bottom: 1rem;
395
  background: #f8fafc;
 
 
 
 
 
 
 
 
 
 
396
  }
397
 
398
  .file-card-title {
399
  font-weight: 600;
400
- color: #1e293b;
401
- margin-bottom: 0.5rem;
 
 
 
 
 
 
 
402
  }
403
 
404
  /* Error Message */
405
  .error-message {
406
- background: #fef2f2;
407
  border: 1px solid #fecaca;
408
- border-radius: 6px;
409
- padding: 1rem;
410
- margin: 1rem 0;
411
  }
412
 
413
  .error-message h4 {
414
- margin: 0 0 0.5rem 0;
415
  color: #dc2626;
 
 
 
 
 
 
 
 
416
  }
417
 
418
  .error-message ul {
419
  margin: 0;
420
- padding-left: 1.25rem;
421
  }
422
 
423
  .error-message li {
424
- margin-bottom: 0.25rem;
425
- color: #57534e;
426
  }
427
 
428
- /* Progress Bar */
429
- .progress-bar {
430
- height: 4px;
431
- background: #e2e8f0;
432
- border-radius: 2px;
433
- margin: 1rem 0;
434
- overflow: hidden;
435
  }
436
 
437
- .progress-fill {
438
- height: 100%;
439
- background: #3b82f6;
440
- width: 33.33%;
441
- transition: width 0.3s ease;
442
  }
443
 
444
- .progress-fill.step2 { width: 66.66%; }
445
- .progress-fill.step3 { width: 100%; }
 
 
 
 
 
 
 
446
 
447
- /* Tips Box */
448
- .tips-box {
449
- background: #eff6ff;
450
- border: 1px solid #bfdbfe;
451
- border-radius: 6px;
452
- padding: 1rem;
453
- margin-top: 1.5rem;
454
  }
455
 
456
- .tips-box h4 {
457
- margin: 0 0 0.75rem 0;
458
- color: #1e40af;
459
- font-size: 0.875rem;
460
- font-weight: 600;
461
  }
462
 
463
- .tip {
464
- display: flex;
465
- align-items: flex-start;
466
- gap: 0.75rem;
467
- margin-bottom: 0.75rem;
 
 
 
 
 
 
 
 
468
  }
469
 
470
- .tip:last-child {
471
- margin-bottom: 0;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
472
  }
473
 
474
- .tip-icon {
475
- color: #3b82f6;
476
- flex-shrink: 0;
477
- margin-top: 0.125rem;
 
478
  }
479
 
480
- .tip-text {
481
- font-size: 0.875rem;
482
- color: #374151;
483
- line-height: 1.5;
484
  }
485
  """
486
  ) as demo:
487
 
488
- # Add font
489
- gr.HTML('<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">')
 
 
 
490
 
491
- # Simple Header
492
  header_html = '''
493
- <div class="header">
494
- <h1>Space Creator</h1>
495
- <p>Convert Python code to deployable Gradio applications</p>
 
 
 
 
 
 
 
 
 
496
  </div>
497
  '''
498
  gr.HTML(header_html)
499
 
500
- # Progress Bar
501
- progress_html = '''
502
- <div class="progress-bar">
503
- <div class="progress-fill" id="progress-fill"></div>
504
- </div>
505
- '''
506
- gr.HTML(progress_html)
507
-
508
- with gr.Row(elem_classes="main-layout"):
509
  # Sidebar
510
- with gr.Column(scale=1, min_width=280, elem_classes="sidebar"):
511
  current_step = gr.State(1)
512
 
513
  # Steps
514
  steps_html = '''
515
- <div style="margin-bottom: 1.5rem;">
516
- <h3 style="margin: 0 0 1rem 0; font-size: 1rem; font-weight: 600; color: #1e293b;">
517
- Workflow Steps
518
- </h3>
519
- <div class="step active">
520
- <span class="step-number">1</span>
521
- <span class="step-title">Input Code</span>
522
- <div class="step-description">Provide your Python code</div>
523
  </div>
524
- <div class="step">
525
- <span class="step-number">2</span>
526
- <span class="step-title">Generate Files</span>
527
- <div class="step-description">Create Gradio app files</div>
 
 
528
  </div>
529
- <div class="step">
530
- <span class="step-number">3</span>
531
- <span class="step-title">Deploy</span>
532
- <div class="step-description">Deploy to Hugging Face</div>
 
 
533
  </div>
534
  </div>
535
- '''
536
- gr.HTML(steps_html)
537
 
538
- # Tips
539
- tips_html = '''
540
- <div class="tips-box">
541
- <h4>Quick Tips</h4>
542
- <div class="tip">
543
- <div class="tip-icon">β€’</div>
544
- <div class="tip-text">Ensure your code is well-structured for best results</div>
545
  </div>
546
- <div class="tip">
547
- <div class="tip-icon">β€’</div>
548
- <div class="tip-text">API keys are used securely and not stored</div>
549
  </div>
550
- <div class="tip">
551
- <div class="tip-icon">β€’</div>
552
- <div class="tip-text">One-click deployment to Hugging Face Spaces</div>
553
  </div>
554
  </div>
555
  '''
556
- gr.HTML(tips_html)
557
 
558
  # Main Content
559
- with gr.Column(scale=3, elem_classes="content"):
560
  # Step 1: Code Input
561
  with gr.Group(visible=True) as step1_group:
562
- gr.Markdown("### Step 1: Provide Your Code")
563
 
564
  with gr.Tabs():
565
- with gr.Tab("Upload File"):
566
  file_input = gr.File(
567
  label="Upload Python or Jupyter Notebook",
568
  file_types=SUPPORTED_EXTENSIONS,
569
- type="filepath"
 
570
  )
571
 
572
- with gr.Tab("Paste Code"):
573
  text_input = gr.Textbox(
574
  label="Python Code",
575
  lines=15,
576
- placeholder="# Paste your Python code here...\n# Example:\ndef add(a, b):\n return a + b",
577
  elem_id="code_editor"
578
  )
579
 
580
- gr.Markdown("### Step 2: API Configuration")
581
- groq_api_key = gr.Textbox(
582
- label="Groq API Key",
583
- type="password",
584
- placeholder="Enter your Groq API key (starts with gsk_)",
585
- info="Required for AI-powered conversion"
586
- )
 
 
 
 
587
 
588
  # API Guide
589
- with gr.Accordion("Need help creating API keys?", open=False):
590
  with gr.Tabs():
591
  with gr.Tab("Groq API Key"):
592
  gr.Markdown("""
593
- 1. Go to [Groq Console](https://console.groq.com)
594
- 2. Sign up or log in
 
595
  3. Navigate to **API Keys** section
596
  4. Click **Create API Key**
597
- 5. Copy the key (starts with `gsk_`)
598
- 6. Paste it in the field above
 
 
 
599
  """)
600
 
601
  with gr.Tab("Hugging Face Token"):
602
  gr.Markdown("""
603
- 1. Go to [Hugging Face](https://huggingface.co)
604
- 2. Click profile β†’ **Settings**
 
605
  3. Navigate to **Access Tokens**
606
  4. Click **New Token**
607
  5. Select token type: **Write**
608
- 6. Copy the token (starts with `hf_`)
609
  7. Paste it in Step 2
 
 
610
  """)
611
 
612
  convert_btn = gr.Button(
613
- "Convert Code",
614
  variant="primary",
615
- size="lg"
 
616
  )
617
 
618
  # Step 2: Generated Files
619
  with gr.Group(visible=False) as step2_group:
620
- gr.Markdown("### Step 2: Generated Files")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
621
 
622
  with gr.Row():
623
  with gr.Column():
624
- gr.Markdown("**app.py**")
625
  app_py_download = gr.File(
626
  label="Download app.py",
627
  file_types=[".py"],
@@ -629,7 +898,6 @@ def create_app():
629
  )
630
 
631
  with gr.Column():
632
- gr.Markdown("**requirements.txt**")
633
  requirements_download = gr.File(
634
  label="Download requirements.txt",
635
  file_types=[".txt"],
@@ -637,67 +905,80 @@ def create_app():
637
  )
638
 
639
  with gr.Column():
640
- gr.Markdown("**README.md**")
641
  readme_download = gr.File(
642
  label="Download README.md",
643
  file_types=[".md"],
644
  interactive=False
645
  )
646
 
647
- gr.Markdown("### Step 3: Deployment Options")
648
 
649
  with gr.Row():
650
  with gr.Column():
651
  hf_token = gr.Textbox(
652
  label="Hugging Face Token",
653
  type="password",
654
- placeholder="Enter your Hugging Face token (starts with hf_)",
655
- info="Required for deployment"
 
656
  )
657
 
658
  with gr.Column():
659
  space_name = gr.Textbox(
660
  label="Space Name",
661
- placeholder="my-gradio-app",
662
- info="Lowercase letters, numbers, and hyphens only"
 
663
  )
664
 
 
665
  deploy_mode = gr.Radio(
666
- choices=["Download Only", "Deploy to Hugging Face Space"],
667
- label="Select Action",
668
- value="Download Only"
 
669
  )
670
 
671
  with gr.Row():
672
- back_btn_step2 = gr.Button("Back", variant="secondary")
673
- deploy_btn = gr.Button("Proceed to Deployment", variant="primary")
674
 
675
  # Step 3: Deployment Results
676
  with gr.Group(visible=False) as step3_group:
677
- gr.Markdown("### Step 3: Deployment Complete")
 
 
 
 
 
 
 
 
 
678
 
679
  with gr.Row():
680
  with gr.Column(scale=2):
681
- gr.Markdown("**Complete Application Package**")
682
  full_package_download = gr.File(
683
- label="Download full package",
684
  file_types=[".zip"],
685
  interactive=False
686
  )
 
687
  with gr.Column(scale=1):
688
- gr.Markdown("**Next Steps**")
689
  gr.Markdown("""
690
- 1. Your app is now deployed
691
- 2. Visit your Hugging Face Space
692
- 3. Monitor deployment logs
693
- 4. Share your app with others
694
  """)
695
 
696
  deployment_status = gr.Markdown()
697
 
698
  with gr.Row():
699
- back_btn_step3 = gr.Button("Start New Project", variant="secondary")
700
- finish_btn = gr.Button("Finish", variant="primary")
701
 
702
  # Status output
703
  status_output = gr.HTML(
@@ -705,33 +986,41 @@ def create_app():
705
  elem_id="status_output"
706
  )
707
 
708
- # JavaScript for updating progress bar
 
 
 
 
 
 
 
 
 
709
  js_code = """
710
  <script>
711
- function updateProgress(step) {
712
- const progressFill = document.getElementById('progress-fill');
713
- progressFill.className = 'progress-fill';
714
- if (step === 2) progressFill.classList.add('step2');
715
- if (step === 3) progressFill.classList.add('step3');
716
-
717
- // Update steps in sidebar
718
- const steps = document.querySelectorAll('.step');
719
  steps.forEach((stepEl, index) => {
720
  stepEl.classList.remove('active');
721
- if (index + 1 === step) {
722
  stepEl.classList.add('active');
723
  }
724
  });
725
  }
 
 
 
 
 
726
  </script>
727
  """
728
  gr.HTML(js_code)
729
 
730
  # Event handlers
731
- def update_progress_bar(step):
732
  return f"""
733
  <script>
734
- updateProgress({step});
735
  </script>
736
  """
737
 
@@ -751,7 +1040,7 @@ def create_app():
751
  inputs=[current_step],
752
  outputs=[step1_group, step2_group, step3_group]
753
  ).then(
754
- fn=update_progress_bar,
755
  inputs=[current_step],
756
  outputs=[status_output]
757
  )
@@ -765,7 +1054,7 @@ def create_app():
765
  inputs=[current_step],
766
  outputs=[step1_group, step2_group, step3_group]
767
  ).then(
768
- fn=update_progress_bar,
769
  inputs=[current_step],
770
  outputs=[status_output]
771
  )
@@ -774,7 +1063,7 @@ def create_app():
774
  fn=lambda: (1, gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)),
775
  outputs=[current_step, step1_group, step2_group, step3_group]
776
  ).then(
777
- fn=update_progress_bar,
778
  inputs=[current_step],
779
  outputs=[status_output]
780
  )
@@ -787,7 +1076,7 @@ def create_app():
787
  inputs=None,
788
  outputs=None
789
  ).then(
790
- fn=update_progress_bar,
791
  inputs=[current_step],
792
  outputs=[status_output]
793
  )
@@ -802,16 +1091,20 @@ def create_app():
802
 
803
 
804
  if __name__ == "__main__":
805
- print("Starting Hugging Face Space Creator...")
806
- print("=" * 50)
807
- print("Enterprise-grade Python to Gradio App Converter")
808
- print("=" * 50)
 
 
 
809
 
810
  app = create_app()
811
  app.launch(
812
  server_name="0.0.0.0",
813
  server_port=7860,
814
  share=False,
815
- debug=True,
816
- favicon_path=None
 
817
  )
 
1
  """
2
+ Main application file for PyDeploy Studio
3
+ Professional Gradio application for converting Python code to deployable Gradio apps
4
+ Created by Veerakumar
5
  """
6
 
7
  import gradio as gr
 
34
 
35
 
36
  class SpaceCreatorApp:
37
+ """Main application class for PyDeploy Studio"""
38
 
39
  def __init__(self):
40
  self.temp_files = []
 
153
  "info": "β„Ή"
154
  }
155
  colors = {
156
+ "success": "#16a34a",
157
+ "error": "#dc2626",
158
+ "warning": "#d97706",
159
+ "info": "#2563eb"
160
  }
161
 
162
  return f'''
 
173
  """Create the Gradio application interface"""
174
  app = SpaceCreatorApp()
175
 
176
+ # Custom theme with yellow and elephant grey
177
  theme = gr.themes.Base(
178
+ primary_hue="yellow",
179
  secondary_hue="gray",
180
  neutral_hue="gray",
181
  font=("Inter", "Segoe UI", "Roboto", "Helvetica", "Arial", "sans-serif")
182
  )
183
 
184
  with gr.Blocks(
185
+ title="PyDeploy Studio",
186
  theme=theme,
187
  css="""
188
+ /* PyDeploy Studio CSS - Yellow & Elephant Grey Theme */
189
  .gradio-container {
190
+ max-width: 1300px !important;
191
  margin: 20px auto !important;
192
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
193
+ background: #f8f9fa !important;
194
  }
195
 
196
  body {
197
+ background: #f1f3f4 !important;
198
  }
199
 
200
+ /* Header with gradient */
201
+ .header-main {
202
+ background: linear-gradient(135deg, #2c3e50 0%, #34495e 100%);
203
  color: white;
204
+ padding: 2.5rem 2rem;
205
+ border-radius: 12px;
206
+ margin-bottom: 24px;
207
+ box-shadow: 0 4px 20px rgba(0,0,0,0.1);
208
+ position: relative;
209
+ overflow: hidden;
210
  }
211
 
212
+ .header-main::before {
213
+ content: '';
214
+ position: absolute;
215
+ top: 0;
216
+ right: 0;
217
+ width: 200px;
218
+ height: 200px;
219
+ background: linear-gradient(45deg, #fbbf24 0%, transparent 70%);
220
+ opacity: 0.1;
221
+ border-radius: 50%;
222
  }
223
 
224
+ .header-content {
225
+ position: relative;
226
+ z-index: 2;
227
+ }
228
+
229
+ .header-content h1 {
230
+ margin: 0 0 0.5rem 0;
231
+ font-size: 2.5rem;
232
+ font-weight: 700;
233
+ background: linear-gradient(90deg, #fbbf24 0%, #f59e0b 100%);
234
+ -webkit-background-clip: text;
235
+ -webkit-text-fill-color: transparent;
236
+ background-clip: text;
237
+ }
238
+
239
+ .header-content .subtitle {
240
+ font-size: 1.1rem;
241
  color: #cbd5e1;
242
+ margin-bottom: 1rem;
243
  }
244
 
245
+ .creator-info {
 
246
  display: flex;
247
+ align-items: center;
248
+ gap: 10px;
249
+ font-size: 0.9rem;
250
+ color: #94a3b8;
251
+ margin-top: 0.5rem;
252
+ }
253
+
254
+ .creator-info a {
255
+ color: #fbbf24;
256
+ text-decoration: none;
257
+ font-weight: 500;
258
+ transition: color 0.2s;
259
+ }
260
+
261
+ .creator-info a:hover {
262
+ color: #f59e0b;
263
+ text-decoration: underline;
264
+ }
265
+
266
+ .creator-info .linkedin-icon {
267
+ color: #0077b5;
268
+ }
269
+
270
+ /* Main Layout */
271
+ .main-wrapper {
272
+ display: flex;
273
+ gap: 24px;
274
  margin-top: 20px;
275
  }
276
 
277
+ /* Sidebar */
278
+ .sidebar-container {
279
+ flex: 0 0 300px;
280
  background: white;
281
+ padding: 1.75rem;
282
+ border-radius: 12px;
283
+ border: 1px solid #e5e7eb;
284
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
285
+ height: fit-content;
286
  }
287
 
288
+ .sidebar-title {
289
+ font-size: 1.1rem;
290
+ font-weight: 600;
291
+ color: #374151;
292
+ margin-bottom: 1.5rem;
293
+ padding-bottom: 0.75rem;
294
+ border-bottom: 2px solid #fbbf24;
295
  }
296
 
297
  /* Steps */
298
+ .step-container {
299
+ margin-bottom: 2rem;
300
+ }
301
+
302
+ .step-item {
303
+ display: flex;
304
+ align-items: flex-start;
305
+ gap: 1rem;
306
+ padding: 1.25rem;
307
  margin-bottom: 0.75rem;
308
+ background: #f9fafb;
309
+ border-radius: 10px;
310
+ border: 1px solid #e5e7eb;
311
+ transition: all 0.3s ease;
312
+ cursor: pointer;
313
  }
314
 
315
+ .step-item:hover {
316
+ transform: translateY(-2px);
317
+ box-shadow: 0 4px 12px rgba(0,0,0,0.08);
318
+ }
319
+
320
+ .step-item.active {
321
+ background: linear-gradient(135deg, #fef3c7 0%, #fffbeb 100%);
322
+ border-color: #fbbf24;
323
+ border-left: 4px solid #fbbf24;
324
  }
325
 
326
  .step-number {
327
+ width: 32px;
328
+ height: 32px;
329
+ background: #e5e7eb;
330
+ color: #6b7280;
 
331
  border-radius: 50%;
332
+ display: flex;
333
+ align-items: center;
334
+ justify-content: center;
335
+ font-weight: 600;
336
+ font-size: 0.9rem;
337
+ flex-shrink: 0;
338
+ transition: all 0.3s ease;
339
  }
340
 
341
+ .step-item.active .step-number {
342
+ background: #fbbf24;
343
+ color: #1f2937;
344
+ }
345
+
346
+ .step-content {
347
+ flex: 1;
348
  }
349
 
350
  .step-title {
351
  font-weight: 600;
352
+ color: #374151;
353
+ margin-bottom: 0.25rem;
354
+ }
355
+
356
+ .step-item.active .step-title {
357
+ color: #1f2937;
358
  }
359
 
360
  .step-description {
361
  font-size: 0.875rem;
362
+ color: #6b7280;
363
+ line-height: 1.5;
364
+ }
365
+
366
+ /* Tips Box */
367
+ .tips-container {
368
+ background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);
369
+ border: 1px solid #e2e8f0;
370
+ border-radius: 10px;
371
+ padding: 1.5rem;
372
+ }
373
+
374
+ .tips-title {
375
+ font-size: 1rem;
376
+ font-weight: 600;
377
+ color: #374151;
378
+ margin-bottom: 1rem;
379
+ display: flex;
380
+ align-items: center;
381
+ gap: 0.5rem;
382
+ }
383
+
384
+ .tips-title::before {
385
+ content: "πŸ’‘";
386
+ }
387
+
388
+ .tip-item {
389
+ display: flex;
390
+ align-items: flex-start;
391
+ gap: 0.75rem;
392
+ margin-bottom: 0.875rem;
393
+ }
394
+
395
+ .tip-item:last-child {
396
+ margin-bottom: 0;
397
+ }
398
+
399
+ .tip-bullet {
400
+ color: #fbbf24;
401
+ font-weight: bold;
402
+ flex-shrink: 0;
403
+ margin-top: 0.125rem;
404
+ }
405
+
406
+ .tip-text {
407
+ font-size: 0.875rem;
408
+ color: #4b5563;
409
+ line-height: 1.5;
410
+ }
411
+
412
+ /* Main Content */
413
+ .content-container {
414
+ flex: 1;
415
+ background: white;
416
+ padding: 2rem;
417
+ border-radius: 12px;
418
+ border: 1px solid #e5e7eb;
419
+ box-shadow: 0 2px 10px rgba(0,0,0,0.05);
420
+ }
421
+
422
+ /* Step Groups */
423
+ .step-group {
424
+ margin-bottom: 2rem;
425
+ }
426
+
427
+ .step-header {
428
+ font-size: 1.5rem;
429
+ font-weight: 600;
430
+ color: #1f2937;
431
+ margin-bottom: 1.5rem;
432
+ padding-bottom: 0.75rem;
433
+ border-bottom: 2px solid #fbbf24;
434
  }
435
 
436
  /* Form Elements */
 
438
  margin-bottom: 1.5rem;
439
  }
440
 
441
+ .form-label {
442
+ display: block;
443
+ margin-bottom: 0.5rem;
444
+ font-weight: 500;
445
+ color: #374151;
446
+ font-size: 0.95rem;
447
+ }
448
+
449
+ .form-info {
450
+ font-size: 0.85rem;
451
+ color: #6b7280;
452
+ margin-top: 0.25rem;
453
+ }
454
+
455
  input, textarea, select {
456
  width: 100%;
457
+ padding: 0.875rem 1rem;
458
+ border: 1px solid #d1d5db;
459
+ border-radius: 8px;
460
+ font-size: 0.95rem;
461
+ font-family: 'Inter', sans-serif;
462
+ transition: all 0.2s ease;
463
+ color: #374151;
464
  }
465
 
466
  input:focus, textarea:focus, select:focus {
467
  outline: none;
468
+ border-color: #fbbf24;
469
+ box-shadow: 0 0 0 3px rgba(251, 191, 36, 0.1);
470
+ }
471
+
472
+ input::placeholder, textarea::placeholder {
473
+ color: #9ca3af;
474
  }
475
 
476
  /* Buttons */
477
  button {
478
+ font-family: 'Inter', sans-serif !important;
 
479
  font-weight: 500 !important;
480
+ font-size: 0.95rem !important;
481
+ padding: 0.875rem 1.75rem !important;
482
+ border-radius: 8px !important;
483
+ transition: all 0.3s ease !important;
484
+ border: none !important;
485
  }
486
 
487
  button.primary {
488
+ background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%) !important;
489
+ color: #1f2937 !important;
490
+ font-weight: 600 !important;
491
  }
492
 
493
  button.primary:hover {
494
+ transform: translateY(-2px) !important;
495
+ box-shadow: 0 4px 12px rgba(251, 191, 36, 0.3) !important;
496
  }
497
 
498
  button.secondary {
499
  background: white !important;
500
+ color: #4b5563 !important;
501
+ border: 1px solid #d1d5db !important;
502
  }
503
 
504
  button.secondary:hover {
505
+ background: #f9fafb !important;
506
+ border-color: #9ca3af !important;
507
  }
508
 
509
  /* Tabs */
510
+ .tab-nav {
511
+ border-bottom: 1px solid #e5e7eb !important;
512
+ margin-bottom: 1.5rem !important;
513
+ }
514
+
515
  .tab-nav button {
516
  padding: 0.75rem 1.5rem !important;
517
  background: none !important;
518
  border: none !important;
519
+ border-bottom: 3px solid transparent !important;
520
+ color: #6b7280 !important;
521
+ border-radius: 0 !important;
522
  }
523
 
524
  .tab-nav button.selected {
525
+ color: #1f2937 !important;
526
+ border-bottom-color: #fbbf24 !important;
527
  font-weight: 600 !important;
528
  }
529
 
530
  /* Code Editor */
531
  #code_editor {
532
+ font-family: 'JetBrains Mono', 'Fira Code', 'Consolas', monospace !important;
533
+ font-size: 0.9rem !important;
534
+ line-height: 1.6 !important;
535
  background: #f8fafc !important;
536
  border: 1px solid #e2e8f0 !important;
537
+ border-radius: 8px !important;
538
+ padding: 1.25rem !important;
539
  }
540
 
541
  /* Status Messages */
542
  .status-message {
543
+ padding: 1rem 1.25rem;
544
+ border-radius: 8px;
545
+ margin: 1.25rem 0;
546
  border-left: 4px solid;
547
  background: #f8fafc;
548
+ font-size: 0.95rem;
549
+ display: flex;
550
+ align-items: flex-start;
551
+ gap: 0.75rem;
552
  }
553
 
554
  .status-message.success {
555
+ border-left-color: #16a34a;
556
  background: #f0fdf4;
557
  }
558
 
559
  .status-message.error {
560
+ border-left-color: #dc2626;
561
  background: #fef2f2;
562
  }
563
 
564
  .status-message.warning {
565
+ border-left-color: #d97706;
566
  background: #fffbeb;
567
  }
568
 
569
  .status-message.info {
570
+ border-left-color: #2563eb;
571
  background: #eff6ff;
572
  }
573
 
574
  /* File Cards */
575
+ .file-grid {
576
+ display: grid;
577
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
578
+ gap: 1rem;
579
+ margin: 1.5rem 0;
580
+ }
581
+
582
  .file-card {
 
 
 
 
583
  background: #f8fafc;
584
+ border: 1px solid #e2e8f0;
585
+ border-radius: 10px;
586
+ padding: 1.5rem;
587
+ transition: all 0.3s ease;
588
+ }
589
+
590
+ .file-card:hover {
591
+ transform: translateY(-2px);
592
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
593
+ border-color: #fbbf24;
594
  }
595
 
596
  .file-card-title {
597
  font-weight: 600;
598
+ color: #1f2937;
599
+ margin-bottom: 0.75rem;
600
+ font-size: 1.1rem;
601
+ }
602
+
603
+ .file-card-description {
604
+ font-size: 0.875rem;
605
+ color: #6b7280;
606
+ margin-bottom: 1rem;
607
  }
608
 
609
  /* Error Message */
610
  .error-message {
611
+ background: linear-gradient(135deg, #fef2f2 0%, #fff5f5 100%);
612
  border: 1px solid #fecaca;
613
+ border-radius: 10px;
614
+ padding: 1.5rem;
615
+ margin: 1.5rem 0;
616
  }
617
 
618
  .error-message h4 {
619
+ margin: 0 0 0.75rem 0;
620
  color: #dc2626;
621
+ font-size: 1.1rem;
622
+ display: flex;
623
+ align-items: center;
624
+ gap: 0.5rem;
625
+ }
626
+
627
+ .error-message h4::before {
628
+ content: "⚠";
629
  }
630
 
631
  .error-message ul {
632
  margin: 0;
633
+ padding-left: 1.5rem;
634
  }
635
 
636
  .error-message li {
637
+ margin-bottom: 0.5rem;
638
+ color: #7f1d1d;
639
  }
640
 
641
+ /* Radio Group */
642
+ .radio-group {
643
+ display: flex;
644
+ gap: 2rem;
645
+ margin: 1.5rem 0;
 
 
646
  }
647
 
648
+ .radio-item {
649
+ display: flex;
650
+ align-items: center;
651
+ gap: 0.5rem;
 
652
  }
653
 
654
+ /* Footer */
655
+ .footer {
656
+ text-align: center;
657
+ padding: 1.5rem;
658
+ margin-top: 2rem;
659
+ color: #6b7280;
660
+ font-size: 0.875rem;
661
+ border-top: 1px solid #e5e7eb;
662
+ }
663
 
664
+ .footer a {
665
+ color: #f59e0b;
666
+ text-decoration: none;
 
 
 
 
667
  }
668
 
669
+ .footer a:hover {
670
+ text-decoration: underline;
 
 
 
671
  }
672
 
673
+ /* Responsive Design */
674
+ @media (max-width: 1024px) {
675
+ .main-wrapper {
676
+ flex-direction: column;
677
+ }
678
+
679
+ .sidebar-container {
680
+ width: 100%;
681
+ }
682
+
683
+ .gradio-container {
684
+ padding: 10px !important;
685
+ }
686
  }
687
 
688
+ @media (max-width: 768px) {
689
+ .header-content h1 {
690
+ font-size: 2rem;
691
+ }
692
+
693
+ .content-container {
694
+ padding: 1.5rem;
695
+ }
696
+
697
+ .file-grid {
698
+ grid-template-columns: 1fr;
699
+ }
700
+
701
+ .radio-group {
702
+ flex-direction: column;
703
+ gap: 1rem;
704
+ }
705
  }
706
 
707
+ /* Animation for active step */
708
+ @keyframes pulse {
709
+ 0% { transform: scale(1); }
710
+ 50% { transform: scale(1.05); }
711
+ 100% { transform: scale(1); }
712
  }
713
 
714
+ .step-item.active {
715
+ animation: pulse 2s infinite;
 
 
716
  }
717
  """
718
  ) as demo:
719
 
720
+ # Add fonts
721
+ gr.HTML('''
722
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
723
+ <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
724
+ ''')
725
 
726
+ # Header with branding
727
  header_html = '''
728
+ <div class="header-main">
729
+ <div class="header-content">
730
+ <h1>PyDeploy Studio</h1>
731
+ <div class="subtitle">Professional Python to Gradio Application Converter</div>
732
+ <div class="creator-info">
733
+ <span>Created by</span>
734
+ <a href="https://linkedin.com/in/veerakumar" target="_blank">
735
+ <span class="linkedin-icon">πŸ”—</span> Veerakumar
736
+ </a>
737
+ <span>β€’ Streamline your deployment workflow</span>
738
+ </div>
739
+ </div>
740
  </div>
741
  '''
742
  gr.HTML(header_html)
743
 
744
+ with gr.Row(elem_classes="main-wrapper"):
 
 
 
 
 
 
 
 
745
  # Sidebar
746
+ with gr.Column(scale=1, elem_classes="sidebar-container"):
747
  current_step = gr.State(1)
748
 
749
  # Steps
750
  steps_html = '''
751
+ <div class="sidebar-title">Workflow Steps</div>
752
+ <div class="step-container">
753
+ <div class="step-item active">
754
+ <div class="step-number">1</div>
755
+ <div class="step-content">
756
+ <div class="step-title">Input Code</div>
757
+ <div class="step-description">Upload or paste your Python code</div>
758
+ </div>
759
  </div>
760
+ <div class="step-item">
761
+ <div class="step-number">2</div>
762
+ <div class="step-content">
763
+ <div class="step-title">Generate Files</div>
764
+ <div class="step-description">Download app.py, requirements.txt & README</div>
765
+ </div>
766
  </div>
767
+ <div class="step-item">
768
+ <div class="step-number">3</div>
769
+ <div class="step-content">
770
+ <div class="step-title">Deploy</div>
771
+ <div class="step-description">Deploy to Hugging Face Spaces</div>
772
+ </div>
773
  </div>
774
  </div>
 
 
775
 
776
+ <div class="tips-container">
777
+ <div class="tips-title">Quick Tips</div>
778
+ <div class="tip-item">
779
+ <span class="tip-bullet">β€’</span>
780
+ <span class="tip-text">Ensure your code has clear functions for best conversion</span>
 
 
781
  </div>
782
+ <div class="tip-item">
783
+ <span class="tip-bullet">β€’</span>
784
+ <span class="tip-text">API keys are used securely and never stored</span>
785
  </div>
786
+ <div class="tip-item">
787
+ <span class="tip-bullet">β€’</span>
788
+ <span class="tip-text">Test locally before deploying to production</span>
789
  </div>
790
  </div>
791
  '''
792
+ gr.HTML(steps_html)
793
 
794
  # Main Content
795
+ with gr.Column(scale=3, elem_classes="content-container"):
796
  # Step 1: Code Input
797
  with gr.Group(visible=True) as step1_group:
798
+ gr.Markdown('<div class="step-header">Step 1: Provide Your Code</div>')
799
 
800
  with gr.Tabs():
801
+ with gr.Tab("πŸ“ Upload File"):
802
  file_input = gr.File(
803
  label="Upload Python or Jupyter Notebook",
804
  file_types=SUPPORTED_EXTENSIONS,
805
+ type="filepath",
806
+ elem_classes="form-group"
807
  )
808
 
809
+ with gr.Tab("πŸ“ Paste Code"):
810
  text_input = gr.Textbox(
811
  label="Python Code",
812
  lines=15,
813
+ placeholder="# Paste your Python code here...\n# Example: Machine Learning model, Data processing function, etc.\n\nimport numpy as np\n\ndef process_data(input_data):\n # Your code here\n return processed_result",
814
  elem_id="code_editor"
815
  )
816
 
817
+ gr.Markdown('<div class="step-header" style="margin-top: 2rem;">Step 2: API Configuration</div>')
818
+
819
+ with gr.Row():
820
+ with gr.Column():
821
+ groq_api_key = gr.Textbox(
822
+ label="Groq API Key",
823
+ type="password",
824
+ placeholder="gsk_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
825
+ info="Required for AI-powered conversion. Get yours from console.groq.com",
826
+ elem_classes="form-group"
827
+ )
828
 
829
  # API Guide
830
+ with gr.Accordion("πŸ”‘ Need help creating API keys?", open=False):
831
  with gr.Tabs():
832
  with gr.Tab("Groq API Key"):
833
  gr.Markdown("""
834
+ ### Creating a Groq API Key
835
+ 1. Visit [console.groq.com](https://console.groq.com)
836
+ 2. Sign up or log in to your account
837
  3. Navigate to **API Keys** section
838
  4. Click **Create API Key**
839
+ 5. Give your key a descriptive name
840
+ 6. Copy the generated key (starts with `gsk_`)
841
+ 7. Paste it in the field above
842
+
843
+ *Note: Keep your API key secure and never share it publicly.*
844
  """)
845
 
846
  with gr.Tab("Hugging Face Token"):
847
  gr.Markdown("""
848
+ ### Creating a Hugging Face Token
849
+ 1. Go to [huggingface.co](https://huggingface.co)
850
+ 2. Click on your profile picture β†’ **Settings**
851
  3. Navigate to **Access Tokens**
852
  4. Click **New Token**
853
  5. Select token type: **Write**
854
+ 6. Copy the generated token (starts with `hf_`)
855
  7. Paste it in Step 2
856
+
857
+ *Write token is required for creating and updating Spaces.*
858
  """)
859
 
860
  convert_btn = gr.Button(
861
+ "πŸš€ Convert Code",
862
  variant="primary",
863
+ size="lg",
864
+ elem_classes="mt-3"
865
  )
866
 
867
  # Step 2: Generated Files
868
  with gr.Group(visible=False) as step2_group:
869
+ gr.Markdown('<div class="step-header">Step 2: Generated Files</div>')
870
+
871
+ gr.Markdown("### Your Gradio Application is Ready!")
872
+
873
+ # File Cards Grid
874
+ file_cards_html = '''
875
+ <div class="file-grid">
876
+ <div class="file-card">
877
+ <div class="file-card-title">app.py</div>
878
+ <div class="file-card-description">Main application file with Gradio interface</div>
879
+ </div>
880
+ <div class="file-card">
881
+ <div class="file-card-title">requirements.txt</div>
882
+ <div class="file-card-description">Python dependencies for your application</div>
883
+ </div>
884
+ <div class="file-card">
885
+ <div class="file-card-title">README.md</div>
886
+ <div class="file-card-description">Documentation with YAML frontmatter</div>
887
+ </div>
888
+ </div>
889
+ '''
890
+ gr.HTML(file_cards_html)
891
 
892
  with gr.Row():
893
  with gr.Column():
 
894
  app_py_download = gr.File(
895
  label="Download app.py",
896
  file_types=[".py"],
 
898
  )
899
 
900
  with gr.Column():
 
901
  requirements_download = gr.File(
902
  label="Download requirements.txt",
903
  file_types=[".txt"],
 
905
  )
906
 
907
  with gr.Column():
 
908
  readme_download = gr.File(
909
  label="Download README.md",
910
  file_types=[".md"],
911
  interactive=False
912
  )
913
 
914
+ gr.Markdown('<div class="step-header" style="margin-top: 2rem;">Step 3: Deployment Options</div>')
915
 
916
  with gr.Row():
917
  with gr.Column():
918
  hf_token = gr.Textbox(
919
  label="Hugging Face Token",
920
  type="password",
921
+ placeholder="hf_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
922
+ info="Write token required for deployment",
923
+ elem_classes="form-group"
924
  )
925
 
926
  with gr.Column():
927
  space_name = gr.Textbox(
928
  label="Space Name",
929
+ placeholder="my-awesome-gradio-app",
930
+ info="3-30 chars, lowercase letters, numbers, and hyphens only",
931
+ elem_classes="form-group"
932
  )
933
 
934
+ gr.Markdown("### Select Deployment Action")
935
  deploy_mode = gr.Radio(
936
+ choices=["πŸ“₯ Download Only", "πŸš€ Deploy to Hugging Face Space"],
937
+ label="",
938
+ value="πŸ“₯ Download Only",
939
+ elem_classes="radio-group"
940
  )
941
 
942
  with gr.Row():
943
+ back_btn_step2 = gr.Button("← Back", variant="secondary")
944
+ deploy_btn = gr.Button("Proceed to Deployment β†’", variant="primary")
945
 
946
  # Step 3: Deployment Results
947
  with gr.Group(visible=False) as step3_group:
948
+ gr.Markdown('<div class="step-header">Step 3: Deployment Complete πŸŽ‰</div>')
949
+
950
+ success_html = '''
951
+ <div style="text-align: center; padding: 2rem;">
952
+ <div style="font-size: 4rem; margin-bottom: 1rem;">βœ…</div>
953
+ <h2 style="color: #16a34a; margin-bottom: 1rem;">Deployment Successful!</h2>
954
+ <p style="color: #6b7280; margin-bottom: 2rem;">Your application is now live on Hugging Face Spaces</p>
955
+ </div>
956
+ '''
957
+ gr.HTML(success_html)
958
 
959
  with gr.Row():
960
  with gr.Column(scale=2):
961
+ gr.Markdown("### Download Complete Package")
962
  full_package_download = gr.File(
963
+ label="gradio_app_full_package.zip",
964
  file_types=[".zip"],
965
  interactive=False
966
  )
967
+ gr.Markdown("*Contains all files ready for deployment*")
968
  with gr.Column(scale=1):
969
+ gr.Markdown("### Next Steps")
970
  gr.Markdown("""
971
+ 1. **Visit** your Space on Hugging Face
972
+ 2. **Monitor** deployment logs
973
+ 3. **Share** your app with others
974
+ 4. **Customize** further if needed
975
  """)
976
 
977
  deployment_status = gr.Markdown()
978
 
979
  with gr.Row():
980
+ back_btn_step3 = gr.Button("πŸ”„ Start New Project", variant="secondary")
981
+ finish_btn = gr.Button("🎯 Finish", variant="primary")
982
 
983
  # Status output
984
  status_output = gr.HTML(
 
986
  elem_id="status_output"
987
  )
988
 
989
+ # Footer
990
+ footer_html = '''
991
+ <div class="footer">
992
+ <p>PyDeploy Studio β€’ Created by <a href="https://linkedin.com/in/veerakumar" target="_blank">Veerakumar</a></p>
993
+ <p style="font-size: 0.8rem; color: #9ca3af; margin-top: 0.5rem;">Transform your Python code into production-ready applications</p>
994
+ </div>
995
+ '''
996
+ gr.HTML(footer_html)
997
+
998
+ # JavaScript for updating steps
999
  js_code = """
1000
  <script>
1001
+ function updateSteps(step) {
1002
+ const steps = document.querySelectorAll('.step-item');
 
 
 
 
 
 
1003
  steps.forEach((stepEl, index) => {
1004
  stepEl.classList.remove('active');
1005
+ if (index === step - 1) {
1006
  stepEl.classList.add('active');
1007
  }
1008
  });
1009
  }
1010
+
1011
+ // Initialize
1012
+ document.addEventListener('DOMContentLoaded', function() {
1013
+ updateSteps(1);
1014
+ });
1015
  </script>
1016
  """
1017
  gr.HTML(js_code)
1018
 
1019
  # Event handlers
1020
+ def update_step_display(step):
1021
  return f"""
1022
  <script>
1023
+ updateSteps({step});
1024
  </script>
1025
  """
1026
 
 
1040
  inputs=[current_step],
1041
  outputs=[step1_group, step2_group, step3_group]
1042
  ).then(
1043
+ fn=update_step_display,
1044
  inputs=[current_step],
1045
  outputs=[status_output]
1046
  )
 
1054
  inputs=[current_step],
1055
  outputs=[step1_group, step2_group, step3_group]
1056
  ).then(
1057
+ fn=update_step_display,
1058
  inputs=[current_step],
1059
  outputs=[status_output]
1060
  )
 
1063
  fn=lambda: (1, gr.update(visible=True), gr.update(visible=False), gr.update(visible=False)),
1064
  outputs=[current_step, step1_group, step2_group, step3_group]
1065
  ).then(
1066
+ fn=update_step_display,
1067
  inputs=[current_step],
1068
  outputs=[status_output]
1069
  )
 
1076
  inputs=None,
1077
  outputs=None
1078
  ).then(
1079
+ fn=update_step_display,
1080
  inputs=[current_step],
1081
  outputs=[status_output]
1082
  )
 
1091
 
1092
 
1093
  if __name__ == "__main__":
1094
+ print("=" * 60)
1095
+ print("PyDeploy Studio - Professional Deployment Platform")
1096
+ print("Created by Veerakumar")
1097
+ print("=" * 60)
1098
+ print("Starting server...")
1099
+ print(f"Local URL: http://localhost:7860")
1100
+ print("=" * 60)
1101
 
1102
  app = create_app()
1103
  app.launch(
1104
  server_name="0.0.0.0",
1105
  server_port=7860,
1106
  share=False,
1107
+ debug=False,
1108
+ favicon_path=None,
1109
+ show_error=True
1110
  )