vectra-client 0.3.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +10 -0
- data/CHANGELOG.md +26 -8
- data/README.md +35 -2
- data/docs/_layouts/default.html +1 -0
- data/docs/_layouts/home.html +44 -3
- data/docs/_layouts/page.html +42 -9
- data/docs/assets/style.css +226 -1
- data/docs/examples/index.md +9 -0
- data/docs/examples/real-world.md +576 -0
- data/docs/grafana_final.png +0 -0
- data/docs/guides/getting-started.md +70 -2
- data/docs/guides/monitoring.md +50 -0
- data/docs/providers/index.md +12 -0
- data/docs/providers/memory.md +145 -0
- data/docs/providers/weaviate.md +84 -25
- data/examples/GRAFANA_QUICKSTART.md +158 -0
- data/examples/README.md +332 -0
- data/examples/comprehensive_demo.rb +1116 -0
- data/examples/grafana-dashboard.json +878 -0
- data/examples/grafana-setup.md +340 -0
- data/examples/prometheus-exporter.rb +229 -0
- data/lib/vectra/batch.rb +63 -8
- data/lib/vectra/client.rb +188 -1
- data/lib/vectra/configuration.rb +4 -2
- data/lib/vectra/credential_rotation.rb +2 -3
- data/lib/vectra/providers/base.rb +19 -1
- data/lib/vectra/providers/memory.rb +298 -0
- data/lib/vectra/providers/qdrant.rb +31 -0
- data/lib/vectra/providers/weaviate.rb +454 -10
- data/lib/vectra/vector.rb +56 -0
- data/lib/vectra/version.rb +1 -1
- data/lib/vectra.rb +20 -0
- data/vectra.gemspec +56 -0
- metadata +12 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: b0d48b8a6205df9a0d6545e3772e26da09f826f03d56751a6fa997e1a73d89f1
|
|
4
|
+
data.tar.gz: 25dc65ad327e03e7912a0b938739b6acf1d6708efd8fa41773d9bbae1053e3dc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 68fc7d7a2c941733bb8f42007dffa52989daedeb362da62c094d05dec7d02f8ca6d7ca8763194e9b51b4ecfe3f7a6e8db4418c7589caab31943f055f75f4c48a
|
|
7
|
+
data.tar.gz: f40ab28eb011943d4961e22c5d31b5a816a81cea1a2bf6afa238004adaa1cdd8558f10b0ee8d56376d6fc737788b16fc1acb7088778d8461ecb3a8db2ff85580
|
data/.rubocop.yml
CHANGED
|
@@ -11,6 +11,7 @@ AllCops:
|
|
|
11
11
|
- 'bin/**/*'
|
|
12
12
|
- 'node_modules/**/*'
|
|
13
13
|
- 'lib/generators/**/templates/**/*'
|
|
14
|
+
- 'examples/**/*'
|
|
14
15
|
|
|
15
16
|
# Layout
|
|
16
17
|
Layout/LineLength:
|
|
@@ -30,6 +31,7 @@ Metrics/BlockLength:
|
|
|
30
31
|
- 'vectra.gemspec'
|
|
31
32
|
- 'Rakefile'
|
|
32
33
|
- 'benchmarks/**/*'
|
|
34
|
+
- 'examples/**/*'
|
|
33
35
|
AllowedMethods:
|
|
34
36
|
- 'included'
|
|
35
37
|
- 'class_methods'
|
|
@@ -38,26 +40,34 @@ Metrics/MethodLength:
|
|
|
38
40
|
Max: 30
|
|
39
41
|
Exclude:
|
|
40
42
|
- 'spec/**/*'
|
|
43
|
+
- 'examples/**/*'
|
|
41
44
|
|
|
42
45
|
Metrics/AbcSize:
|
|
43
46
|
Max: 30
|
|
44
47
|
Exclude:
|
|
45
48
|
- 'spec/**/*'
|
|
49
|
+
- 'examples/**/*'
|
|
46
50
|
|
|
47
51
|
Metrics/ClassLength:
|
|
48
52
|
Max: 250
|
|
49
53
|
Exclude:
|
|
50
54
|
- 'spec/**/*'
|
|
55
|
+
- 'examples/**/*'
|
|
51
56
|
|
|
52
57
|
Metrics/ModuleLength:
|
|
53
58
|
Exclude:
|
|
54
59
|
- 'spec/**/*'
|
|
60
|
+
- 'examples/**/*'
|
|
55
61
|
|
|
56
62
|
Metrics/CyclomaticComplexity:
|
|
57
63
|
Max: 10
|
|
64
|
+
Exclude:
|
|
65
|
+
- 'examples/**/*'
|
|
58
66
|
|
|
59
67
|
Metrics/PerceivedComplexity:
|
|
60
68
|
Max: 10
|
|
69
|
+
Exclude:
|
|
70
|
+
- 'examples/**/*'
|
|
61
71
|
|
|
62
72
|
Metrics/ParameterLists:
|
|
63
73
|
Max: 7
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [v0.4.0](https://github.com/stokry/vectra/tree/v0.4.0) (2026-01-12)
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- Memory provider for in-memory vector storage
|
|
7
|
+
- QueryBuilder for chainable query API
|
|
8
|
+
- Batch operations with concurrent processing
|
|
9
|
+
- Vector normalization methods (L2, L1)
|
|
10
|
+
- Enhanced error message extraction
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
- Weaviate DELETE request query parameters
|
|
14
|
+
- Qdrant error message extraction from nested status
|
|
15
|
+
- Client ping error info capture
|
|
16
|
+
- Credential rotation timeout parameter handling
|
|
17
|
+
|
|
18
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v0.3.4...v0.4.0)
|
|
19
|
+
|
|
20
|
+
## [v0.3.4](https://github.com/stokry/vectra/tree/v0.3.4) (2026-01-12)
|
|
21
|
+
|
|
22
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v0.3.3...v0.3.4)
|
|
23
|
+
|
|
24
|
+
## [v0.3.3](https://github.com/stokry/vectra/tree/v0.3.3) (2026-01-09)
|
|
25
|
+
|
|
26
|
+
[Full Changelog](https://github.com/stokry/vectra/compare/v0.3.2...v0.3.3)
|
|
27
|
+
|
|
3
28
|
## [v0.3.2](https://github.com/stokry/vectra/tree/v0.3.2) (2026-01-08)
|
|
4
29
|
|
|
5
30
|
[Full Changelog](https://github.com/stokry/vectra/compare/v0.3.1...v0.3.2)
|
|
@@ -16,6 +41,7 @@
|
|
|
16
41
|
|
|
17
42
|
[Full Changelog](https://github.com/stokry/vectra/compare/v0.2.1...v0.2.2)
|
|
18
43
|
|
|
44
|
+
## [v0.2.1](https://github.com/stokry/vectra/tree/v0.2.1) (2026-01-08)
|
|
19
45
|
|
|
20
46
|
[Full Changelog](https://github.com/stokry/vectra/compare/v0.2.0...v0.2.1)
|
|
21
47
|
|
|
@@ -23,14 +49,6 @@
|
|
|
23
49
|
|
|
24
50
|
[Full Changelog](https://github.com/stokry/vectra/compare/v0.1.3...v0.2.0)
|
|
25
51
|
|
|
26
|
-
## [v0.3.3](https://github.com/stokry/vectra/tree/v0.3.3) (2026-01-09)
|
|
27
|
-
|
|
28
|
-
[Full Changelog](https://github.com/stokry/vectra/compare/v0.3.2...v0.3.3)
|
|
29
|
-
|
|
30
|
-
### Changed
|
|
31
|
-
|
|
32
|
-
- Version bump and minor maintenance release.
|
|
33
|
-
|
|
34
52
|
## [v0.1.3](https://github.com/stokry/vectra/tree/v0.1.3) (2026-01-07)
|
|
35
53
|
|
|
36
54
|
[Full Changelog](https://github.com/stokry/vectra/compare/v0.1.1...v0.1.3)
|
data/README.md
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
| **Qdrant** | Open Source | ✅ Supported |
|
|
18
18
|
| **Weaviate** | Open Source | ✅ Supported |
|
|
19
19
|
| **pgvector** | PostgreSQL | ✅ Supported |
|
|
20
|
+
| **Memory** | In-Memory | ✅ Testing only |
|
|
20
21
|
|
|
21
22
|
## Installation
|
|
22
23
|
|
|
@@ -48,12 +49,38 @@ client.upsert(
|
|
|
48
49
|
]
|
|
49
50
|
)
|
|
50
51
|
|
|
51
|
-
# Search
|
|
52
|
+
# Search (classic API)
|
|
52
53
|
results = client.query(vector: [0.1, 0.2, 0.3], top_k: 5)
|
|
53
54
|
results.each { |match| puts "#{match.id}: #{match.score}" }
|
|
54
55
|
|
|
56
|
+
# Search (chainable Query Builder)
|
|
57
|
+
results = client
|
|
58
|
+
.query('docs')
|
|
59
|
+
.vector([0.1, 0.2, 0.3])
|
|
60
|
+
.top_k(5)
|
|
61
|
+
.with_metadata
|
|
62
|
+
.execute
|
|
63
|
+
|
|
64
|
+
results.each do |match|
|
|
65
|
+
puts "#{match.id}: #{match.score}"
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Normalize embeddings (for better cosine similarity)
|
|
69
|
+
embedding = openai_response['data'][0]['embedding']
|
|
70
|
+
normalized = Vectra::Vector.normalize(embedding)
|
|
71
|
+
client.upsert(vectors: [{ id: 'doc-1', values: normalized }])
|
|
72
|
+
|
|
55
73
|
# Delete
|
|
56
74
|
client.delete(ids: ['doc-1', 'doc-2'])
|
|
75
|
+
|
|
76
|
+
# Health check
|
|
77
|
+
if client.healthy?
|
|
78
|
+
puts "Connection is healthy"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Ping with latency
|
|
82
|
+
status = client.ping
|
|
83
|
+
puts "Provider: #{status[:provider]}, Latency: #{status[:latency_ms]}ms"
|
|
57
84
|
```
|
|
58
85
|
|
|
59
86
|
## Provider Examples
|
|
@@ -69,10 +96,16 @@ client = Vectra.qdrant(host: 'http://localhost:6333')
|
|
|
69
96
|
client = Vectra.qdrant(host: 'https://your-cluster.qdrant.io', api_key: ENV['QDRANT_API_KEY'])
|
|
70
97
|
|
|
71
98
|
# Weaviate
|
|
72
|
-
client = Vectra.weaviate(
|
|
99
|
+
client = Vectra.weaviate(
|
|
100
|
+
api_key: ENV['WEAVIATE_API_KEY'],
|
|
101
|
+
host: 'https://your-weaviate-instance'
|
|
102
|
+
)
|
|
73
103
|
|
|
74
104
|
# pgvector (PostgreSQL)
|
|
75
105
|
client = Vectra.pgvector(connection_url: 'postgres://user:pass@localhost/mydb')
|
|
106
|
+
|
|
107
|
+
# Memory (in-memory, testing only)
|
|
108
|
+
client = Vectra.memory
|
|
76
109
|
```
|
|
77
110
|
|
|
78
111
|
## Features
|
data/docs/_layouts/default.html
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
<title>{{ page.title }} - {{ site.title }}</title>
|
|
8
8
|
<link rel="stylesheet" href="{{ site.baseurl }}/assets/style.css">
|
|
9
9
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>◆</text></svg>">
|
|
10
|
+
<script defer src="https://umami-production-dfb8.up.railway.app/script.js" data-website-id="07e5420c-12d1-4e3c-9dbd-5cecb15a878f"></script>
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
13
|
{{ content }}
|
data/docs/_layouts/home.html
CHANGED
|
@@ -7,13 +7,19 @@
|
|
|
7
7
|
<title>{{ page.title }} - {{ site.title }}</title>
|
|
8
8
|
<link rel="stylesheet" href="{{ site.baseurl }}/assets/style.css">
|
|
9
9
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>◆</text></svg>">
|
|
10
|
+
<script defer src="https://umami-production-dfb8.up.railway.app/script.js" data-website-id="07e5420c-12d1-4e3c-9dbd-5cecb15a878f"></script>
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
13
|
<!-- Header -->
|
|
13
14
|
<header class="tma-header">
|
|
14
15
|
<nav class="tma-nav">
|
|
15
16
|
<a href="{{ site.baseurl }}/" class="tma-nav__brand">Vectra</a>
|
|
16
|
-
<
|
|
17
|
+
<button class="tma-nav__toggle" aria-label="Toggle menu" aria-expanded="false">
|
|
18
|
+
<span class="tma-nav__toggle-line"></span>
|
|
19
|
+
<span class="tma-nav__toggle-line"></span>
|
|
20
|
+
<span class="tma-nav__toggle-line"></span>
|
|
21
|
+
</button>
|
|
22
|
+
<ul class="tma-nav__menu" id="nav-menu">
|
|
17
23
|
<li><a href="{{ site.baseurl }}/guides/getting-started" class="tma-nav__link">Getting Started</a></li>
|
|
18
24
|
<li><a href="{{ site.baseurl }}/providers" class="tma-nav__link">Providers</a></li>
|
|
19
25
|
<li><a href="{{ site.baseurl }}/api/overview" class="tma-nav__link">API</a></li>
|
|
@@ -29,7 +35,7 @@
|
|
|
29
35
|
<!-- Hero Section -->
|
|
30
36
|
<section class="tma-hero">
|
|
31
37
|
<div class="tma-hero__container">
|
|
32
|
-
<span class="tma-hero__badge">v0.
|
|
38
|
+
<span class="tma-hero__badge">v0.3.3 — Grafana Dashboard & Monitoring</span>
|
|
33
39
|
<h1 class="tma-hero__title">
|
|
34
40
|
Vector Databases,<br>
|
|
35
41
|
<span class="tma-hero__title-gradient">Unified for Ruby.</span>
|
|
@@ -77,7 +83,7 @@
|
|
|
77
83
|
<span class="tma-feature-card__icon">📈</span>
|
|
78
84
|
<h3 class="tma-feature-card__title">Observable</h3>
|
|
79
85
|
<p class="tma-feature-card__description">
|
|
80
|
-
|
|
86
|
+
Grafana dashboard, Prometheus metrics, and native instrumentation for Datadog and New Relic. Track latency, throughput, and errors.
|
|
81
87
|
</p>
|
|
82
88
|
</div>
|
|
83
89
|
<div class="tma-feature-card">
|
|
@@ -183,5 +189,40 @@
|
|
|
183
189
|
</ul>
|
|
184
190
|
</div>
|
|
185
191
|
</footer>
|
|
192
|
+
<script>
|
|
193
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
194
|
+
const navToggle = document.querySelector('.tma-nav__toggle');
|
|
195
|
+
const navMenu = document.querySelector('.tma-nav__menu');
|
|
196
|
+
|
|
197
|
+
if (navToggle && navMenu) {
|
|
198
|
+
navToggle.addEventListener('click', function(e) {
|
|
199
|
+
e.preventDefault();
|
|
200
|
+
e.stopPropagation();
|
|
201
|
+
const isExpanded = navToggle.getAttribute('aria-expanded') === 'true';
|
|
202
|
+
navToggle.setAttribute('aria-expanded', !isExpanded);
|
|
203
|
+
navMenu.classList.toggle('tma-nav__menu--open');
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Close menu when clicking on a link
|
|
207
|
+
const navLinks = navMenu.querySelectorAll('.tma-nav__link');
|
|
208
|
+
navLinks.forEach(function(link) {
|
|
209
|
+
link.addEventListener('click', function() {
|
|
210
|
+
navToggle.setAttribute('aria-expanded', 'false');
|
|
211
|
+
navMenu.classList.remove('tma-nav__menu--open');
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
// Close menu when clicking outside
|
|
216
|
+
document.addEventListener('click', function(e) {
|
|
217
|
+
if (navMenu.classList.contains('tma-nav__menu--open') &&
|
|
218
|
+
!navMenu.contains(e.target) &&
|
|
219
|
+
!navToggle.contains(e.target)) {
|
|
220
|
+
navToggle.setAttribute('aria-expanded', 'false');
|
|
221
|
+
navMenu.classList.remove('tma-nav__menu--open');
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
</script>
|
|
186
227
|
</body>
|
|
187
228
|
</html>
|
data/docs/_layouts/page.html
CHANGED
|
@@ -7,13 +7,19 @@
|
|
|
7
7
|
<title>{{ page.title }} - {{ site.title }}</title>
|
|
8
8
|
<link rel="stylesheet" href="{{ site.baseurl }}/assets/style.css">
|
|
9
9
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>◆</text></svg>">
|
|
10
|
+
<script defer src="https://umami-production-dfb8.up.railway.app/script.js" data-website-id="07e5420c-12d1-4e3c-9dbd-5cecb15a878f"></script>
|
|
10
11
|
</head>
|
|
11
12
|
<body>
|
|
12
13
|
<!-- Header -->
|
|
13
14
|
<header class="tma-header">
|
|
14
15
|
<nav class="tma-nav">
|
|
15
16
|
<a href="{{ site.baseurl }}/" class="tma-nav__brand">Vectra</a>
|
|
16
|
-
<
|
|
17
|
+
<button class="tma-nav__toggle" aria-label="Toggle menu" aria-expanded="false">
|
|
18
|
+
<span class="tma-nav__toggle-line"></span>
|
|
19
|
+
<span class="tma-nav__toggle-line"></span>
|
|
20
|
+
<span class="tma-nav__toggle-line"></span>
|
|
21
|
+
</button>
|
|
22
|
+
<ul class="tma-nav__menu" id="nav-menu">
|
|
17
23
|
<li><a href="{{ site.baseurl }}/guides/getting-started" class="tma-nav__link">Getting Started</a></li>
|
|
18
24
|
<li><a href="{{ site.baseurl }}/providers" class="tma-nav__link">Providers</a></li>
|
|
19
25
|
<li><a href="{{ site.baseurl }}/api/overview" class="tma-nav__link">API</a></li>
|
|
@@ -58,14 +64,6 @@
|
|
|
58
64
|
</ul>
|
|
59
65
|
</div>
|
|
60
66
|
|
|
61
|
-
<div class="tma-sidebar__section">
|
|
62
|
-
<h3 class="tma-sidebar__title">Examples</h3>
|
|
63
|
-
<ul class="tma-sidebar__list">
|
|
64
|
-
<li><a href="{{ site.baseurl }}/examples" class="tma-sidebar__link {% if page.url == '/examples/' %}tma-sidebar__link--active{% endif %}">Overview</a></li>
|
|
65
|
-
<li><a href="{{ site.baseurl }}/examples/basic-usage" class="tma-sidebar__link {% if page.url == '/examples/basic-usage/' %}tma-sidebar__link--active{% endif %}">Basic Usage</a></li>
|
|
66
|
-
</ul>
|
|
67
|
-
</div>
|
|
68
|
-
|
|
69
67
|
<div class="tma-sidebar__section">
|
|
70
68
|
<h3 class="tma-sidebar__title">Community</h3>
|
|
71
69
|
<ul class="tma-sidebar__list">
|
|
@@ -80,5 +78,40 @@
|
|
|
80
78
|
{{ content }}
|
|
81
79
|
</main>
|
|
82
80
|
</div>
|
|
81
|
+
<script>
|
|
82
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
83
|
+
const navToggle = document.querySelector('.tma-nav__toggle');
|
|
84
|
+
const navMenu = document.querySelector('.tma-nav__menu');
|
|
85
|
+
|
|
86
|
+
if (navToggle && navMenu) {
|
|
87
|
+
navToggle.addEventListener('click', function(e) {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
const isExpanded = navToggle.getAttribute('aria-expanded') === 'true';
|
|
91
|
+
navToggle.setAttribute('aria-expanded', !isExpanded);
|
|
92
|
+
navMenu.classList.toggle('tma-nav__menu--open');
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Close menu when clicking on a link
|
|
96
|
+
const navLinks = navMenu.querySelectorAll('.tma-nav__link');
|
|
97
|
+
navLinks.forEach(function(link) {
|
|
98
|
+
link.addEventListener('click', function() {
|
|
99
|
+
navToggle.setAttribute('aria-expanded', 'false');
|
|
100
|
+
navMenu.classList.remove('tma-nav__menu--open');
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
// Close menu when clicking outside
|
|
105
|
+
document.addEventListener('click', function(e) {
|
|
106
|
+
if (navMenu.classList.contains('tma-nav__menu--open') &&
|
|
107
|
+
!navMenu.contains(e.target) &&
|
|
108
|
+
!navToggle.contains(e.target)) {
|
|
109
|
+
navToggle.setAttribute('aria-expanded', 'false');
|
|
110
|
+
navMenu.classList.remove('tma-nav__menu--open');
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
</script>
|
|
83
116
|
</body>
|
|
84
117
|
</html>
|
data/docs/assets/style.css
CHANGED
|
@@ -164,6 +164,40 @@ body {
|
|
|
164
164
|
border-color: var(--tma-color-border-hover);
|
|
165
165
|
}
|
|
166
166
|
|
|
167
|
+
.tma-nav__toggle {
|
|
168
|
+
display: none;
|
|
169
|
+
flex-direction: column;
|
|
170
|
+
justify-content: space-around;
|
|
171
|
+
width: 24px;
|
|
172
|
+
height: 24px;
|
|
173
|
+
background: transparent;
|
|
174
|
+
border: none;
|
|
175
|
+
cursor: pointer;
|
|
176
|
+
padding: 0;
|
|
177
|
+
z-index: 10;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
.tma-nav__toggle-line {
|
|
181
|
+
width: 100%;
|
|
182
|
+
height: 2px;
|
|
183
|
+
background: var(--tma-color-text-primary);
|
|
184
|
+
border-radius: 2px;
|
|
185
|
+
transition: all var(--tma-transition-normal);
|
|
186
|
+
transform-origin: center;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
.tma-nav__toggle[aria-expanded="true"] .tma-nav__toggle-line:nth-child(1) {
|
|
190
|
+
transform: rotate(45deg) translate(6px, 6px);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.tma-nav__toggle[aria-expanded="true"] .tma-nav__toggle-line:nth-child(2) {
|
|
194
|
+
opacity: 0;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.tma-nav__toggle[aria-expanded="true"] .tma-nav__toggle-line:nth-child(3) {
|
|
198
|
+
transform: rotate(-45deg) translate(6px, -6px);
|
|
199
|
+
}
|
|
200
|
+
|
|
167
201
|
/* ============================================
|
|
168
202
|
Hero Section
|
|
169
203
|
============================================ */
|
|
@@ -751,8 +785,49 @@ code {
|
|
|
751
785
|
padding: 0 var(--tma-spacing-md);
|
|
752
786
|
}
|
|
753
787
|
|
|
788
|
+
.tma-nav__toggle {
|
|
789
|
+
display: flex;
|
|
790
|
+
}
|
|
791
|
+
|
|
754
792
|
.tma-nav__menu {
|
|
755
|
-
display:
|
|
793
|
+
display: flex;
|
|
794
|
+
position: fixed;
|
|
795
|
+
top: var(--tma-header-height);
|
|
796
|
+
left: 0;
|
|
797
|
+
right: 0;
|
|
798
|
+
height: 0;
|
|
799
|
+
max-height: 400px;
|
|
800
|
+
background: rgba(10, 10, 15, 0.98);
|
|
801
|
+
backdrop-filter: blur(12px);
|
|
802
|
+
flex-direction: column;
|
|
803
|
+
align-items: stretch;
|
|
804
|
+
padding: 0;
|
|
805
|
+
gap: var(--tma-spacing-xs);
|
|
806
|
+
transform: translateX(100%);
|
|
807
|
+
transition: transform var(--tma-transition-normal), opacity var(--tma-transition-normal), height var(--tma-transition-normal), padding var(--tma-transition-normal);
|
|
808
|
+
z-index: 999;
|
|
809
|
+
overflow-y: auto;
|
|
810
|
+
opacity: 0;
|
|
811
|
+
pointer-events: none;
|
|
812
|
+
border-top: 1px solid var(--tma-color-border);
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.tma-nav__menu.tma-nav__menu--open {
|
|
816
|
+
transform: translateX(0);
|
|
817
|
+
opacity: 1;
|
|
818
|
+
pointer-events: auto;
|
|
819
|
+
height: 400px;
|
|
820
|
+
padding: var(--tma-spacing-lg);
|
|
821
|
+
}
|
|
822
|
+
|
|
823
|
+
.tma-nav__menu li {
|
|
824
|
+
width: 100%;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.tma-nav__link {
|
|
828
|
+
width: 100%;
|
|
829
|
+
padding: var(--tma-spacing-md);
|
|
830
|
+
justify-content: flex-start;
|
|
756
831
|
}
|
|
757
832
|
|
|
758
833
|
.tma-hero {
|
|
@@ -925,3 +1000,153 @@ code {
|
|
|
925
1000
|
color: #ef4444;
|
|
926
1001
|
font-weight: bold;
|
|
927
1002
|
}
|
|
1003
|
+
|
|
1004
|
+
/* ============================================
|
|
1005
|
+
Dashboard Showcase
|
|
1006
|
+
============================================ */
|
|
1007
|
+
.tma-dashboard-showcase {
|
|
1008
|
+
display: grid;
|
|
1009
|
+
grid-template-columns: 1fr 1fr;
|
|
1010
|
+
gap: var(--tma-spacing-2xl);
|
|
1011
|
+
margin: var(--tma-spacing-2xl) 0;
|
|
1012
|
+
padding: var(--tma-spacing-xl);
|
|
1013
|
+
background: var(--tma-color-bg-secondary);
|
|
1014
|
+
border-radius: var(--tma-radius-lg);
|
|
1015
|
+
border: 1px solid var(--tma-color-border);
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
.tma-dashboard-showcase__image {
|
|
1019
|
+
position: relative;
|
|
1020
|
+
border-radius: var(--tma-radius-md);
|
|
1021
|
+
overflow: hidden;
|
|
1022
|
+
box-shadow: var(--tma-shadow-lg);
|
|
1023
|
+
background: var(--tma-color-bg-primary);
|
|
1024
|
+
border: 1px solid var(--tma-color-border);
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
.tma-dashboard-screenshot {
|
|
1028
|
+
width: 100%;
|
|
1029
|
+
height: auto;
|
|
1030
|
+
display: block;
|
|
1031
|
+
border-radius: var(--tma-radius-md);
|
|
1032
|
+
transition: transform var(--tma-transition-normal);
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
.tma-dashboard-showcase__image:hover .tma-dashboard-screenshot {
|
|
1036
|
+
transform: scale(1.02);
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
.tma-dashboard-showcase__features {
|
|
1040
|
+
display: flex;
|
|
1041
|
+
flex-direction: column;
|
|
1042
|
+
justify-content: center;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.tma-dashboard-showcase__features h4 {
|
|
1046
|
+
font-size: 1.3rem;
|
|
1047
|
+
font-weight: 700;
|
|
1048
|
+
margin-bottom: var(--tma-spacing-lg);
|
|
1049
|
+
color: var(--tma-color-text-primary);
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
.tma-dashboard-showcase__features ul {
|
|
1053
|
+
list-style: none;
|
|
1054
|
+
padding-left: 0;
|
|
1055
|
+
margin: 0 0 var(--tma-spacing-xl) 0;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
.tma-dashboard-showcase__features li {
|
|
1059
|
+
margin-bottom: var(--tma-spacing-md);
|
|
1060
|
+
padding-left: var(--tma-spacing-lg);
|
|
1061
|
+
position: relative;
|
|
1062
|
+
color: var(--tma-color-text-secondary);
|
|
1063
|
+
line-height: 1.6;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
.tma-dashboard-showcase__features li::before {
|
|
1067
|
+
content: '▸';
|
|
1068
|
+
position: absolute;
|
|
1069
|
+
left: 0;
|
|
1070
|
+
color: var(--tma-color-accent-primary);
|
|
1071
|
+
font-weight: bold;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
.tma-dashboard-showcase__features strong {
|
|
1075
|
+
color: var(--tma-color-text-primary);
|
|
1076
|
+
font-weight: 600;
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
.tma-dashboard-showcase__actions {
|
|
1080
|
+
display: flex;
|
|
1081
|
+
gap: var(--tma-spacing-md);
|
|
1082
|
+
flex-wrap: wrap;
|
|
1083
|
+
margin-top: var(--tma-spacing-lg);
|
|
1084
|
+
}
|
|
1085
|
+
|
|
1086
|
+
.tma-button {
|
|
1087
|
+
display: inline-flex;
|
|
1088
|
+
align-items: center;
|
|
1089
|
+
gap: var(--tma-spacing-sm);
|
|
1090
|
+
padding: var(--tma-spacing-md) var(--tma-spacing-lg);
|
|
1091
|
+
border-radius: var(--tma-radius-md);
|
|
1092
|
+
font-weight: 600;
|
|
1093
|
+
font-size: 0.95rem;
|
|
1094
|
+
text-decoration: none;
|
|
1095
|
+
transition: all var(--tma-transition-fast);
|
|
1096
|
+
border: 1px solid transparent;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
.tma-button--primary {
|
|
1100
|
+
background: var(--tma-color-accent-primary);
|
|
1101
|
+
color: #0a0a0f!important;
|
|
1102
|
+
border-color: var(--tma-color-accent-primary);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
.tma-button--primary:hover {
|
|
1106
|
+
background: var(--tma-color-accent-light);
|
|
1107
|
+
border-color: var(--tma-color-accent-light);
|
|
1108
|
+
color: #0a0a0f!important;
|
|
1109
|
+
transform: translateY(-1px);
|
|
1110
|
+
box-shadow: var(--tma-shadow-md);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
.tma-button--secondary {
|
|
1114
|
+
background: transparent;
|
|
1115
|
+
color: var(--tma-color-accent-primary);
|
|
1116
|
+
border-color: var(--tma-color-accent-primary);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
.tma-button--secondary:hover {
|
|
1120
|
+
background: var(--tma-color-accent-muted);
|
|
1121
|
+
border-color: var(--tma-color-accent-light);
|
|
1122
|
+
color: var(--tma-color-accent-light);
|
|
1123
|
+
transform: translateY(-1px);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/* Responsive Dashboard Showcase */
|
|
1127
|
+
@media (max-width: 1024px) {
|
|
1128
|
+
.tma-dashboard-showcase {
|
|
1129
|
+
grid-template-columns: 1fr;
|
|
1130
|
+
gap: var(--tma-spacing-xl);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
.tma-dashboard-showcase__features {
|
|
1134
|
+
order: -1;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
@media (max-width: 768px) {
|
|
1139
|
+
.tma-dashboard-showcase {
|
|
1140
|
+
padding: var(--tma-spacing-md);
|
|
1141
|
+
margin: var(--tma-spacing-lg) 0;
|
|
1142
|
+
}
|
|
1143
|
+
|
|
1144
|
+
.tma-dashboard-showcase__actions {
|
|
1145
|
+
flex-direction: column;
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
.tma-button {
|
|
1149
|
+
width: 100%;
|
|
1150
|
+
justify-content: center;
|
|
1151
|
+
}
|
|
1152
|
+
}
|
data/docs/examples/index.md
CHANGED
|
@@ -48,7 +48,16 @@ Practical examples to get started with Vectra.
|
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
50
|
|
|
51
|
+
## Real-World Examples
|
|
52
|
+
|
|
53
|
+
<div class="tma-comparison-card">
|
|
54
|
+
<h4>Production Use Cases</h4>
|
|
55
|
+
<p>E-commerce search, RAG chatbots, multi-tenant SaaS, and batch processing</p>
|
|
56
|
+
<a href="{{ site.baseurl }}/examples/real-world/">View Examples →</a>
|
|
57
|
+
</div>
|
|
58
|
+
|
|
51
59
|
## More Resources
|
|
52
60
|
|
|
53
61
|
- [GitHub Examples](https://github.com/stokry/vectra/tree/main/examples) - Full example files
|
|
62
|
+
- [Comprehensive Demo](https://github.com/stokry/vectra/tree/main/examples/comprehensive_demo.rb) - Complete feature demonstration
|
|
54
63
|
- [Integration Tests](https://github.com/stokry/vectra/tree/main/spec/integration) - Real-world test cases
|