kamau1 commited on
Commit
95cf7f2
·
verified ·
1 Parent(s): 5e36ad1

feat: api tabs

Browse files
static/css/dashboard-simple.css CHANGED
@@ -518,34 +518,35 @@
518
 
519
  /* API Documentation Section */
520
  .api-documentation-section {
521
- margin-top: 80px;
522
- padding: 60px 0;
523
- background: #ffffff;
524
- border-top: 2px solid #f1f3f4;
 
525
  }
526
 
 
527
  .api-docs-header {
 
 
 
528
  text-align: center;
529
- margin-bottom: 40px;
530
- max-width: 800px;
531
- margin-left: auto;
532
- margin-right: auto;
533
- padding: 0 20px;
534
  }
535
 
536
  .api-docs-header h2 {
537
- font-size: 2.5rem;
538
  font-weight: 700;
539
- color: #1a73e8;
540
- margin-bottom: 16px;
541
  letter-spacing: -0.5px;
 
542
  }
543
 
544
  .api-docs-header p {
545
  font-size: 1.1rem;
546
- color: #5f6368;
547
- line-height: 1.6;
548
- font-weight: 400;
549
  }
550
 
551
  .api-docs-container {
@@ -554,80 +555,89 @@
554
  padding: 0 20px;
555
  }
556
 
557
- /* API Overview Card */
558
- .api-overview-card {
559
- background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
560
- border-radius: 16px;
561
- padding: 32px;
562
- margin-bottom: 40px;
563
- color: white;
564
- box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3);
 
 
 
 
 
565
  }
566
 
567
- .api-endpoint-header {
568
  display: flex;
569
  align-items: center;
570
  gap: 16px;
571
- margin-bottom: 24px;
572
  flex-wrap: wrap;
573
  }
574
 
575
  .method-badge {
576
- background: rgba(255, 255, 255, 0.2);
577
  color: white;
578
- padding: 8px 16px;
579
- border-radius: 8px;
580
- font-size: 0.9rem;
581
- font-weight: 700;
582
  letter-spacing: 0.5px;
583
- backdrop-filter: blur(10px);
584
  }
585
 
586
  .endpoint-url {
587
- background: rgba(255, 255, 255, 0.15);
588
- color: white;
589
- padding: 12px 20px;
590
- border-radius: 8px;
591
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
592
- font-size: 0.95rem;
593
- font-weight: 500;
594
  flex: 1;
595
  min-width: 300px;
596
- backdrop-filter: blur(10px);
597
  }
598
 
599
- .api-status {
600
- background: rgba(76, 175, 80, 0.9);
601
- color: white;
602
- padding: 6px 12px;
603
- border-radius: 20px;
604
- font-size: 0.8rem;
605
  font-weight: 600;
606
  }
607
 
608
- .api-features {
609
  display: grid;
610
- grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
611
  gap: 16px;
 
612
  }
613
 
614
  .feature-item {
615
- background: rgba(255, 255, 255, 0.1);
616
- padding: 16px 20px;
617
- border-radius: 12px;
618
- font-size: 0.95rem;
619
- line-height: 1.4;
620
- backdrop-filter: blur(10px);
621
- border: 1px solid rgba(255, 255, 255, 0.1);
622
  }
623
 
624
- /* API Tabs Container */
625
- .api-tabs-container {
 
 
 
 
 
 
 
 
 
 
 
626
  background: white;
627
- border-radius: 16px;
628
- box-shadow: 0 4px 24px rgba(0, 0, 0, 0.08);
629
- overflow: hidden;
630
- margin-bottom: 40px;
631
  }
632
  padding: 2px 6px;
633
  border-radius: 3px;
@@ -649,50 +659,45 @@
649
  margin-bottom: 32px;
650
  }
651
 
652
- .api-tabs {
653
  display: flex;
654
- background: #f8f9fa;
655
- border-bottom: 1px solid #e9ecef;
656
  overflow-x: auto;
 
657
  }
658
 
659
- .api-tab {
660
  background: none;
661
  border: none;
662
  padding: 16px 24px;
663
- font-size: 0.95rem;
664
- font-weight: 600;
665
  color: #6c757d;
666
  cursor: pointer;
667
  border-bottom: 3px solid transparent;
668
- transition: all 0.3s ease;
669
  white-space: nowrap;
 
670
  position: relative;
671
  }
672
 
673
- .api-tab:hover {
674
  color: #495057;
675
- background: #e9ecef;
676
  }
677
 
678
- .api-tab.active {
679
- color: #1a73e8;
 
680
  background: white;
681
- border-bottom-color: #1a73e8;
682
- font-weight: 700;
683
- }
684
-
685
- .api-tab-content {
686
- position: relative;
687
  }
688
 
689
- .tab-pane {
690
  display: none;
691
  }
692
 
693
- .tab-pane.active {
694
  display: block;
695
- padding: 32px;
696
  }
697
 
698
  .code-header {
@@ -726,31 +731,57 @@
726
  background: #0860ca;
727
  }
728
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
729
  .code-block {
730
- background: #1e1e1e;
731
- color: #e1e4e8;
732
- padding: 24px;
733
  margin: 0;
734
- font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace;
735
- font-size: 0.9rem;
736
- line-height: 1.6;
737
  overflow-x: auto;
738
- white-space: pre;
739
- border-radius: 12px;
740
- box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1);
741
- border: 1px solid #333;
742
- position: relative;
743
- }
744
-
745
- .code-block::before {
746
- content: '';
747
- position: absolute;
748
- top: 0;
749
- left: 0;
750
- right: 0;
751
- height: 3px;
752
- background: linear-gradient(90deg, #1a73e8, #4285f4);
753
- border-radius: 12px 12px 0 0;
754
  }
755
 
756
  /* Syntax Highlighting */
@@ -776,123 +807,122 @@
776
  .code-block .json-boolean { color: #ff7b72; }
777
 
778
  /* Response Section */
779
- .response-section {
780
- background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%);
781
- border-radius: 12px;
 
782
  padding: 24px;
783
  margin-bottom: 24px;
784
- border: 1px solid #dee2e6;
785
  }
786
 
787
- .response-section h3 {
788
- color: #1a73e8;
789
- font-size: 1.4rem;
790
- font-weight: 700;
791
- margin-bottom: 12px;
792
  }
793
 
794
  .response-description {
795
- color: #495057;
796
- font-size: 1rem;
797
- line-height: 1.5;
798
  margin-bottom: 20px;
 
799
  }
800
 
801
- .species-summary {
802
  display: grid;
803
  gap: 12px;
 
804
  }
805
 
806
- .species-item {
807
  display: flex;
808
  justify-content: space-between;
809
  align-items: center;
810
  background: white;
811
  padding: 12px 16px;
812
- border-radius: 8px;
813
  border: 1px solid #e9ecef;
814
- box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
815
  }
816
 
817
  .species-name {
818
- font-weight: 600;
819
- color: #343a40;
820
  }
821
 
822
- .confidence {
823
- padding: 4px 12px;
824
- border-radius: 20px;
825
- font-size: 0.85rem;
826
- font-weight: 700;
827
  }
828
 
829
- .confidence.high {
830
  background: #d4edda;
831
  color: #155724;
832
  }
833
 
834
- .confidence.medium {
835
  background: #fff3cd;
836
  color: #856404;
837
  }
838
 
839
- .more-species {
840
- color: #6c757d;
841
- font-style: italic;
842
- text-align: center;
843
- padding: 8px;
844
- background: rgba(108, 117, 125, 0.1);
845
- border-radius: 6px;
846
- }
847
-
848
- /* Additional Information */
849
- .api-docs-footer {
850
- margin-top: 32px;
851
  }
852
 
853
- .api-docs-info-grid {
854
  display: grid;
855
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
856
- gap: 20px;
857
  }
858
 
859
- .api-info-card {
860
  background: white;
861
- padding: 20px;
862
  border-radius: 8px;
863
- border: 1px solid #e1e5e9;
864
  }
865
 
866
- .api-info-card h4 {
867
- margin: 0 0 16px 0;
868
  font-size: 1rem;
869
  font-weight: 600;
870
- color: #1a1a1a;
 
871
  }
872
 
873
- .api-info-card ul {
874
- margin: 0;
875
- padding: 0;
876
  list-style: none;
877
  }
878
 
879
- .api-info-card li {
880
- padding: 6px 0;
881
- color: #656d76;
882
  font-size: 0.875rem;
883
- line-height: 1.5;
884
- border-bottom: 1px solid #f6f8fa;
885
  }
886
 
887
- .api-info-card li:last-child {
888
  border-bottom: none;
889
  }
890
 
891
- .api-info-card strong {
892
- color: #1a1a1a;
893
  font-weight: 600;
894
  }
895
 
 
 
 
 
 
 
 
 
 
 
896
  /* Responsive Design */
897
  @media (max-width: 768px) {
898
  .api-docs-header h2 {
 
518
 
519
  /* API Documentation Section */
520
  .api-documentation-section {
521
+ margin: 60px 0;
522
+ background: white;
523
+ border-radius: 12px;
524
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
525
+ overflow: hidden;
526
  }
527
 
528
+ /* Header */
529
  .api-docs-header {
530
+ background: #f8f9fa;
531
+ color: #495057;
532
+ padding: 40px;
533
  text-align: center;
534
+ border-bottom: 1px solid #e9ecef;
 
 
 
 
535
  }
536
 
537
  .api-docs-header h2 {
538
+ font-size: 2rem;
539
  font-weight: 700;
540
+ margin-bottom: 12px;
 
541
  letter-spacing: -0.5px;
542
+ color: #495057;
543
  }
544
 
545
  .api-docs-header p {
546
  font-size: 1.1rem;
547
+ opacity: 0.8;
548
+ max-width: 600px;
549
+ margin: 0 auto;
550
  }
551
 
552
  .api-docs-container {
 
555
  padding: 0 20px;
556
  }
557
 
558
+ /* API Overview */
559
+ .api-overview {
560
+ padding: 32px 40px;
561
+ border-bottom: 1px solid #e9ecef;
562
+ background: #f8f9fa;
563
+ }
564
+
565
+ .endpoint-card {
566
+ background: white;
567
+ border: 1px solid #e1e5e9;
568
+ border-radius: 8px;
569
+ padding: 24px;
570
+ margin-bottom: 20px;
571
  }
572
 
573
+ .endpoint-header {
574
  display: flex;
575
  align-items: center;
576
  gap: 16px;
577
+ margin-bottom: 16px;
578
  flex-wrap: wrap;
579
  }
580
 
581
  .method-badge {
582
+ background: #28a745;
583
  color: white;
584
+ padding: 6px 12px;
585
+ border-radius: 4px;
586
+ font-size: 0.875rem;
587
+ font-weight: 600;
588
  letter-spacing: 0.5px;
 
589
  }
590
 
591
  .endpoint-url {
592
+ background: #f8f9fa;
593
+ border: 1px solid #e9ecef;
594
+ padding: 8px 12px;
595
+ border-radius: 4px;
596
+ font-family: 'SFMono-Regular', 'Monaco', 'Consolas', monospace;
597
+ font-size: 0.875rem;
598
+ color: #495057;
599
  flex: 1;
600
  min-width: 300px;
 
601
  }
602
 
603
+ .status-badge {
604
+ background: #d4edda;
605
+ color: #155724;
606
+ padding: 4px 8px;
607
+ border-radius: 12px;
608
+ font-size: 0.75rem;
609
  font-weight: 600;
610
  }
611
 
612
+ .features-grid {
613
  display: grid;
614
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
615
  gap: 16px;
616
+ margin-top: 20px;
617
  }
618
 
619
  .feature-item {
620
+ background: #f8f9fa;
621
+ padding: 16px;
622
+ border-radius: 6px;
623
+ border-left: 4px solid #6c757d;
 
 
 
624
  }
625
 
626
+ .feature-title {
627
+ font-weight: 600;
628
+ color: #495057;
629
+ margin-bottom: 4px;
630
+ }
631
+
632
+ .feature-description {
633
+ font-size: 0.875rem;
634
+ color: #6c757d;
635
+ }
636
+
637
+ /* Tabs Navigation */
638
+ .tabs-container {
639
  background: white;
640
+ border-bottom: 1px solid #e9ecef;
 
 
 
641
  }
642
  padding: 2px 6px;
643
  border-radius: 3px;
 
659
  margin-bottom: 32px;
660
  }
661
 
662
+ .tabs-nav {
663
  display: flex;
 
 
664
  overflow-x: auto;
665
+ border-bottom: 1px solid #e9ecef;
666
  }
667
 
668
+ .tab-button {
669
  background: none;
670
  border: none;
671
  padding: 16px 24px;
672
+ font-size: 0.875rem;
673
+ font-weight: 500;
674
  color: #6c757d;
675
  cursor: pointer;
676
  border-bottom: 3px solid transparent;
 
677
  white-space: nowrap;
678
+ transition: all 0.2s ease;
679
  position: relative;
680
  }
681
 
682
+ .tab-button:hover {
683
  color: #495057;
684
+ background: #f8f9fa;
685
  }
686
 
687
+ .tab-button.active {
688
+ color: #495057;
689
+ border-bottom-color: #495057;
690
  background: white;
691
+ font-weight: 600;
 
 
 
 
 
692
  }
693
 
694
+ .tab-content {
695
  display: none;
696
  }
697
 
698
+ .tab-content.active {
699
  display: block;
700
+ padding: 32px 40px;
701
  }
702
 
703
  .code-header {
 
731
  background: #0860ca;
732
  }
733
 
734
+ /* Code Blocks */
735
+ .code-section {
736
+ margin-bottom: 32px;
737
+ }
738
+
739
+ .code-header {
740
+ display: flex;
741
+ justify-content: space-between;
742
+ align-items: center;
743
+ background: #2d3748;
744
+ color: white;
745
+ padding: 12px 20px;
746
+ border-radius: 6px 6px 0 0;
747
+ }
748
+
749
+ .code-title {
750
+ font-size: 0.875rem;
751
+ font-weight: 500;
752
+ }
753
+
754
+ .copy-button {
755
+ background: #4a5568;
756
+ color: white;
757
+ border: none;
758
+ padding: 6px 12px;
759
+ border-radius: 4px;
760
+ font-size: 0.75rem;
761
+ cursor: pointer;
762
+ transition: background 0.2s ease;
763
+ }
764
+
765
+ .copy-button:hover {
766
+ background: #2d3748;
767
+ }
768
+
769
+ .copy-button.copied {
770
+ background: #38a169;
771
+ }
772
+
773
  .code-block {
774
+ background: #1a202c;
775
+ color: #e2e8f0;
776
+ padding: 20px;
777
  margin: 0;
778
+ font-family: 'SFMono-Regular', 'Monaco', 'Consolas', monospace;
779
+ font-size: 0.875rem;
780
+ line-height: 1.5;
781
  overflow-x: auto;
782
+ border-radius: 0 0 6px 6px;
783
+ border: 1px solid #2d3748;
784
+ border-top: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
785
  }
786
 
787
  /* Syntax Highlighting */
 
807
  .code-block .json-boolean { color: #ff7b72; }
808
 
809
  /* Response Section */
810
+ .response-demo {
811
+ background: #f8f9fa;
812
+ border: 1px solid #e9ecef;
813
+ border-radius: 8px;
814
  padding: 24px;
815
  margin-bottom: 24px;
 
816
  }
817
 
818
+ .response-title {
819
+ font-size: 1.1rem;
820
+ font-weight: 600;
821
+ color: #495057;
822
+ margin-bottom: 16px;
823
  }
824
 
825
  .response-description {
826
+ color: #6c757d;
 
 
827
  margin-bottom: 20px;
828
+ line-height: 1.5;
829
  }
830
 
831
+ .detection-summary {
832
  display: grid;
833
  gap: 12px;
834
+ margin-bottom: 20px;
835
  }
836
 
837
+ .detection-item {
838
  display: flex;
839
  justify-content: space-between;
840
  align-items: center;
841
  background: white;
842
  padding: 12px 16px;
843
+ border-radius: 6px;
844
  border: 1px solid #e9ecef;
 
845
  }
846
 
847
  .species-name {
848
+ font-weight: 500;
849
+ color: #495057;
850
  }
851
 
852
+ .confidence-badge {
853
+ padding: 4px 8px;
854
+ border-radius: 12px;
855
+ font-size: 0.75rem;
856
+ font-weight: 600;
857
  }
858
 
859
+ .confidence-high {
860
  background: #d4edda;
861
  color: #155724;
862
  }
863
 
864
+ .confidence-medium {
865
  background: #fff3cd;
866
  color: #856404;
867
  }
868
 
869
+ /* Documentation Footer */
870
+ .docs-footer {
871
+ padding: 40px;
872
+ background: #f8f9fa;
873
+ border-top: 1px solid #e9ecef;
 
 
 
 
 
 
 
874
  }
875
 
876
+ .info-grid {
877
  display: grid;
878
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
879
+ gap: 24px;
880
  }
881
 
882
+ .info-card {
883
  background: white;
884
+ padding: 24px;
885
  border-radius: 8px;
886
+ border: 1px solid #e9ecef;
887
  }
888
 
889
+ .info-card h4 {
 
890
  font-size: 1rem;
891
  font-weight: 600;
892
+ color: #495057;
893
+ margin-bottom: 16px;
894
  }
895
 
896
+ .info-list {
 
 
897
  list-style: none;
898
  }
899
 
900
+ .info-list li {
901
+ padding: 8px 0;
902
+ color: #6c757d;
903
  font-size: 0.875rem;
904
+ border-bottom: 1px solid #f8f9fa;
 
905
  }
906
 
907
+ .info-list li:last-child {
908
  border-bottom: none;
909
  }
910
 
911
+ .info-list strong {
912
+ color: #495057;
913
  font-weight: 600;
914
  }
915
 
916
+ /* Syntax highlighting */
917
+ .keyword { color: #f56565; }
918
+ .string { color: #68d391; }
919
+ .number { color: #63b3ed; }
920
+ .comment { color: #a0aec0; font-style: italic; }
921
+ .function { color: #d6bcfa; }
922
+ .variable { color: #fbb6ce; }
923
+ .operator { color: #f56565; }
924
+ .property { color: #63b3ed; }
925
+
926
  /* Responsive Design */
927
  @media (max-width: 768px) {
928
  .api-docs-header h2 {
static/js/dashboard.js CHANGED
@@ -398,29 +398,50 @@ function fallbackCopyTextToClipboard(text) {
398
 
399
  // API Documentation Tabs
400
  document.addEventListener('DOMContentLoaded', function() {
401
- const apiTabs = document.querySelectorAll('.api-tab');
402
- const tabPanes = document.querySelectorAll('.tab-pane');
403
 
404
- apiTabs.forEach(tab => {
405
- tab.addEventListener('click', function() {
406
  const targetTab = this.getAttribute('data-tab');
407
 
408
- // Remove active class from all tabs and panes
409
- apiTabs.forEach(t => t.classList.remove('active'));
410
- tabPanes.forEach(p => p.classList.remove('active'));
411
 
412
- // Add active class to clicked tab
413
  this.classList.add('active');
414
 
415
- // Show corresponding tab pane
416
- const targetPane = document.getElementById(targetTab + '-tab');
417
- if (targetPane) {
418
- targetPane.classList.add('active');
419
  }
420
  });
421
  });
422
  });
423
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
424
  // Make dashboard instance globally available for sample image clicks
425
  let dashboard;
426
 
 
398
 
399
  // API Documentation Tabs
400
  document.addEventListener('DOMContentLoaded', function() {
401
+ const tabButtons = document.querySelectorAll('.tab-button');
402
+ const tabContents = document.querySelectorAll('.tab-content');
403
 
404
+ tabButtons.forEach(button => {
405
+ button.addEventListener('click', function() {
406
  const targetTab = this.getAttribute('data-tab');
407
 
408
+ // Remove active class from all buttons and contents
409
+ tabButtons.forEach(b => b.classList.remove('active'));
410
+ tabContents.forEach(c => c.classList.remove('active'));
411
 
412
+ // Add active class to clicked button
413
  this.classList.add('active');
414
 
415
+ // Show corresponding tab content
416
+ const targetContent = document.getElementById(targetTab + '-tab');
417
+ if (targetContent) {
418
+ targetContent.classList.add('active');
419
  }
420
  });
421
  });
422
  });
423
 
424
+ // Copy code functionality
425
+ function copyCode(elementId) {
426
+ const codeElement = document.getElementById(elementId);
427
+ const text = codeElement.textContent;
428
+
429
+ navigator.clipboard.writeText(text).then(function() {
430
+ // Find the copy button and show feedback
431
+ const button = codeElement.parentElement.querySelector('.copy-button');
432
+ const originalText = button.textContent;
433
+ button.textContent = 'Copied!';
434
+ button.classList.add('copied');
435
+
436
+ setTimeout(() => {
437
+ button.textContent = originalText;
438
+ button.classList.remove('copied');
439
+ }, 2000);
440
+ }).catch(function(err) {
441
+ console.error('Failed to copy text: ', err);
442
+ });
443
+ }
444
+
445
  // Make dashboard instance globally available for sample image clicks
446
  let dashboard;
447
 
templates/dashboard.html CHANGED
@@ -169,43 +169,56 @@
169
  <!-- API Documentation Section -->
170
  <div class="api-documentation-section">
171
  <div class="api-docs-header">
172
- <h2>🚀 API Documentation</h2>
173
  <p>Professional marine species identification API for developers and researchers</p>
174
  </div>
175
 
176
- <div class="api-docs-container">
177
- <!-- API Overview Card -->
178
- <div class="api-overview-card">
179
- <div class="api-endpoint-header">
180
  <span class="method-badge">POST</span>
181
  <code class="endpoint-url">https://seamo-ai-fishapi.hf.space/api/v1/detect</code>
182
- <span class="api-status">Live</span>
183
  </div>
184
- <div class="api-features">
185
- <div class="feature-item">🐟 <strong>691 Species</strong> - Comprehensive marine life detection</div>
186
- <div class="feature-item">⚡ <strong>~2 seconds</strong> - Fast AI-powered processing</div>
187
- <div class="feature-item">📍 <strong>Precise locations</strong> - Bounding boxes with confidence scores</div>
188
- <div class="feature-item">🖼️ <strong>Annotated images</strong> - Visual results with species labels</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
189
  </div>
190
  </div>
 
191
 
192
- <!-- Tabbed Interface -->
193
- <div class="api-tabs-container">
194
- <div class="api-tabs">
195
- <button class="api-tab active" data-tab="curl">cURL</button>
196
- <button class="api-tab" data-tab="python">Python</button>
197
- <button class="api-tab" data-tab="javascript">JavaScript</button>
198
- <button class="api-tab" data-tab="csharp">C#</button>
199
- <button class="api-tab" data-tab="response">Response</button>
200
- </div>
201
 
202
- <div class="api-tab-content">
203
- <!-- cURL Tab -->
204
- <div class="tab-pane active" id="curl-tab">
205
- <div class="code-header">
206
- <span class="code-title">cURL Request</span>
207
- <button class="copy-btn" onclick="copyToClipboard('curl-code')">Copy</button>
208
- </div>
209
  <pre class="code-block" id="curl-code"><span class="comment"># Easy one-liner with automatic base64 conversion</span>
210
  <span class="cmd">curl</span> <span class="flag">-X</span> <span class="method">POST</span> <span class="string">"https://seamo-ai-fishapi.hf.space/api/v1/detect"</span> <span class="operator">\</span>
211
  <span class="flag">-H</span> <span class="string">"Content-Type: application/json"</span> <span class="operator">\</span>
@@ -215,14 +228,16 @@
215
  \"iou_threshold\": 0.45,
216
  \"return_annotated_image\": true
217
  }"</span></pre>
218
- </div>
 
219
 
220
- <!-- Python Tab -->
221
- <div class="tab-pane" id="python-tab">
222
- <div class="code-header">
223
- <span class="code-title">Python Request</span>
224
- <button class="copy-btn" onclick="copyToClipboard('python-code')">Copy</button>
225
- </div>
 
226
  <pre class="code-block" id="python-code"><span class="keyword">import</span> <span class="module">requests</span>
227
  <span class="keyword">import</span> <span class="module">base64</span>
228
 
@@ -245,14 +260,16 @@
245
  <span class="function">print</span>(<span class="string">f"Found </span>{<span class="function">len</span>(<span class="variable">result</span>[<span class="string">'detections'</span>])}<span class="string"> species"</span>)
246
  <span class="keyword">for</span> <span class="variable">detection</span> <span class="keyword">in</span> <span class="variable">result</span>[<span class="string">'detections'</span>]:
247
  <span class="function">print</span>(<span class="string">f"- </span>{<span class="variable">detection</span>[<span class="string">'class_name'</span>]}<span class="string">: </span>{<span class="variable">detection</span>[<span class="string">'confidence'</span>]:<span class="string">.2%</span>}<span class="string">"</span>)</pre>
248
- </div>
 
249
 
250
- <!-- JavaScript Tab -->
251
- <div class="tab-pane" id="javascript-tab">
252
- <div class="code-header">
253
- <span class="code-title">JavaScript Request</span>
254
- <button class="copy-btn" onclick="copyToClipboard('js-code')">Copy</button>
255
- </div>
 
256
  <pre class="code-block" id="js-code"><span class="comment">// Convert file to base64</span>
257
  <span class="keyword">function</span> <span class="function">fileToBase64</span>(<span class="variable">file</span>) {
258
  <span class="keyword">return</span> <span class="keyword">new</span> <span class="function">Promise</span>((<span class="variable">resolve</span>, <span class="variable">reject</span>) <span class="operator">=></span> {
@@ -285,14 +302,16 @@
285
  });
286
  })
287
  .<span class="function">catch</span>(<span class="variable">error</span> <span class="operator">=></span> <span class="variable">console</span>.<span class="function">error</span>(<span class="string">'Error:'</span>, <span class="variable">error</span>));</pre>
288
- </div>
 
289
 
290
- <!-- C# Tab -->
291
- <div class="tab-pane" id="csharp-tab">
292
- <div class="code-header">
293
- <span class="code-title">C# Request</span>
294
- <button class="copy-btn" onclick="copyToClipboard('csharp-code')">Copy</button>
295
- </div>
 
296
  <pre class="code-block" id="csharp-code"><span class="keyword">using</span> <span class="namespace">System</span>;
297
  <span class="keyword">using</span> <span class="namespace">System.IO</span>;
298
  <span class="keyword">using</span> <span class="namespace">System.Net.Http</span>;
@@ -323,38 +342,38 @@
323
 
324
  <span class="keyword">var</span> <span class="variable">result</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="variable">response</span>.<span class="property">Content</span>.<span class="function">ReadAsStringAsync</span>();
325
  <span class="class">Console</span>.<span class="function">WriteLine</span>(<span class="variable">result</span>);</pre>
 
 
 
 
 
 
 
 
 
326
  </div>
327
 
328
- <!-- Response Tab -->
329
- <div class="tab-pane" id="response-tab">
330
- <div class="response-section">
331
- <h3>📊 Real API Response</h3>
332
- <p class="response-description">
333
- Actual response from testing with <strong>red_fish.png</strong> -
334
- detected <strong>8 marine species</strong> in 1.79 seconds:
335
- </p>
336
-
337
- <div class="species-summary">
338
- <div class="species-item">
339
- <span class="species-name">🐟 Sebastolobus (Rockfish)</span>
340
- <span class="confidence high">86.7%</span>
341
- </div>
342
- <div class="species-item">
343
- <span class="species-name">🪸 Octocorallia (Soft Coral)</span>
344
- <span class="confidence medium">69.7%</span>
345
- </div>
346
- <div class="species-item">
347
- <span class="species-name">🥒 Psolus squamatus (Sea Cucumber)</span>
348
- <span class="confidence medium">66.3%</span>
349
- </div>
350
- <div class="more-species">+ 5 more species detected with precise bounding boxes</div>
351
- </div>
352
  </div>
353
-
354
- <div class="code-header">
355
- <span class="code-title">JSON Response</span>
356
- <button class="copy-btn" onclick="copyToClipboard('response-code')">Copy</button>
357
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
358
  <pre class="code-block" id="response-code">{
359
  <span class="json-key">"detections"</span>: [
360
  {
@@ -389,36 +408,39 @@
389
  </div>
390
  </div>
391
 
392
- <!-- Additional Information -->
393
- <div class="api-docs-footer">
394
- <div class="api-docs-info-grid">
395
- <div class="api-info-card">
396
- <h4>Parameters</h4>
397
- <ul>
398
- <li><strong>file</strong> (required): Image file (JPG, PNG, WebP)</li>
399
- <li><strong>confidence_threshold</strong>: Min confidence (0.0-1.0, default: 0.25)</li>
400
- <li><strong>iou_threshold</strong>: IoU threshold (0.0-1.0, default: 0.45)</li>
401
- </ul>
402
- </div>
403
- <div class="api-info-card">
404
- <h4>Additional Endpoints</h4>
405
- <ul>
406
- <li><strong>GET /health</strong>: API health status</li>
407
- <li><strong>GET /api/v1/species</strong>: List all supported species</li>
408
- <li><strong>GET /docs</strong>: Interactive Swagger documentation</li>
409
- </ul>
410
- </div>
411
- <div class="api-info-card">
412
- <h4>Rate Limits</h4>
413
- <ul>
414
- <li><strong>Free tier</strong>: 100 requests/hour</li>
415
- <li><strong>Max file size</strong>: 10MB</li>
416
- <li><strong>Supported formats</strong>: JPEG, PNG, WebP</li>
417
- </ul>
418
- </div>
 
 
419
  </div>
420
  </div>
421
  </div>
 
422
  </div>
423
  </div>
424
  {% endblock %}
 
169
  <!-- API Documentation Section -->
170
  <div class="api-documentation-section">
171
  <div class="api-docs-header">
172
+ <h2>API Documentation</h2>
173
  <p>Professional marine species identification API for developers and researchers</p>
174
  </div>
175
 
176
+ <div class="api-overview">
177
+ <div class="endpoint-card">
178
+ <div class="endpoint-header">
 
179
  <span class="method-badge">POST</span>
180
  <code class="endpoint-url">https://seamo-ai-fishapi.hf.space/api/v1/detect</code>
181
+ <span class="status-badge">Live</span>
182
  </div>
183
+
184
+ <div class="features-grid">
185
+ <div class="feature-item">
186
+ <div class="feature-title">691 Species</div>
187
+ <div class="feature-description">Comprehensive marine life detection</div>
188
+ </div>
189
+ <div class="feature-item">
190
+ <div class="feature-title">~2 seconds</div>
191
+ <div class="feature-description">Fast AI-powered processing</div>
192
+ </div>
193
+ <div class="feature-item">
194
+ <div class="feature-title">Precise Locations</div>
195
+ <div class="feature-description">Bounding boxes with confidence scores</div>
196
+ </div>
197
+ <div class="feature-item">
198
+ <div class="feature-title">Annotated Images</div>
199
+ <div class="feature-description">Visual results with species labels</div>
200
+ </div>
201
  </div>
202
  </div>
203
+ </div>
204
 
205
+ <!-- Tabs Navigation -->
206
+ <div class="tabs-container">
207
+ <div class="tabs-nav">
208
+ <button class="tab-button active" data-tab="curl">cURL</button>
209
+ <button class="tab-button" data-tab="python">Python</button>
210
+ <button class="tab-button" data-tab="javascript">JavaScript</button>
211
+ <button class="tab-button" data-tab="csharp">C#</button>
212
+ <button class="tab-button" data-tab="response">Response</button>
213
+ </div>
214
 
215
+ <!-- cURL Tab -->
216
+ <div class="tab-content active" id="curl-tab">
217
+ <div class="code-section">
218
+ <div class="code-header">
219
+ <span class="code-title">cURL Request</span>
220
+ <button class="copy-button" onclick="copyCode('curl-code')">Copy</button>
221
+ </div>
222
  <pre class="code-block" id="curl-code"><span class="comment"># Easy one-liner with automatic base64 conversion</span>
223
  <span class="cmd">curl</span> <span class="flag">-X</span> <span class="method">POST</span> <span class="string">"https://seamo-ai-fishapi.hf.space/api/v1/detect"</span> <span class="operator">\</span>
224
  <span class="flag">-H</span> <span class="string">"Content-Type: application/json"</span> <span class="operator">\</span>
 
228
  \"iou_threshold\": 0.45,
229
  \"return_annotated_image\": true
230
  }"</span></pre>
231
+ </div>
232
+ </div>
233
 
234
+ <!-- Python Tab -->
235
+ <div class="tab-content" id="python-tab">
236
+ <div class="code-section">
237
+ <div class="code-header">
238
+ <span class="code-title">Python Request</span>
239
+ <button class="copy-button" onclick="copyCode('python-code')">Copy</button>
240
+ </div>
241
  <pre class="code-block" id="python-code"><span class="keyword">import</span> <span class="module">requests</span>
242
  <span class="keyword">import</span> <span class="module">base64</span>
243
 
 
260
  <span class="function">print</span>(<span class="string">f"Found </span>{<span class="function">len</span>(<span class="variable">result</span>[<span class="string">'detections'</span>])}<span class="string"> species"</span>)
261
  <span class="keyword">for</span> <span class="variable">detection</span> <span class="keyword">in</span> <span class="variable">result</span>[<span class="string">'detections'</span>]:
262
  <span class="function">print</span>(<span class="string">f"- </span>{<span class="variable">detection</span>[<span class="string">'class_name'</span>]}<span class="string">: </span>{<span class="variable">detection</span>[<span class="string">'confidence'</span>]:<span class="string">.2%</span>}<span class="string">"</span>)</pre>
263
+ </div>
264
+ </div>
265
 
266
+ <!-- JavaScript Tab -->
267
+ <div class="tab-content" id="javascript-tab">
268
+ <div class="code-section">
269
+ <div class="code-header">
270
+ <span class="code-title">JavaScript Request</span>
271
+ <button class="copy-button" onclick="copyCode('js-code')">Copy</button>
272
+ </div>
273
  <pre class="code-block" id="js-code"><span class="comment">// Convert file to base64</span>
274
  <span class="keyword">function</span> <span class="function">fileToBase64</span>(<span class="variable">file</span>) {
275
  <span class="keyword">return</span> <span class="keyword">new</span> <span class="function">Promise</span>((<span class="variable">resolve</span>, <span class="variable">reject</span>) <span class="operator">=></span> {
 
302
  });
303
  })
304
  .<span class="function">catch</span>(<span class="variable">error</span> <span class="operator">=></span> <span class="variable">console</span>.<span class="function">error</span>(<span class="string">'Error:'</span>, <span class="variable">error</span>));</pre>
305
+ </div>
306
+ </div>
307
 
308
+ <!-- C# Tab -->
309
+ <div class="tab-content" id="csharp-tab">
310
+ <div class="code-section">
311
+ <div class="code-header">
312
+ <span class="code-title">C# Request</span>
313
+ <button class="copy-button" onclick="copyCode('csharp-code')">Copy</button>
314
+ </div>
315
  <pre class="code-block" id="csharp-code"><span class="keyword">using</span> <span class="namespace">System</span>;
316
  <span class="keyword">using</span> <span class="namespace">System.IO</span>;
317
  <span class="keyword">using</span> <span class="namespace">System.Net.Http</span>;
 
342
 
343
  <span class="keyword">var</span> <span class="variable">result</span> <span class="operator">=</span> <span class="keyword">await</span> <span class="variable">response</span>.<span class="property">Content</span>.<span class="function">ReadAsStringAsync</span>();
344
  <span class="class">Console</span>.<span class="function">WriteLine</span>(<span class="variable">result</span>);</pre>
345
+ </div>
346
+ </div>
347
+
348
+ <!-- Response Tab -->
349
+ <div class="tab-content" id="response-tab">
350
+ <div class="response-demo">
351
+ <div class="response-title">Example API Response</div>
352
+ <div class="response-description">
353
+ Actual response from testing with a marine image - detected <strong>8 marine species</strong> in 1.79 seconds:
354
  </div>
355
 
356
+ <div class="detection-summary">
357
+ <div class="detection-item">
358
+ <span class="species-name">Sebastolobus (Rockfish)</span>
359
+ <span class="confidence-badge confidence-high">86.7%</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
360
  </div>
361
+ <div class="detection-item">
362
+ <span class="species-name">Octocorallia (Soft Coral)</span>
363
+ <span class="confidence-badge confidence-medium">69.7%</span>
 
364
  </div>
365
+ <div class="detection-item">
366
+ <span class="species-name">Psolus squamatus (Sea Cucumber)</span>
367
+ <span class="confidence-badge confidence-medium">66.3%</span>
368
+ </div>
369
+ </div>
370
+ </div>
371
+
372
+ <div class="code-section">
373
+ <div class="code-header">
374
+ <span class="code-title">JSON Response</span>
375
+ <button class="copy-button" onclick="copyCode('response-code')">Copy</button>
376
+ </div>
377
  <pre class="code-block" id="response-code">{
378
  <span class="json-key">"detections"</span>: [
379
  {
 
408
  </div>
409
  </div>
410
 
411
+ <!-- Documentation Footer -->
412
+ <div class="docs-footer">
413
+ <div class="info-grid">
414
+ <div class="info-card">
415
+ <h4>Request Parameters</h4>
416
+ <ul class="info-list">
417
+ <li><strong>image</strong> (required): Base64 encoded image data</li>
418
+ <li><strong>confidence_threshold</strong>: Minimum confidence (0.0-1.0, default: 0.25)</li>
419
+ <li><strong>iou_threshold</strong>: IoU threshold (0.0-1.0, default: 0.45)</li>
420
+ <li><strong>return_annotated_image</strong>: Return annotated image (boolean, default: true)</li>
421
+ </ul>
422
+ </div>
423
+ <div class="info-card">
424
+ <h4>Response Format</h4>
425
+ <ul class="info-list">
426
+ <li><strong>detections</strong>: Array of detected species with bounding boxes</li>
427
+ <li><strong>processing_time</strong>: Time taken for inference in seconds</li>
428
+ <li><strong>model_info</strong>: Information about the AI model used</li>
429
+ <li><strong>image_dimensions</strong>: Original image width and height</li>
430
+ </ul>
431
+ </div>
432
+ <div class="info-card">
433
+ <h4>Model Information</h4>
434
+ <ul class="info-list">
435
+ <li><strong>Model</strong>: marina-benthic-33k</li>
436
+ <li><strong>Species</strong>: 691 marine species supported</li>
437
+ <li><strong>Performance</strong>: ~2 seconds average processing</li>
438
+ <li><strong>Accuracy</strong>: High precision bounding boxes</li>
439
+ </ul>
440
  </div>
441
  </div>
442
  </div>
443
+ </div>
444
  </div>
445
  </div>
446
  {% endblock %}