Skip to content
Closed
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ yarn.lock
.python-version
__pycache__

# Local Netlify folder
.netlify

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[codz]
Expand Down
20 changes: 20 additions & 0 deletions .netlify/functions/geolocation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
exports.handler = async (event) => {
try {
// Netlify provides geo data in a base64 encoded header
const geoData = JSON.parse(
Buffer.from(event.headers["x-nf-geo"], "base64").toString("utf-8")
);
const countryCode = geoData.country?.code || null;

return {
statusCode: 200,
body: JSON.stringify({ country: countryCode }),
};
} catch (error) {
console.error("Error parsing geolocation data:", error);
return {
statusCode: 500,
body: JSON.stringify({ error: "Failed to determine location" }),
};
}
};
1 change: 1 addition & 0 deletions docs/agents/query/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Query Agent
sidebar_position: 10
description: "Overview of the AI agent that handles complex queries across multiple Weaviate collections with natural language understanding."
image: og/docs/agents.jpg
show_expert_call_cta: true
# tags: ['agents', 'getting started', 'query agent']
---

Expand Down
1 change: 1 addition & 0 deletions docs/agents/query/tutorial-ecommerce.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ sidebar_label: 'Tutorial: E-Commerce assistant'
description: "Tutorial for creating an e-commerce assistant that answers product and brand queries using the Query Agent."
sidebar_position: 40
image: og/docs/tutorials.jpg
show_expert_call_cta: true
# tags: ['basics']
---

Expand Down
1 change: 1 addition & 0 deletions docs/agents/query/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Usage
sidebar_position: 30
description: "Technical documentation and usage examples for implementing the Query Agent."
image: og/docs/agents.jpg
show_expert_call_cta: true
# tags: ['agents', 'getting started', 'query agent']
---

Expand Down
1 change: 1 addition & 0 deletions docs/weaviate/concepts/cluster.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Horizontal Scaling
sidebar_position: 30
description: "Multi-node cluster architecture and horizontal scaling strategies for high-availability Weaviate deployments."
image: og/docs/concepts.jpg
show_expert_call_cta: true
# tags: ['architecture', 'horizontal scaling', 'cluster', 'replication', 'sharding']
---

Expand Down
1 change: 1 addition & 0 deletions docs/weaviate/concepts/replication-architecture/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Replication Architecture
sidebar_position: 0
description: "Multi-node data replication design for high availability, reliability, and improved database performance."
image: og/docs/concepts.jpg
show_expert_call_cta: true
# tags: ['architecture']
---

Expand Down
1 change: 1 addition & 0 deletions docs/weaviate/concepts/resources.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ title: Resource Planning
sidebar_position: 90
description: "CPU, memory, and GPU resource planning guidelines for optimal Weaviate performance at scale."
image: og/docs/concepts.jpg
show_expert_call_cta: true
# tags: ['architecture', 'resource', 'cpu', 'memory', 'gpu']
---

Expand Down
3 changes: 3 additions & 0 deletions netlify.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
[headers.values]
access-control-allow-origin = "*"

[functions]
directory = ".netlify/functions/"

## Remove /current from the path
[[redirects]]
from = "/weaviate/current/*"
Expand Down
17 changes: 17 additions & 0 deletions src/components/ExpertCallCTA/geolocation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/**
* Fetches the user's country code based on their IP address.
* @returns {Promise<string|null>} The two-letter country code (e.g., 'US') or null if the fetch fails.
*/
export const getUserCountryCode = async () => {
try {
const response = await fetch('https://ip-api.com/json/?fields=countryCode');
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
return data.countryCode;
} catch (error) {
console.error("Failed to fetch user location:", error);
return null; // Return null on error so we can handle it gracefully
}
};
91 changes: 91 additions & 0 deletions src/components/ExpertCallCTA/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import React, { useState, useEffect } from "react";
import styles from "./styles.module.scss";

// This function now calls your internal Netlify function
const getCountryFromNetlify = async () => {
try {
const response = await fetch("/.netlify/functions/geolocation");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
return data.country;
} catch (error) {
console.error("Failed to fetch from Netlify function:", error);
return null;
}
};

export default function ExpertCallCTA() {
const [isVisible, setIsVisible] = useState(false);

useEffect(() => {
// A sample list of countries to exclude.
// ❗ IMPORTANT: This list is an example and should be reviewed and
// customized for your specific needs.
const excludedCountries = [
"RU", // Russia
"VN", // Vietnam
"IN", // India
"IR", // Iran
"PK", // Pakistan
];
const checkVisibility = async () => {
const userCountry = await getCountryFromNetlify();

// If the location lookup fails for any reason, default to showing the component.
// This ensures that users with privacy tools aren't blocked.
if (!userCountry) {
setIsVisible(true);
return;
}

// If the user's country is NOT in the exclusion list, show the component.
if (!excludedCountries.includes(userCountry)) {
setIsVisible(true);
}
};

checkVisibility();
}, []); // Empty array ensures this runs only once on mount

// If not visible, render nothing.
if (!isVisible) {
return null;
}

return (
<div className={styles.container}>
<p className={styles.text}>
Ready for production? Book a call with a Weaviate expert to get help.
</p>

<div className={styles.buttonContainer}>
<a
href="https://calendly.com/your-company/expert-call"
target="_blank"
rel="noopener noreferrer"
className={`button button--primary ${styles.ctaButton}`}
>
Book call
</a>
<a
className={`button button--primary ${styles.askAiButton}`}
onClick={() => {
if (window.Kapa && typeof window.Kapa.open === "function") {
window.Kapa.open({
mode: "ai",
query: "",
submit: false,
});
} else {
console.warn("Kapa is not available");
}
}}
>
Ask AI
</a>
</div>
</div>
);
}
33 changes: 33 additions & 0 deletions src/components/ExpertCallCTA/styles.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.container {
background-color: var(--ifm-background-surface-color);
padding: 1rem;
border-radius: var(--ifm-card-border-radius);
margin-top: 1.5rem; /* Adds space between the TOC and this component */
text-align: left;
border: 1px solid var(--ifm-color-emphasis-300);
}

.buttonContainer {
display: flex;
flex-wrap: wrap; /* Allows buttons to stack on small screens */
gap: 0.75rem; /* Defines the space between the buttons */
}

.text {
margin-bottom: 0.8rem;
font-size: 0.9rem !important;
line-height: 1.4;
color: var(--ifm-toc-link-color);
}

.ctaButton {
background-color: var(--site-primary);
border-color: var(--site-primary);
color: white;
}

.askAiButton {
background-color: rgb(155, 155, 155);
border-color: rgb(155, 155, 155);
color: white;
}
73 changes: 73 additions & 0 deletions src/theme/DocItem/Layout/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from "react";
import clsx from "clsx";
import { useWindowSize } from "@docusaurus/theme-common";
import { useDoc } from "@docusaurus/plugin-content-docs/client";
import DocItemPaginator from "@theme/DocItem/Paginator";
import DocVersionBanner from "@theme/DocVersionBanner";
import DocVersionBadge from "@theme/DocVersionBadge";
import DocItemFooter from "@theme/DocItem/Footer";
import DocItemTOCMobile from "@theme/DocItem/TOC/Mobile";
import DocItemTOCDesktop from "@theme/DocItem/TOC/Desktop";
import DocItemContent from "@theme/DocItem/Content";
import DocBreadcrumbs from "@theme/DocBreadcrumbs";
import ContentVisibility from "@theme/ContentVisibility";
import styles from "./styles.module.css";

/* ---- START: Customizations ---- */
import ExpertCallCTA from "@site/src/components/ExpertCallCTA";
/* ---- END: Customizations ---- */

/**
* Decide if the toc should be rendered, on mobile or desktop viewports
*/
function useDocTOC() {
const { frontMatter, toc } = useDoc();
const windowSize = useWindowSize();
const hidden = frontMatter.hide_table_of_contents;
const canRender = !hidden && toc.length > 0;
const mobile = canRender ? <DocItemTOCMobile /> : undefined;
const desktop =
canRender && (windowSize === "desktop" || windowSize === "ssr") ? (
<DocItemTOCDesktop />
) : undefined;
return {
hidden,
mobile,
desktop,
};
}

export default function DocItemLayout({ children }) {
const docTOC = useDocTOC();
const { frontMatter, metadata } = useDoc();
return (
<div className="row">
<div className={clsx("col", !docTOC.hidden && styles.docItemCol)}>
<ContentVisibility metadata={metadata} />
<DocVersionBanner />
<div className={styles.docItemContainer}>
<article>
<DocBreadcrumbs />
<DocVersionBadge />
{docTOC.mobile}
<DocItemContent>{children}</DocItemContent>
<DocItemFooter />
</article>
<DocItemPaginator />
</div>
</div>
{docTOC.desktop && (
<div className="col col--3">
{/* ---- START: Customizations ---- */}
{/* Add a wrapper div to make the whole block sticky */}
<div className={styles.tocStickyContainer}>
<DocItemTOCDesktop toc={docTOC.desktop.value} />

{frontMatter.show_expert_call_cta && <ExpertCallCTA />}
</div>
{/* ---- END: Customizations ---- */}
</div>
)}
</div>
);
}
25 changes: 25 additions & 0 deletions src/theme/DocItem/Layout/styles.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
.docItemContainer header + *,
.docItemContainer article > *:first-child {
margin-top: 0;
}

@media (min-width: 997px) {
.docItemCol {
max-width: 75% !important;
}
}

.tocStickyContainer {
/* Sticky positioning */
top: var(--ifm-navbar-height);
position: sticky;

/* ---- START: Use Grid instead of Flexbox ---- */
/* Use Grid to create a strict two-row layout */
display: grid;
grid-template-rows: 1fr auto;
/* ---- END: Use Grid instead of Flexbox ---- */

/* Scrolling behavior */
max-height: calc(100vh - var(--ifm-navbar-height));
}
Loading