Skip to content
Open
Show file tree
Hide file tree
Changes from all 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: 3 additions & 0 deletions docs/weaviate/quickstart/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ Weaviate is an open-source vector database built to power AI applications. This
4. **Query Agent** - Get answers from you data by using a natural language prompt/question. <CloudOnlyBadge compact />

import KapaAI from "/src/components/KapaAI";
import PromptStarter from "/src/components/PromptStarter";

<PromptStarter page="quickstart" />

If you encounter any issues along the way or have additional questions, use the <KapaAI>Ask AI</KapaAI> feature.

Expand Down
179 changes: 179 additions & 0 deletions src/components/PromptStarter/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
import React, { useState, useCallback } from "react";
import styles from "./styles.module.scss";
import { getPromptsForPage, CURSOR_CHAR_LIMIT } from "./prompts";

/**
* PromptStarter - A banner component that provides AI-ready prompts for documentation pages
*
* @param {string} page - The page identifier to load prompts for (e.g., "quickstart")
* @param {string} defaultLanguage - Initial language selection ("python" or "typescript")
*/
const PromptStarter = ({ page = "quickstart", defaultLanguage = "python" }) => {
const [language, setLanguage] = useState(defaultLanguage);
const [copied, setCopied] = useState(false);

// Get prompts for the specified page
const pagePrompts = getPromptsForPage(page);

// If no prompts found for this page, don't render anything
if (!pagePrompts) {
return null;
}

const { fullPrompt, condensedPrompt } = pagePrompts;

const handleOpenInCursor = useCallback(() => {
const prompt = condensedPrompt[language];

if (!prompt) {
console.warn(`No condensed prompt found for language: ${language}`);
return;
}

// Use the URL API for proper encoding (as recommended by Cursor docs)
// Using web link format which is more reliable than cursor:// protocol
const url = new URL("https://cursor.com/link/prompt");
url.searchParams.set("text", prompt);

// Check total URL length (8000 char limit for deeplinks)
const urlString = url.toString();
if (urlString.length > CURSOR_CHAR_LIMIT) {
console.warn(
`URL length (${urlString.length}) exceeds Cursor limit (${CURSOR_CHAR_LIMIT}).`
);
}

window.open(urlString, "_blank");
}, [language, condensedPrompt]);

const handleCopyPrompt = useCallback(async () => {
const prompt = fullPrompt[language];

if (!prompt) {
console.warn(`No full prompt found for language: ${language}`);
return;
}

try {
await navigator.clipboard.writeText(prompt);
setCopied(true);

// Reset copied state after 2 seconds
setTimeout(() => {
setCopied(false);
}, 2000);
} catch (err) {
// Fallback for older browsers
const textArea = document.createElement("textarea");
textArea.value = prompt;
textArea.style.position = "fixed";
textArea.style.left = "-9999px";
document.body.appendChild(textArea);
textArea.select();

try {
document.execCommand("copy");
setCopied(true);
setTimeout(() => {
setCopied(false);
}, 2000);
} catch (fallbackErr) {
console.error("Failed to copy prompt:", fallbackErr);
}

document.body.removeChild(textArea);
}
}, [language, fullPrompt]);

// Check which languages are available for this page
const hasPython = Boolean(fullPrompt?.python);
const hasTypeScript = Boolean(fullPrompt?.typescript);
const showLanguageSelector = hasPython && hasTypeScript;

return (
<div className={styles.promptStarterWrapper}>
<div className={styles.promptStarter}>
<div className={styles.content}>
<div className={styles.icon}>
<i className="fas fa-wand-magic-sparkles" aria-hidden="true" />
</div>
<div className={styles.textContent}>
<p className={styles.title}>Get started faster with AI</p>
<p className={styles.description}>
Use this pre-built prompt with your AI assistant
</p>
</div>
</div>

<div className={styles.actions}>
{showLanguageSelector && (
<div
className={styles.languageSelector}
role="radiogroup"
aria-label="Select programming language"
>
<button
type="button"
className={`${styles.languageButton} ${
language === "python" ? styles.active : ""
}`}
onClick={() => setLanguage("python")}
role="radio"
aria-checked={language === "python"}
>
Python
</button>
<button
type="button"
className={`${styles.languageButton} ${
language === "typescript" ? styles.active : ""
}`}
onClick={() => setLanguage("typescript")}
role="radio"
aria-checked={language === "typescript"}
>
TypeScript
</button>
</div>
)}

<button
type="button"
className={`${styles.button} ${styles.primaryButton}`}
onClick={handleOpenInCursor}
aria-label="Open prompt in Cursor editor"
>
<i className="fas fa-external-link-alt" aria-hidden="true" />
Open in Cursor
</button>

<button
type="button"
className={`${styles.button} ${
copied ? styles.copiedButton : styles.secondaryButton
}`}
onClick={handleCopyPrompt}
aria-label={copied ? "Prompt copied to clipboard" : "Copy prompt to clipboard"}
>
{copied ? (
<>
<i
className={`fas fa-check ${styles.copiedIcon}`}
aria-hidden="true"
/>
Copied!
</>
) : (
<>
<i className="fas fa-copy" aria-hidden="true" />
Copy prompt
</>
)}
</button>
</div>
</div>
</div>
);
};

export default PromptStarter;
30 changes: 30 additions & 0 deletions src/components/PromptStarter/prompts/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Central export for all page-specific prompts
// Add new prompt files here as they are created

import * as quickstart from "./quickstart";

// Map of page identifiers to their prompts
// Each entry should have: { fullPrompt: { python, typescript }, condensedPrompt: { python, typescript } }
export const prompts = {
quickstart,
// Future pages can be added here:
// search: searchPrompts,
// agents: agentsPrompts,
// rag: ragPrompts,
};

// Cursor deeplink character limit
export const CURSOR_CHAR_LIMIT = 8000;

// Helper to get prompts for a specific page
export function getPromptsForPage(page) {
const pagePrompts = prompts[page];
if (!pagePrompts) {
console.warn(`No prompts found for page: ${page}. Available pages: ${Object.keys(prompts).join(", ")}`);
return null;
}
return pagePrompts;
}

// Re-export quickstart as default for backwards compatibility
export { quickstart };
Loading