dokii commited on
Commit
c954c29
Β·
verified Β·
1 Parent(s): 3d1d381

You are Aurora, the UI/UX Designer for the Qdrant Service frontend project. Your primary responsibility is to translate the project's goals and user needs into visually appealing, intuitive, and accessible user interfaces.

Browse files

**Project Goal:** Bootstrap a Bootstrap 5 powered frontend for the Qdrant Service.

**Your Core Directives:**

1. **Adhere to Design Language:** Strictly follow the established design language, including the color palette, typography, and component styles previously defined. Ensure all generated UI elements are consistent with this language.
2. **Bootstrap 5 Integration:** Design all components and layouts with Bootstrap 5 in mind. Utilize its grid system, utility classes, and pre-built components where appropriate. Your designs should be easily implementable by the Engineer.
3. **Accessibility First:** Prioritize accessibility in all design decisions. This includes:
* Ensuring sufficient color contrast ratios (WCAG AA minimum).
* Designing clear focus states for interactive elements.
* Using semantic HTML structures that support screen readers.
* Providing clear and concise labels for all form elements and interactive components.
* Considering different screen sizes and input methods (keyboard navigation).
4. **Intuitive User Flows:** Design user flows that are logical and easy to understand. Ensure navigation is clear and users can accomplish their tasks efficiently.
5. **Visual Aesthetics:** Create a clean, minimalist, and natural aesthetic. Focus on visual balance, whitespace, and a hierarchy that guides the user's attention effectively.
6. **Deliverables:** Produce specific design artifacts as requested, such as:
* High-fidelity mockups for key pages/components.
* Detailed component specifications.
* Interactive prototypes (if requested).
* Iconography specifications.

**Current Context:** You have access to the sitemap and wireframes, which outline the application's structure and basic user flows. You have also been provided with the backend code to understand the service's capabilities.

**Your Task:** Based on the existing wireframes and design language, create high-fidelity mockups for the main pages (Home, Models, Index Image, Search) and define any specific interactive component behaviors or states not fully covered in the wireframes. Ensure all designs are production-ready for implementation by the Engineer.


--- ---

The overall goal is: 'Bootstrap a Bootstrap 5 powered frontend for the Qdrant Service'

Your role's specific goal is: 'Implement designs into clean, modular, and performant code, focusing on responsive design and accessibility.'
Your specific sub-task is: 'Prepare the frontend application for deployment, including build processes and configuration for a production environment.'

The team's roles are:
[Role(title='Task-Agnostic Step (TAS) extractor', purpose='Identify and extract granular, actionable steps from high-level goals, ensuring no task-specific knowledge is required for this extraction process. These steps should be general enough to be assigned to various specialized agents.'), Role(title='Prompt Engineer', purpose='Refine system prompts for AI agents based on their roles and the specific tasks they are assigned. This ensures clear communication, effective workflow structuring, and optimal performance of each agent.'), Role(title='Designer', purpose='Generate aesthetic layouts, color palettes, typography, and UI flows for the frontend. Ensure designs are accessible, visually balanced, and align with the overall project requirements.'), Role(title='Engineer', purpose='Implement the designed frontend components into clean, modular, and performant code. Focus on responsive design, accessibility, and seamless integration with the backend API.')]

Please use the following outputs from the other agents as your input:

--- Artifact 'files' from (User) in [initial]:
{
"path": "main.py",
"content": "import traceback\nfrom fastapi import FastAPI, HTTPException\nfrom pydantic import BaseModel\nfrom typing import List, Dict, Any\nfrom qdrant_client import QdrantClient, models\nimport time\nimport base64\nimport io\nfrom PIL import Image\nimport open_clip\nimport uuid\nimport hashlib\nimport torch\n\n# --- Configuration ---\nQDRANT_HOST = \"localhost\"\nQDRANT_PORT = 6333\nSIMILARITY_THRESHOLD = 0.75 # Example threshold\nIMAGE_COLLECTION_NAME = \"image_metadata\"\n\n# Model-specific configurations, including vector dimensions.\nMODEL_CONFIG = {\n \"ViT-B-32\": {\"dim\": 512, \"description\": \"ViT-B-32 from OpenAI\", \"pretrained\": \"openai\"},\n \"RN50\": {\"dim\": 1024, \"description\": \"ResNet-50 from OpenAI\", \"pretrained\": \"openai\"},\n}\n\n# --- Pydantic Models ---\nclass ModelInfo(BaseModel):\n name: str\n description: str\n dim: int\n\nclass TextBenchmarkRequest(BaseModel):\n query: str\n model_name: str\n\nclass ImageBenchmarkRequest(BaseModel):\n image_base64: str\n model_name: str\n\nclass IndexImageRequest(BaseModel):\n image_base64: str\n metadata: Dict[str, Any]\n\nclass SearchResult(BaseModel):\n image_id: str\n metadata: Dict[str, Any]\n score: float\n\nclass BenchmarkResponse(BaseModel):\n model_name: str\n results: List[SearchResult]\n latency_ms: float\n\n# --- FastAPI App Setup ---\napp = FastAPI()\n\n# --- Qdrant Client Initialization ---\nclass QdrantService:\n def __init__(self, host: str, port: int):\n #self.client = QdrantClient(host=host, port=port)\n self.client = QdrantClient(path=\"./qdrant_data\") # Using local storage for simplicity\n self._loaded_models = {}\n self.device = \"cuda\" if torch.cuda.is_available() else \"cpu\"\n print(f\"Using device: {self.device}\")\n\n\n def get_available_models(self) -> List[ModelInfo]:\n # In a real scenario, this could also query a model registry or check available collections.\n # For now, we use the configured models.\n model_names = [\n ModelInfo(name=name, description=config[\"description\"], dim=config[\"dim\"]) for name, config in MODEL_CONFIG.items()\n ]\n return model_names\n\n def _get_model_collection_name(self, model_name: str) -> str:\n return f\"namespace-{model_name}\"\n\n def _load_model(self, model_name: str):\n if model_name not in self._loaded_models:\n print(f\"Loading model {model_name}...\")\n pretrained = MODEL_CONFIG[model_name].get(\"pretrained\", \"\")\n model, _, preprocess = open_clip.create_model_and_transforms(\n model_name, pretrained=pretrained, device=self.device\n )\n tokenizer = open_clip.get_tokenizer(model_name)\n self._loaded_models[model_name] = (model, preprocess, tokenizer)\n return self._loaded_models[model_name]\n\n def _get_embedding(self, text_or_image: Any, model_name: str) -> List[float]:\n model, preprocess, tokenizer = self._load_model(model_name)\n\n with torch.no_grad(), torch.cuda.amp.autocast():\n if isinstance(text_or_image, str):\n text = tokenizer(text_or_image).to(self.device)\n embedding = model.encode_text(text)\n elif isinstance(text_or_image, Image.Image):\n image = preprocess(text_or_image).unsqueeze(0).to(self.device)\n embedding = model.encode_image(image)\n else:\n raise ValueError(\"Input must be a string or a PIL Image.\")\n\n embedding /= embedding.norm(dim=-1, keepdim=True)\n\n return embedding.cpu().numpy().flatten().tolist()\n\n def search_by_text(self, query: str, model_name: str, limit: int = 10) -> List[SearchResult]:\n collection_name = self._get_model_collection_name(model_name)\n try:\n query_vector = self._get_embedding(query, model_name)\n \n search_result = self.client.search(\n collection_name=collection_name,\n query_vector=query_vector,\n limit=limit,\n query_filter=models.Filter(\n must_not=[\n models.FieldCondition(key=\"score\", range=models.Range(lt=SIMILARITY_THRESHOLD))\n ]\n )\n )\n \n results = []\n for hit in search_result:\n # Fetch metadata from the metadata collection\n metadata_response = self.client.retrieve(\n collection_name=IMAGE_COLLECTION_NAME,\n ids=[hit.id],\n with_payload=True\n )\n if metadata_response:\n results.append(SearchResult(\n image_id=hit.id,\n metadata=metadata_response[0].payload,\n score=hit.score\n ))\n return results\n except Exception as e:\n print(f\"Error searching text in {model_name}: {e}\")\n raise HTTPException(status_code=500, detail=f\"Error performing text search for model {model_name}\")\n\n def search_by_image(self, image_base64: str, model_name: str, limit: int = 10) -> List[SearchResult]:\n collection_name = self._get_model_collection_name(model_name)\n try:\n image_bytes = base64.b64decode(image_base64)\n image = Image.open(io.BytesIO(image_bytes))\n \n query_vector = self._get_embedding(image, model_name)\n\n search_result = self.client.search(\n collection_name=collection_name,\n query_vector=query_vector,\n limit=limit,\n query_filter=models.Filter(\n must_not=[\n models.FieldCondition(key=\"score\", range=models.Range(lt=SIMILARITY_THRESHOLD))\n ]\n )\n )\n \n results = []\n for hit in search_result:\n # Fetch metadata from the metadata collection\n metadata_response = self.clie

Files changed (2) hide show
  1. README.md +8 -5
  2. index.html +305 -18
README.md CHANGED
@@ -1,10 +1,13 @@
1
  ---
2
- title: Qdrant Vision Quest
3
- emoji: πŸ“ˆ
4
- colorFrom: pink
5
- colorTo: green
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
1
  ---
2
+ title: Qdrant Vision Quest πŸš€
3
+ colorFrom: purple
4
+ colorTo: blue
5
+ emoji: 🐳
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite-v3
10
  ---
11
 
12
+ # Welcome to your new DeepSite project!
13
+ This project was created with [DeepSite](https://deepsite.hf.co).
index.html CHANGED
@@ -1,19 +1,306 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  </html>
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Qdrant Vision Quest - AI Image Search</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <script src="https://unpkg.com/feather-icons"></script>
9
+ <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
10
+ <style>
11
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap');
12
+ body {
13
+ font-family: 'Inter', sans-serif;
14
+ background-color: #f8fafc;
15
+ }
16
+ .hero-gradient {
17
+ background: linear-gradient(135deg, #6366f1 0%, #8b5cf6 50%, #ec4899 100%);
18
+ }
19
+ .card-hover:hover {
20
+ transform: translateY(-5px);
21
+ box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);
22
+ }
23
+ .search-input {
24
+ transition: all 0.3s ease;
25
+ }
26
+ .search-input:focus {
27
+ box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.3);
28
+ }
29
+ </style>
30
+ </head>
31
+ <body class="min-h-screen">
32
+ <!-- Navigation -->
33
+ <nav class="bg-white shadow-sm">
34
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
35
+ <div class="flex justify-between h-16">
36
+ <div class="flex items-center">
37
+ <div class="flex-shrink-0 flex items-center">
38
+ <i data-feather="search" class="h-8 w-8 text-indigo-600"></i>
39
+ <span class="ml-2 text-xl font-bold text-gray-900">Qdrant Vision Quest</span>
40
+ </div>
41
+ <div class="hidden sm:ml-6 sm:flex sm:space-x-8">
42
+ <a href="#" class="border-indigo-500 text-gray-900 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Home</a>
43
+ <a href="#" class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Search</a>
44
+ <a href="#" class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">Models</a>
45
+ <a href="#" class="border-transparent text-gray-500 hover:border-gray-300 hover:text-gray-700 inline-flex items-center px-1 pt-1 border-b-2 text-sm font-medium">API</a>
46
+ </div>
47
+ </div>
48
+ <div class="hidden sm:ml-6 sm:flex sm:items-center">
49
+ <button class="bg-indigo-600 hover:bg-indigo-700 text-white px-4 py-2 rounded-md text-sm font-medium transition duration-150 ease-in-out">
50
+ Get Started
51
+ </button>
52
+ </div>
53
+ <div class="-mr-2 flex items-center sm:hidden">
54
+ <button type="button" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-gray-500 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-indigo-500" aria-expanded="false">
55
+ <span class="sr-only">Open main menu</span>
56
+ <i data-feather="menu" class="block h-6 w-6"></i>
57
+ </button>
58
+ </div>
59
+ </div>
60
+ </div>
61
+ </nav>
62
+
63
+ <!-- Hero Section -->
64
+ <div class="hero-gradient text-white">
65
+ <div class="max-w-7xl mx-auto py-16 px-4 sm:py-24 sm:px-6 lg:px-8 text-center">
66
+ <h1 class="text-4xl font-extrabold tracking-tight sm:text-5xl lg:text-6xl">
67
+ Discover Images with AI Power
68
+ </h1>
69
+ <p class="mt-6 max-w-2xl mx-auto text-xl text-indigo-100">
70
+ Qdrant Vision Quest harnesses cutting-edge machine learning to help you find and organize visual content like never before.
71
+ </p>
72
+ <div class="mt-10 flex justify-center">
73
+ <div class="rounded-md shadow">
74
+ <a href="#" class="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-indigo-600 bg-white hover:bg-gray-50 md:py-4 md:text-lg md:px-10">
75
+ Try Demo
76
+ </a>
77
+ </div>
78
+ <div class="ml-3 rounded-md shadow">
79
+ <a href="#" class="w-full flex items-center justify-center px-8 py-3 border border-transparent text-base font-medium rounded-md text-white bg-indigo-500 bg-opacity-60 hover:bg-opacity-70 md:py-4 md:text-lg md:px-10">
80
+ Learn More
81
+ </a>
82
+ </div>
83
+ </div>
84
+ </div>
85
+ </div>
86
+
87
+ <!-- Features Section -->
88
+ <div class="py-12 bg-white">
89
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
90
+ <div class="lg:text-center">
91
+ <h2 class="text-base text-indigo-600 font-semibold tracking-wide uppercase">Features</h2>
92
+ <p class="mt-2 text-3xl leading-8 font-extrabold tracking-tight text-gray-900 sm:text-4xl">
93
+ A better way to search images
94
+ </p>
95
+ <p class="mt-4 max-w-2xl text-xl text-gray-500 lg:mx-auto">
96
+ Leverage state-of-the-art visual search technology powered by Qdrant vector database.
97
+ </p>
98
+ </div>
99
+
100
+ <div class="mt-10">
101
+ <div class="grid grid-cols-1 gap-10 sm:grid-cols-2 lg:grid-cols-3">
102
+ <!-- Feature 1 -->
103
+ <div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover transition duration-300">
104
+ <div class="flex items-center justify-center h-12 w-12 rounded-md bg-indigo-500 text-white">
105
+ <i data-feather="search"></i>
106
+ </div>
107
+ <div class="mt-6">
108
+ <h3 class="text-lg font-medium text-gray-900">Semantic Search</h3>
109
+ <p class="mt-2 text-base text-gray-500">
110
+ Find images based on meaning, not just keywords. Our AI understands context.
111
+ </p>
112
+ </div>
113
+ </div>
114
+
115
+ <!-- Feature 2 -->
116
+ <div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover transition duration-300">
117
+ <div class="flex items-center justify-center h-12 w-12 rounded-md bg-purple-500 text-white">
118
+ <i data-feather="upload"></i>
119
+ </div>
120
+ <div class="mt-6">
121
+ <h3 class="text-lg font-medium text-gray-900">Image Indexing</h3>
122
+ <p class="mt-2 text-base text-gray-500">
123
+ Easily add your own images to the database with customizable metadata.
124
+ </p>
125
+ </div>
126
+ </div>
127
+
128
+ <!-- Feature 3 -->
129
+ <div class="bg-gray-50 p-6 rounded-lg shadow-sm card-hover transition duration-300">
130
+ <div class="flex items-center justify-center h-12 w-12 rounded-md bg-pink-500 text-white">
131
+ <i data-feather="cpu"></i>
132
+ </div>
133
+ <div class="mt-6">
134
+ <h3 class="text-lg font-medium text-gray-900">Multiple Models</h3>
135
+ <p class="mt-2 text-base text-gray-500">
136
+ Choose from different AI models to optimize for speed or accuracy.
137
+ </p>
138
+ </div>
139
+ </div>
140
+ </div>
141
+ </div>
142
+ </div>
143
+ </div>
144
+
145
+ <!-- Demo Search Section -->
146
+ <div class="py-12 bg-gray-50">
147
+ <div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8">
148
+ <div class="text-center">
149
+ <h2 class="text-3xl font-extrabold text-gray-900 sm:text-4xl">
150
+ Try it out
151
+ </h2>
152
+ <p class="mt-4 text-lg text-gray-500">
153
+ Experience the power of visual search with our interactive demo.
154
+ </p>
155
+ </div>
156
+ <div class="mt-10 bg-white shadow rounded-lg p-6">
157
+ <div class="relative">
158
+ <div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
159
+ <i data-feather="search" class="h-5 w-5 text-gray-400"></i>
160
+ </div>
161
+ <input id="search" name="search" class="search-input block w-full pl-10 pr-3 py-3 border border-gray-300 rounded-md leading-5 bg-white placeholder-gray-500 focus:outline-none focus:placeholder-gray-400 focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm" placeholder="Search for images..." type="search">
162
+ </div>
163
+ <div class="mt-6 grid grid-cols-2 gap-4 sm:grid-cols-3">
164
+ <div class="relative">
165
+ <div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden">
166
+ <img src="http://static.photos/nature/320x240/1" alt="Nature" class="w-full h-full object-cover">
167
+ </div>
168
+ <button class="absolute top-2 right-2 bg-white p-1 rounded-full shadow-sm text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
169
+ <i data-feather="heart" class="h-4 w-4"></i>
170
+ </button>
171
+ </div>
172
+ <div class="relative">
173
+ <div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden">
174
+ <img src="http://static.photos/cityscape/320x240/2" alt="City" class="w-full h-full object-cover">
175
+ </div>
176
+ <button class="absolute top-2 right-2 bg-white p-1 rounded-full shadow-sm text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
177
+ <i data-feather="heart" class="h-4 w-4"></i>
178
+ </button>
179
+ </div>
180
+ <div class="relative">
181
+ <div class="aspect-w-1 aspect-h-1 bg-gray-200 rounded-lg overflow-hidden">
182
+ <img src="http://static.photos/food/320x240/3" alt="Food" class="w-full h-full object-cover">
183
+ </div>
184
+ <button class="absolute top-2 right-2 bg-white p-1 rounded-full shadow-sm text-gray-400 hover:text-gray-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
185
+ <i data-feather="heart" class="h-4 w-4"></i>
186
+ </button>
187
+ </div>
188
+ </div>
189
+ <div class="mt-6">
190
+ <button class="w-full flex justify-center items-center px-4 py-2 border border-gray-300 shadow-sm text-sm font-medium rounded-md text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
191
+ Load More Results
192
+ </button>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+
198
+ <!-- CTA Section -->
199
+ <div class="bg-indigo-700">
200
+ <div class="max-w-2xl mx-auto text-center py-16 px-4 sm:py-20 sm:px-6 lg:px-8">
201
+ <h2 class="text-3xl font-extrabold text-white sm:text-4xl">
202
+ <span class="block">Ready to dive in?</span>
203
+ <span class="block">Start your visual search journey today.</span>
204
+ </h2>
205
+ <p class="mt-4 text-lg leading-6 text-indigo-200">
206
+ Integrate our API or use our hosted solution to power your applications.
207
+ </p>
208
+ <a href="#" class="mt-8 w-full inline-flex items-center justify-center px-5 py-3 border border-transparent text-base font-medium rounded-md text-indigo-600 bg-white hover:bg-indigo-50 sm:w-auto">
209
+ Sign up for free
210
+ </a>
211
+ </div>
212
+ </div>
213
+
214
+ <!-- Footer -->
215
+ <footer class="bg-gray-800">
216
+ <div class="max-w-7xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
217
+ <div class="grid grid-cols-2 gap-8 md:grid-cols-4">
218
+ <div class="space-y-4">
219
+ <h3 class="text-sm font-semibold text-gray-300 tracking-wider uppercase">Product</h3>
220
+ <div class="space-y-2">
221
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Features </a>
222
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Pricing </a>
223
+ <a href="#" class="text-base text-gray-400 hover:text-white"> API </a>
224
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Integrations </a>
225
+ </div>
226
+ </div>
227
+ <div class="space-y-4">
228
+ <h3 class="text-sm font-semibold text-gray-300 tracking-wider uppercase">Resources</h3>
229
+ <div class="space-y-2">
230
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Documentation </a>
231
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Guides </a>
232
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Blog </a>
233
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Support </a>
234
+ </div>
235
+ </div>
236
+ <div class="space-y-4">
237
+ <h3 class="text-sm font-semibold text-gray-300 tracking-wider uppercase">Company</h3>
238
+ <div class="space-y-2">
239
+ <a href="#" class="text-base text-gray-400 hover:text-white"> About </a>
240
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Careers </a>
241
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Privacy </a>
242
+ <a href="#" class="text-base text-gray-400 hover:text-white"> Terms </a>
243
+ </div>
244
+ </div>
245
+ <div class="space-y-4">
246
+ <h3 class="text-sm font-semibold text-gray-300 tracking-wider uppercase">Connect</h3>
247
+ <div class="flex space-x-6">
248
+ <a href="#" class="text-gray-400 hover:text-white">
249
+ <i data-feather="twitter" class="h-6 w-6"></i>
250
+ </a>
251
+ <a href="#" class="text-gray-400 hover:text-white">
252
+ <i data-feather="github" class="h-6 w-6"></i>
253
+ </a>
254
+ <a href="#" class="text-gray-400 hover:text-white">
255
+ <i data-feather="linkedin" class="h-6 w-6"></i>
256
+ </a>
257
+ <a href="#" class="text-gray-400 hover:text-white">
258
+ <i data-feather="mail" class="h-6 w-6"></i>
259
+ </a>
260
+ </div>
261
+ </div>
262
+ </div>
263
+ <div class="mt-12 border-t border-gray-700 pt-8 flex justify-between">
264
+ <p class="text-base text-gray-400">
265
+ &copy; 2023 Qdrant Vision Quest. All rights reserved.
266
+ </p>
267
+ <div class="flex space-x-6">
268
+ <a href="#" class="text-gray-400 hover:text-white">
269
+ <span class="sr-only">Privacy Policy</span>
270
+ Privacy
271
+ </a>
272
+ <a href="#" class="text-gray-400 hover:text-white">
273
+ <span class="sr-only">Terms of Service</span>
274
+ Terms
275
+ </a>
276
+ </div>
277
+ </div>
278
+ </div>
279
+ </footer>
280
+
281
+ <script>
282
+ feather.replace();
283
+
284
+ // Simple animation for the features on scroll
285
+ document.addEventListener('DOMContentLoaded', function() {
286
+ const featureCards = document.querySelectorAll('.card-hover');
287
+
288
+ const observer = new IntersectionObserver((entries) => {
289
+ entries.forEach(entry => {
290
+ if (entry.isIntersecting) {
291
+ entry.target.style.opacity = '1';
292
+ entry.target.style.transform = 'translateY(0)';
293
+ }
294
+ });
295
+ }, { threshold: 0.1 });
296
+
297
+ featureCards.forEach((card, index) => {
298
+ card.style.opacity = '0';
299
+ card.style.transform = 'translateY(20px)';
300
+ card.style.transition = `opacity 0.5s ease ${index * 0.1}s, transform 0.5s ease ${index * 0.1}s`;
301
+ observer.observe(card);
302
+ });
303
+ });
304
+ </script>
305
+ </body>
306
  </html>