New homepage (#2172)

* two new sections

* enterprise capabilities and enterprise ready sections

* sections: engineered-for-builders and performance-by-design

* sections: cta-banner, integrations-logos, solutions

# Conflicts:
#	qdrant-landing/themes/qdrant-2024/assets/css/partials/_cta-banner.scss
#	qdrant-landing/themes/qdrant-2024/layouts/partials/cta-banner.html

* remove old sections from index.html

* wip: home page

* reuse links, carousel width

* globe and globe lights

* globe lights

* finalyzing the globe, add customers icons

* new icons set + svg partial update

* upd icons in the enterprise-ready section

* lines background

* globe lights as gradient and svg

* fix carousel responsiveness

* fix cut box shadow

* accordion slider responsiveness

* new hero

* hero customers

* some hero responsiveness

* customers layout fix

* cards responsiveness

* fixes

* remove floating github link

* hero - bigger screens

* refactor css

* more hero responsiveness

* fix

* hero parallax

* replace svg as img with embedded svg logos

* fix marquee

* slider's tabs responsiveness

* remove horizontal scroll on the mobile

* moved images

* images optim

* moved paths to markdown

* svg -> png

* some refactoring and clean up

* moved scss

* svg to png

* more images optimization and cleaning

* optimizing png

* fix globe cards height

* add reveal effect

* improve reveal effect

* fix for the hero animation in Safari

* removed type:page preventing use-cases page from rendering with newer version of Hugo

* restore static/img/home/reranking.webp

* remove unused files

* formatting

* hero and reveal fixes

* fixes

* update cta banner

* links and content fix

* fixes: content, links, web-ui illustration

* canva testimonial

* upd link

* fix

* replace links

* slider links
This commit is contained in:
trean
2026-03-11 23:27:37 +01:00
committed by GitHub
parent 724821b675
commit 305aea6b9a
442 changed files with 7194 additions and 829 deletions
@@ -0,0 +1,152 @@
{{ with (.Site.GetPage "/headless/main/case-studies") }}
<section class="case-studies">
<div class="container case-studies__container">
<div class="case-studies__header">
<h2 class="case-studies__title">{{ .Params.title }}</h2>
<div class="case-studies__controls">
<button type="button" class="case-studies__arrow case-studies__arrow--prev" aria-label="Previous slide">
<svg width="24" height="14" viewBox="0 0 17 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M5.5 1L1.5 5L5.5 9M1.5 5H16" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
<button type="button" class="case-studies__arrow case-studies__arrow--next" aria-label="Next slide">
<svg width="24" height="14" viewBox="0 0 17 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5 1L15.5 5M15.5 5L11.5 9M15.5 5H1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
<div class="case-studies__carousel-outer">
<div class="case-studies__carousel">
<div class="case-studies__track">
{{ range .Params.caseStudies }}
<div class="case-studies__slide">
{{ if .link }}<a href="{{ .link }}" class="case-studies__card-link">{{ end }}
<div class="case-studies__card">
<p class="case-studies__card-text">
{{ .text }}
{{ if .highlight }}
<span class="case-studies__phrase{{ if eq (trim .textAfter " ") "." }} case-studies__phrase--no-break{{ end }}"><span class="case-studies__highlight">{{ .highlight }}</span>{{ if ne (trim .textAfter " ") "." }} {{ end }}{{ .textAfter }}</span>
{{ end }}
{{ if and (not .highlight) .textAfter }}{{ .textAfter }}{{ end }}
{{ if .highlight2 }}
<span class="case-studies__phrase{{ if eq (trim .textAfter2 " ") "." }} case-studies__phrase--no-break{{ end }}"><span class="case-studies__highlight">{{ .highlight2 }}</span>{{ if ne (trim .textAfter2 " ") "." }} {{ end }}{{ .textAfter2 }}</span>
{{ end }}
{{ if and (not .highlight2) .textAfter2 }}{{ .textAfter2 }}{{ end }}
</p>
<div class="case-studies__card-footer">
<div class="case-studies__card-logo" role="img" aria-label="{{ .logoAlt }}">
{{ partial "svg" (dict "icon" .logoIcon "path" "themes/qdrant-2024/static/img/customer-logo/") }}
</div>
<div class="case-studies__card-arrow">
<svg width="24" height="14" viewBox="0 0 17 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.5 1L15.5 5M15.5 5L11.5 9M15.5 5H1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
</div>
{{ if .link }}</a>{{ end }}
</div>
{{ end }}
</div>
</div>
</div>
</div>
</section>
<script>
(function() {
const container = document.querySelector('.case-studies__container');
const carousel = document.querySelector('.case-studies__carousel');
const track = document.querySelector('.case-studies__track');
const prevBtn = document.querySelector('.case-studies__arrow--prev');
const nextBtn = document.querySelector('.case-studies__arrow--next');
if (!container || !carousel || !track || !prevBtn || !nextBtn) return;
const slides = track.querySelectorAll('.case-studies__slide');
const gap = 30;
const breakpoints = { sm: 576, md: 768, xl: 1200 };
let currentOffset = 0;
function getVisibleCount() {
const w = window.innerWidth;
if (w < breakpoints.sm) return 1;
if (w < breakpoints.md) return 2;
if (w < breakpoints.xl) return 3;
return 4;
}
function getContainerContentWidth() {
const style = getComputedStyle(container);
const paddingLeft = parseFloat(style.paddingLeft) || 0;
const paddingRight = parseFloat(style.paddingRight) || 0;
return container.offsetWidth - paddingLeft - paddingRight;
}
function getSlideWidth() {
const contentWidth = getContainerContentWidth();
const count = Math.min(getVisibleCount(), slides.length);
const gaps = Math.max(0, count - 1) * gap;
return Math.floor((contentWidth - gaps) / count);
}
function applySlideWidth() {
const slideWidth = getSlideWidth();
carousel.style.setProperty('--case-studies-slide-width', slideWidth + 'px');
}
function getMaxOffset() {
applySlideWidth();
const slideWidth = getSlideWidth();
const trackWidth = slides.length * slideWidth + (slides.length - 1) * gap;
const contentWidth = getContainerContentWidth();
return Math.max(0, trackWidth - contentWidth);
}
function updateTrack() {
const maxOffset = getMaxOffset();
currentOffset = Math.min(Math.max(0, currentOffset), maxOffset);
track.style.transform = `translateX(-${currentOffset}px)`;
}
function updateButtons() {
const maxOffset = getMaxOffset();
prevBtn.disabled = currentOffset <= 0;
nextBtn.disabled = currentOffset >= maxOffset;
}
prevBtn.addEventListener('click', function() {
const slideWidth = getSlideWidth();
currentOffset = Math.max(0, currentOffset - (slideWidth + gap));
updateTrack();
updateButtons();
});
nextBtn.addEventListener('click', function() {
const maxOffset = getMaxOffset();
const slideWidth = getSlideWidth();
currentOffset = Math.min(maxOffset, currentOffset + (slideWidth + gap));
updateTrack();
updateButtons();
});
function onResize() {
applySlideWidth();
updateTrack();
updateButtons();
}
let resizeTimer;
window.addEventListener('resize', function() {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function() {
requestAnimationFrame(onResize);
}, 100);
});
applySlideWidth();
updateTrack();
updateButtons();
})();
</script>
{{ end }}
@@ -0,0 +1,15 @@
{{ with (.Site.GetPage "/headless/main/customers") }}
<section class="customers">
<div class="container">
<div class="customers__grid">
{{ range .Params.logoRows }}
{{ range .logos }}
<div class="customers__logo">
{{ partial "svg.html" (dict "icon" .src "path" "static" "fill" "#B4BACC") }}
</div>
{{ end }}
{{ end }}
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,53 @@
{{ with (.Site.GetPage "/headless/main/engineered-for-builders") }}
<section class="engineered-for-builders">
<div class="engineered-for-builders__background" aria-hidden="true"></div>
<div class="engineered-for-builders__background-texture" aria-hidden="true"></div>
<div class="container">
<div class="engineered-for-builders__header">
<h2 class="engineered-for-builders__title">{{ .Params.title }}</h2>
<p class="engineered-for-builders__subtitle">{{ .Params.subtitle }}</p>
</div>
{{ with .Params.illustration }}
<div class="engineered-for-builders__illustration">
{{ if .srcset }}
<picture>
{{ with .webpSrcset }}<source type="image/webp" srcset="{{ . }}" />{{ end }}
<img
src="{{ .src }}"
srcset="{{ .srcset }}"
alt="{{ .alt }}"
class="engineered-for-builders__illustration-image"
width="{{ .width }}"
height="{{ .height }}"
loading="lazy"
decoding="async"
/>
</picture>
{{ else }}
{{ partial "picture" (dict "src" .src "alt" .alt "class" "engineered-for-builders__illustration-image" "loading" "lazy" "decoding" "async" "width" .width "height" .height) }}
{{ end }}
</div>
{{ end }}
<div class="engineered-for-builders__features">
{{ range .Params.features }}
<div class="engineered-for-builders__feature">
<h3 class="engineered-for-builders__feature-title">{{ .title }}</h3>
<p class="engineered-for-builders__feature-description">{{ .description }}</p>
<a href="{{ .link.url }}" class="engineered-for-builders__feature-link">
{{ .link.text }}
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M3.33 8H12.67M12.67 8L8.67 4M12.67 8L8.67 12"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</a>
</div>
{{ end }}
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,45 @@
{{ with (.Site.GetPage "/headless/main/enterprise-capabilities") }}
{{ $iconsPath := "static/img/components/icons/" }}
<section class="enterprise-capabilities">
<div class="enterprise-capabilities__stars" aria-hidden="true"></div>
<div class="container enterprise-capabilities__white-light" aria-hidden="true"></div>
<div class="enterprise-capabilities__background" aria-hidden="true">
<div class="enterprise-capabilities__globe-blue-light"></div>
<div class="enterprise-capabilities__globe-blue-light"></div>
<div class="enterprise-capabilities__globe-blue-light"></div>
<div class="enterprise-capabilities__globe-front"></div>
</div>
<div class="container enterprise-capabilities__white-light" aria-hidden="true"></div>
<div class="enterprise-capabilities__background" aria-hidden="true">
<div class="enterprise-capabilities__globe-front"></div>
</div>
<div class="container">
<div class="enterprise-capabilities__content">
<div class="enterprise-capabilities__header">
<h2 class="enterprise-capabilities__title">{{ .Params.title }}</h2>
<p class="enterprise-capabilities__subtitle">{{ .Params.subtitle }}</p>
</div>
<div class="enterprise-capabilities__cards">
{{ range .Params.deploymentOptions }}
<a href="{{ .link.url }}" class="enterprise-capabilities__card enterprise-capabilities__card--{{ .position }}">
{{ if .connector }}
<img src="{{ .connector }}" alt="" class="enterprise-capabilities__connector" />
{{ end }}
<div class="enterprise-capabilities__card-icon">
{{ partial "svg" (dict "icon" .icon "path" $iconsPath "color" .iconColor ) }}
</div>
<div class="enterprise-capabilities__card-content">
<h3 class="enterprise-capabilities__card-title">{{ .title }}</h3>
<p class="enterprise-capabilities__card-description">{{ .description }}</p>
</div>
<span class="link link_white link_md enterprise-capabilities__card-link"
>{{ .link.text }}</span
>
</a>
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,50 @@
{{ with (.Site.GetPage "/headless/main/enterprise-ready") }}
<section class="enterprise-ready">
<div class="container">
<div class="enterprise-ready__header">
<h2 class="enterprise-ready__title">{{ .Params.title }}</h2>
<p class="enterprise-ready__subtitle">{{ .Params.subtitle }}</p>
</div>
<div class="enterprise-ready__content">
{{/* Large cards row */}}
<div class="enterprise-ready__row enterprise-ready__row--large">
{{ range .Params.largeCards }}
{{ if and .link .link.url }}
<a href="{{ .link.url }}" class="enterprise-ready__card enterprise-ready__card--large enterprise-ready__card--link"{{ if or (hasPrefix .link.url "http://") (hasPrefix .link.url "https://") }} target="_blank" rel="noopener noreferrer"{{ end }}>
{{ else }}
<div class="enterprise-ready__card enterprise-ready__card--large">
{{ end }}
<div class="enterprise-ready__card-visual enterprise-ready__card-visual--{{ .visual }}">
{{ if .image }}
{{ partial "picture" (dict "src" .image.src "alt" .image.alt "class" "enterprise-ready__card-img" "loading" "lazy" "decoding" "async") }}
{{ end }}
</div>
<div class="enterprise-ready__card-footer">
<span class="link link_dark link_md enterprise-ready__card-link">{{ .title }}</span>
</div>
{{ if and .link .link.url }}</a>{{ else }}</div>{{ end }}
{{ end }}
</div>
{{/* Small cards row */}}
{{ $iconsPath := "static/img/components/icons/" }}
<div class="enterprise-ready__row enterprise-ready__row--small">
{{ range .Params.smallCards }}
{{ if and .link .link.url }}
<a href="{{ .link.url }}" class="enterprise-ready__card enterprise-ready__card--small enterprise-ready__card--link"{{ if or (hasPrefix .link.url "http://") (hasPrefix .link.url "https://") }} target="_blank" rel="noopener noreferrer"{{ end }}>
{{ else }}
<div class="enterprise-ready__card enterprise-ready__card--small">
{{ end }}
<div class="enterprise-ready__card-icon">
{{ if .icon }}
{{ partial "svg" (dict "icon" .icon.name "path" $iconsPath "color" .icon.color "stroke" .icon.stroke "fill" .icon.fill) }}
{{ end }}
</div>
<span class="enterprise-ready__card-label">{{ .title }}</span>
{{ if and .link .link.url }}</a>{{ else }}</div>{{ end }}
{{ end }}
</div>
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,95 @@
{{ with (.Site.GetPage "/headless/main/hero") }}
<section class="hero">
<div class="hero__container">
<div class="hero__grid"></div>
<div class="hero__content">
<div class="hero__heading">
<h1 class="hero__title">{{ .Params.title }}</h1>
<p class="hero__subtitle">{{ .Params.subtitle }}</p>
</div>
<div class="hero__buttons">
<a data-metric-loc="hero" href="{{ .Params.startFree.url }}" class="button button_contained button_lg"
data-metric-loc="hero">{{ .Params.startFree.text }}</a>
<a data-metric-loc="hero" href="{{ .Params.learnMore.url }}" class="button button_outlined button_lg"
data-metric-loc="hero">{{ .Params.learnMore.text }}</a>
</div>
</div>
<div class="hero__planet">
{{ with .Params.planet }}
<img class="hero__planet-blur" src="{{ .blur }}" alt="" width="570" height="544" decoding="async" />
<img
class="hero__planet-blur hero__planet-blur--alt"
src="{{ .blur2 }}"
alt=""
width="570"
height="544"
decoding="async"
/>
<img class="hero__planet-sphere" src="{{ .sphere }}" alt="" width="514" height="488" decoding="async" />
{{ with .texture }}
<picture>
<source srcset="{{ .webp }}" type="image/webp" />
<img
class="hero__planet-texture"
src="{{ .png }}"
alt=""
width="1012"
height="960"
loading="eager"
decoding="async"
/>
</picture>
{{ end }}
{{ end }}
</div>
{{ with .Params.blueHaze }}
<img class="hero__blue-haze" src="{{ . }}" alt="" width="1200" height="600" decoding="async" />
{{ end }}
<div class="hero__astronauts">
{{ with .Params.astronauts }}
<picture>
<source type="image/webp" srcset="{{ .webpSrcset }}" sizes="100vw" />
<img
src="{{ .fallbackSrc }}"
srcset="{{ .pngSrcset }}"
sizes="100vw"
alt="{{ .alt }}"
width="{{ .width }}"
height="{{ .height }}"
draggable="false"
loading="eager"
decoding="async"
fetchpriority="high"
/>
</picture>
{{ end }}
</div>
<div class="hero__fade-top"></div>
<div class="hero__fade-bottom"></div>
<div class="hero__fade-left"></div>
<div class="hero__fade-right"></div>
</div>
{{ if .Params.valueBadges }}
<div class="hero__badges">
{{ range .Params.valueBadges }}
{{ if .url }}
<a href="{{ .url }}" class="hero__badge hero__badge--link"{{ if or (hasPrefix .url "http://") (hasPrefix .url "https://") }} target="_blank" rel="noopener noreferrer"{{ end }}>
<img src="{{ .icon }}" alt="" class="hero__badge-icon" width="16" height="16" decoding="async" />
<span class="hero__badge-text">{{ .text }}</span>
</a>
{{ else }}
<span class="hero__badge">
<img src="{{ .icon }}" alt="" class="hero__badge-icon" width="16" height="16" decoding="async" />
<span class="hero__badge-text">{{ .text }}</span>
</span>
{{ end }}
{{ end }}
</div>
{{ end }}
</section>
{{ end }}
@@ -0,0 +1,46 @@
{{ with (.Site.GetPage "/headless/main/integrations-logos") }}
{{ $logosFirstRow := .Params.logosFirstRow }}
{{ $logosSecondRow := .Params.logosSecondRow }}
<section class="integrations-logos">
<div class="container">
<p class="integrations-logos__title">{{ .Params.title }}</p>
</div>
<div class="integrations-logos__content">
<div class="integrations-logos__cards">
<div class="integrations-logos__cards__container">
<div class="integrations-logos__cards__block">
<div class="integrations-logos__cards__inner integrations-logos__cards__inner_to-left">
<span>
{{ partial "integrations-logos-cards" (dict "context" $logosFirstRow) }}
</span>
<span>
{{ partial "integrations-logos-cards" (dict "context" $logosFirstRow) }}
</span>
</div>
</div>
</div>
</div>
<div class="integrations-logos__cards">
<div class="integrations-logos__cards__container">
<div class="integrations-logos__cards__block">
<div class="integrations-logos__cards__inner integrations-logos__cards__inner_to-right">
<span>
{{ partial "integrations-logos-cards" (dict "context" $logosSecondRow) }}
</span>
<span>
{{ partial "integrations-logos-cards" (dict "context" $logosSecondRow) }}
</span>
</div>
</div>
</div>
</div>
<div class="integrations-logos__gradient-left"></div>
<div class="integrations-logos__gradient-right"></div>
</div>
</section>
{{ end }}
@@ -0,0 +1,110 @@
{{ with (.Site.GetPage "/headless/main/performance-by-design") }}
<section class="performance-by-design">
<div class="container">
<div class="performance-by-design__header">
<span class="performance-by-design__tagline">{{ .Params.tagline }}</span>
<h2 class="performance-by-design__title">{{ .Params.title }}</h2>
<p class="performance-by-design__subtitle">{{ .Params.subtitle }}</p>
</div>
{{/* Slider layout: visible only below md */}}
<div class="performance-by-design__slider">
<div class="performance-by-design__content">
<div class="performance-by-design__features">
{{ range $index, $feature := .Params.features }}
<div class="performance-by-design__feature{{ if eq $index 0 }} performance-by-design__feature--active{{ end }}" data-feature-index="{{ $index }}">
<h3 class="performance-by-design__feature-title">{{ $feature.title }}</h3>
<div class="performance-by-design__feature-body">
<p class="performance-by-design__feature-description">{{ $feature.description }}</p>
</div>
</div>
{{ end }}
</div>
<div class="performance-by-design__visual">
{{ range $index, $feature := .Params.features }}
<div class="performance-by-design__image{{ if eq $index 0 }} performance-by-design__image--active{{ end }}" data-image-index="{{ $index }}">
{{ if $feature.image }}
{{ partial "picture" (dict "src" $feature.image.src "alt" $feature.image.alt "loading" "lazy" "decoding" "async") }}
{{ end }}
</div>
{{ end }}
</div>
</div>
</div>
{{/* Card grid: visible from md up, 2 cards per row */}}
<div class="performance-by-design__grid">
{{ range .Params.features }}
<div class="performance-by-design__card">
{{ if .image }}
<div class="performance-by-design__card-visual">
{{ partial "picture" (dict "src" .image.src "alt" .image.alt "class" "performance-by-design__card-image" "loading" "lazy" "decoding" "async") }}
</div>
{{ end }}
<div class="performance-by-design__card-content">
<h3 class="performance-by-design__card-title">{{ .title }}</h3>
<p class="performance-by-design__card-description">{{ .description }}</p>
</div>
</div>
{{ end }}
</div>
</div>
</section>
<script>
(function () {
var section = document.querySelector('.performance-by-design');
if (!section) return;
var features = section.querySelectorAll('.performance-by-design__feature');
var images = section.querySelectorAll('.performance-by-design__image');
if (!features.length) return;
var currentIndex = 0;
var autoplayInterval = null;
var AUTOPLAY_DELAY = 5000;
function goToFeature(index) {
if (index < 0 || index >= features.length) return;
features.forEach(function (f) {
f.classList.remove('performance-by-design__feature--active');
});
images.forEach(function (img) {
img.classList.remove('performance-by-design__image--active');
});
features[index].classList.add('performance-by-design__feature--active');
if (images[index]) images[index].classList.add('performance-by-design__image--active');
currentIndex = index;
}
function nextFeature() {
var next = (currentIndex + 1) % features.length;
goToFeature(next);
}
function startAutoplay() {
stopAutoplay();
autoplayInterval = setInterval(nextFeature, AUTOPLAY_DELAY);
}
function stopAutoplay() {
if (autoplayInterval) {
clearInterval(autoplayInterval);
autoplayInterval = null;
}
}
features.forEach(function (feature, i) {
feature.addEventListener('click', function () {
goToFeature(i);
startAutoplay();
});
});
startAutoplay();
})();
</script>
{{ end }}
@@ -0,0 +1,23 @@
{{ with (.Site.GetPage "/headless/main/solutions") }}
<section class="solutions">
<div class="solutions__background"></div>
<div class="container">
<div class="solutions__header">
<span class="solutions__label">{{ .Params.label }}</span>
<h2 class="solutions__title">{{ .Params.title }}</h2>
<p class="solutions__subtitle">{{ .Params.subtitle }}</p>
</div>
<div>
{{ partial "tab-slider" (dict
"sectionClass" "solutions"
"tabs" .Params.tabs
"items" .Params.tabs
"slidePartial" "solutions-slide-content"
"showControls" true
)
}}
</div>
</div>
</section>
{{ end }}
@@ -0,0 +1,27 @@
{{ with (.Site.GetPage "/headless/main/why-qdrant") }}
<section class="why-qdrant">
<div class="container">
<div class="why-qdrant__header">
<span class="why-qdrant__pill">{{ .Params.pill }}</span>
<h2 class="why-qdrant__title">{{ .Params.title }}</h2>
<p class="why-qdrant__subtitle">{{ .Params.subtitle }}</p>
</div>
<div class="why-qdrant__grid">
{{ range .Params.featureCards }}
<div class="why-qdrant__card why-qdrant__card--{{ .size }}" data-card-id="{{ .id }}">
<div class="why-qdrant__card-visual why-qdrant__card-visual--{{ .id }}">
{{ if .image }}
{{ partial "picture" (dict "src" .image.src "alt" .image.alt "class" "why-qdrant__card-image" "loading" "lazy" "decoding" "async") }}
{{ end }}
</div>
<div class="why-qdrant__card-content">
<h3 class="why-qdrant__card-title">{{ .title }}</h3>
<p class="why-qdrant__card-description">{{ .description | safeHTML }}</p>
<a href="{{ .link.url }}" class="link link_md why-qdrant__card-link">{{ .link.text }}</a>
</div>
</div>
{{ end }}
</div>
</div>
</section>
{{ end }}