Small fixes.

This commit is contained in:
István Zoltán Szabó
2026-09-15 16:07:01 +02:00
parent 204d626936
commit 0a2683237f
17 changed files with 111 additions and 72 deletions
+5 -2
View File
@@ -4,8 +4,11 @@ on:
pull_request:
paths:
- 'qdrant-landing/content/**/*.md'
- 'qdrant-landing/layouts/shortcodes/prompt.markdown.md'
- 'qdrant-landing/themes/qdrant-2024/layouts/shortcodes/prompt.html'
# Every shortcode, not just the prompt ones: the Markdown variants are
# what keep prompt bodies out of the agent-facing output, and naming them
# individually is how prompt-index.markdown.md went unguarded.
- 'qdrant-landing/layouts/shortcodes/**'
- 'qdrant-landing/themes/qdrant-2024/layouts/shortcodes/**'
- 'automation/prompts/**'
- '.github/workflows/prompts.yml'
# A skill link breaks when a skill is renamed or unpublished in qdrant/skills,
+3 -3
View File
@@ -98,9 +98,9 @@ automation/prompts/check-skill-links.sh # skill links resolve, needs network
automation/snippets/generate-md.py # if you touched snippets, then commit the result
```
Run `git add -A` or `git add :/` from anywhere other than the repository root.
Plain `git add .` inside `qdrant-landing/` silently misses changes to
`automation/` and `.github/`.
When you are not at the repository root, stage with `git add -A` or
`git add :/`. Plain `git add .` inside `qdrant-landing/` silently misses
changes to `automation/` and `.github/`.
## Two traps in the templates
+13
View File
@@ -75,6 +75,19 @@ does. That split is why titles stay short, and why the type signal is
consistent across every prompt rather than depending on each author phrasing it
the same way.
## Formatting a prompt body
**Do not hard-wrap prose.** Write each paragraph as one long line and let the
page wrap it. The element renders the body with `white-space: pre-wrap`, so any
line breaks you type are preserved, and a body wrapped at 80 columns keeps those
breaks in a content column that is narrower than that. `start-building` is the
exception: its numbered steps and indented commands are structure, so its line
breaks are content.
**A body can contain anything, including fenced blocks.** The shortcode passes
it to Chroma as a value rather than re-parsing it as markdown, so a prompt that
includes a YAML or JSON snippet renders correctly.
## Two rules that break silently
**Prompt bodies must never reach a built `index.md`.** Those files are consumed
+20 -9
View File
@@ -9,8 +9,11 @@
# body, so the only way a body reaches index.md is an author pasting it as
# a fenced block instead of using the shortcode. That is a source-level
# mistake, so it is caught in the source.
# 2. The Markdown variant of the shortcode still drops the body. Rule 1 is
# only equivalent to "no body in index.md" while this holds.
# 2. No Markdown variant renders the body. Rule 1 is only equivalent to "no
# body in index.md" while this holds, and it has to cover every template
# that can reach a prompt's content, not just the element's. The index
# ranges the same pages, so a body added there lands in the built
# index.md exactly the same way.
# 3. Every prompt's declared `page:` really includes it. The prompt files live
# in one folder and cannot know who includes them, so the declaration is
# what the index trusts. This also catches a prompt that is written but
@@ -28,7 +31,12 @@ repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
public_dir="${1:-}"
prompts_dir="$repo_root/qdrant-landing/content/documentation/headless/prompts"
content_dir="$repo_root/qdrant-landing/content"
md_shortcode="$repo_root/qdrant-landing/layouts/shortcodes/prompt.markdown.md"
# Every Markdown-output template that can reach a prompt page. Add to this list
# rather than writing a new check if another one appears.
md_shortcodes=(
"$repo_root/qdrant-landing/layouts/shortcodes/prompt.markdown.md"
"$repo_root/qdrant-landing/layouts/shortcodes/prompt-index.markdown.md"
)
failures=0
@@ -42,12 +50,15 @@ if [[ ! -d "$prompts_dir" ]]; then
exit 0
fi
# --- rule 2: the Markdown variant must not render the prompt body ---
if [[ ! -f "$md_shortcode" ]]; then
fail "missing $md_shortcode: without it, prompt bodies reach the agent-facing Markdown"
elif grep -qE '\.(RawContent|Content|Inner)\b' "$md_shortcode"; then
fail "$md_shortcode renders the prompt body; it must emit only the skill pointer"
fi
# --- rule 2: no Markdown variant may render the prompt body ---
for md_shortcode in "${md_shortcodes[@]}"; do
rel="${md_shortcode#"$repo_root"/}"
if [[ ! -f "$md_shortcode" ]]; then
fail "missing $rel: without it, prompt bodies reach the agent-facing Markdown"
elif grep -qE '\.(RawContent|Content|Inner)\b' "$md_shortcode"; then
fail "$rel renders the prompt body; it must emit only titles, pages, and skill pointers"
fi
done
shopt -s nullglob
checked=0
@@ -13,16 +13,17 @@ Use them to give your agent task-specific guidance, troubleshoot existing deploy
## Start Building
If you're new to Qdrant, paste this into your coding assistant.
If you're new to Qdrant, the Start building on Qdrant prompt takes your coding assistant from an empty project to a working search query.
It stands up a local instance, installs the client with local embeddings, adds the [Qdrant Advisor](/documentation/agentic-tools/skills/#the-qdrant-advisor) skill, and then builds against your own use case.
{{< prompt "start-building" >}}
Nothing in those four steps needs an account.
None of that needs an account.
Qdrant runs in Docker and [FastEmbed](/documentation/fastembed/fastembed-quickstart/) generates embeddings on your machine, so you can go from nothing to a working search query without signing up for anything.
Step 4 does the work that matters.
A wrong collection configuration rarely fails loudly in vector search: a mismatched distance metric or a missing payload index returns plausible results and quietly costs you relevance, so it's worth making your agent commit to those choices out loud before it writes code.
The part that matters most is the collection configuration.
A wrong one rarely fails loudly in vector search: a mismatched distance metric or a missing payload index returns plausible results and quietly costs you relevance.
The prompt is written to make your assistant ask what you are building, then commit to those choices out loud before it writes any code.
## Agent Skills
@@ -12,6 +12,6 @@ Qdrant documentation includes short, ready-to-use prompts on the pages where the
Each prompt is collapsed by default, requires no additional input, and tells your assistant which [agent skill](/documentation/agentic-tools/skills/) to load. The prompt defines the task; the skill provides the Qdrant-specific guidance needed to complete it.
This page lists all available prompts. Follow a link to open the prompt alongside the documentation that provides its context.
This page lists all available prompts. Follow a link to jump to the prompt on the page that provides its context.
{{< prompt-index >}}
@@ -1,15 +1,8 @@
---
title: "Design a collection"
skill: qdrant-multitenancy
# No skill: on purpose. The catalog has no collection-design skill, and
# qdrant-multitenancy would label the whole prompt as a tenancy prompt in
# the index. The body still links it where it is actually relevant.
page: /documentation/manage-data/collections/
---
Help me design a Qdrant collection for my data. Ask me what I am searching
over, roughly how many vectors I expect, which embedding model I am using, and
what I will filter on, before you write any code. Decide first whether this
should be one collection or many, reading
https://skills.qdrant.tech/qdrant-multitenancy/SKILL.md, since that choice
drives the index layout. Then derive the vector size from the model rather than
hardcoding it, name the distance metric the model was trained for and say why
you picked it, and add a payload index for every field I will filter on. Finish
by telling me which of these I cannot change later without recreating the
collection.
Help me design a Qdrant collection for my data. Ask me what I am searching over, roughly how many vectors I expect, which embedding model I am using, and what I will filter on, before you write any code. Decide first whether this should be one collection or many, reading https://skills.qdrant.tech/qdrant-multitenancy/SKILL.md, since that choice drives the index layout. Then derive the vector size from the model rather than hardcoding it, name the distance metric the model was trained for and say why you picked it, and add a payload index for every field I will filter on. Finish by telling me which of these I cannot change later without recreating the collection.
@@ -3,11 +3,4 @@ title: "Diagnose high memory usage"
skill: qdrant-performance-optimization/memory-usage-optimization
page: /documentation/ops-optimization/optimize/
---
My Qdrant memory usage is higher than I expected, or a node was killed for
running out of memory. Read
https://skills.qdrant.tech/qdrant-performance-optimization/memory-usage-optimization/SKILL.md
first, then ask me for my collection configuration before proposing anything.
Tell me which component is actually consuming the memory, whether that is the
vectors, the HNSW index, or the payload indexes, and give me the fixes in order
of impact. Say which ones need a reindex, and what recall I would lose if I
quantize.
My Qdrant memory usage is higher than I expected, or a node was killed for running out of memory. Read https://skills.qdrant.tech/qdrant-performance-optimization/memory-usage-optimization/SKILL.md first, then ask me for my collection configuration before proposing anything. Tell me which component is actually consuming the memory, whether that is the vectors, the HNSW index, or the payload indexes, and give me the fixes in order of impact. Say which ones need a reindex, and what recall I would lose if I quantize.
@@ -3,10 +3,4 @@ title: "Review my deployment"
skill: qdrant-sizing
page: /documentation/production-checklist/
---
Review my Qdrant deployment before I put production traffic on it. Read
https://skills.qdrant.tech/qdrant-sizing/SKILL.md, then ask me for my
collection configuration, my expected vector count and query rate, and the
hardware I have provisioned. Tell me which of my settings will not survive real
load, ordered by how much it would hurt, and separate what I can change later
from what needs the collection recreated. Where my numbers do not support a
conclusion, say what to measure rather than guessing.
Review my Qdrant deployment before I put production traffic on it. Read https://skills.qdrant.tech/qdrant-sizing/SKILL.md, then ask me for my collection configuration, my expected vector count and query rate, and the hardware I have provisioned. Tell me which of my settings will not survive real load, ordered by how much it would hurt, and separate what I can change later from what needs the collection recreated. Where my numbers do not support a conclusion, say what to measure rather than guessing.
@@ -3,9 +3,4 @@ title: "Set up monitoring"
skill: qdrant-monitoring/setup
page: /documentation/ops-monitoring/monitoring/
---
Help me set up monitoring for my Qdrant deployment. Read
https://skills.qdrant.tech/qdrant-monitoring/setup/SKILL.md first, then ask me
whether I am self-hosted, on Qdrant Cloud, or on Hybrid Cloud, since the scrape
setup differs. Give me the Prometheus scrape config, the health probes worth
wiring up, and the three or four alerts that would actually have caught a real
incident. Tell me which metrics to ignore.
Help me set up monitoring for my Qdrant deployment. Read https://skills.qdrant.tech/qdrant-monitoring/setup/SKILL.md first, then ask me whether I am self-hosted, on Qdrant Cloud, or on Hybrid Cloud, since the scrape setup differs. Give me the Prometheus scrape config, the health probes worth wiring up, and the three or four alerts that would actually have caught a real incident. Tell me which metrics to ignore.
@@ -29,7 +29,7 @@ Qdrant supports these most popular types of metrics:
In addition to metrics and vector size, each collection uses its own set of parameters that controls collection optimization, index construction, and vacuum.
These settings can be changed at any time by a corresponding request.
If you would rather have an agent design this with you, the following prompt asks it for your data and query shape first, then commits to a vector configuration and the payload indexes to create.
To hand this to an agent instead, the Design a collection prompt makes it ask about your data and query shape first, then commit to a vector configuration and the payload indexes to create.
{{< prompt "design-a-collection" >}}
@@ -21,7 +21,7 @@ The integration with Qdrant is easy to
[configure](https://prometheus.io/docs/prometheus/latest/getting_started/#configure-prometheus-to-monitor-the-sample-targets)
with Prometheus and Grafana.
If you would rather have an agent handle this, use the following prompt to select the appropriate configuration for your deployment type and recommend relevant alerts.
If you would rather have an agent handle this, the Set up monitoring prompt asks it to select the right configuration for your deployment type and recommend the alerts worth wiring up.
{{< prompt "set-up-monitoring" >}}
@@ -25,7 +25,7 @@ This guide will walk you three main optimization strategies:
This page covers the <code>memory</code> parameter introduced in Qdrant v1.19. If you're using an older version, see the <a href="/documentation/ops-configuration/memory-tiers/#legacy-settings">Legacy Settings</a> section for how to map the new parameter to the old ones.
</aside>
If you would rather have an agent work through this with you, the following prompt asks it to find which component is actually using the memory before it suggests any changes.
An agent can work through this with you. The Diagnose high memory usage prompt makes it find which component is actually using the memory before it suggests any changes.
{{< prompt "diagnose-memory-usage" >}}
@@ -10,7 +10,7 @@ weight: 147
A practical checklist to ensure Qdrant is optimized, stable, and ready to handle real-world load.
If you would rather have an agent run through this with you, use the following prompt to get a prioritized list of what would break first under real load.
An agent can run the checklist with you. The Review my deployment prompt asks it for a prioritized list of what would break first under real load.
{{< prompt "review-before-launch" >}}
@@ -7,6 +7,10 @@
Keep in step with prompt-index.html, which emits table markup instead of
pipes because shortcode output is not re-parsed as markdown.
Page links are absolute and index.md-suffixed to match every other link in
this output, which single.markdown.md rewrites that way. A bare site path
would be the one column an agent reading this table could not resolve.
*/ -}}
{{- $section := site.GetPage "documentation/headless/prompts" -}}
{{- if not $section -}}
@@ -15,5 +19,5 @@
| Prompt | Page | Agent skill |
|---|---|---|
{{ range $section.RegularPages.ByTitle -}}
| {{ .Title }} | {{ with .Params.page }}{{ . }}{{ else }}None{{ end }} | {{ with .Params.skill }}https://skills.qdrant.tech/{{ . }}/SKILL.md{{ else }}None{{ end }} |
| {{ .Title }} | {{ with .Params.page }}{{ with site.GetPage . }}{{ .Permalink }}index.md{{ else }}{{ . }}{{ end }}{{ else }}None{{ end }} | {{ with .Params.skill }}https://skills.qdrant.tech/{{ . }}/SKILL.md{{ else }}None{{ end }} |
{{ end -}}
@@ -1,10 +1,22 @@
@use '../helpers/functions' as *;
// Both themes are declared here so a palette change is a one-block edit. The
// light values were previously written as literals at the use site, which is
// how a palette silently stops being the palette.
$prompt-surface: $neutral-20;
$prompt-border: $neutral-40;
$prompt-text: $neutral-98;
$prompt-text-muted: $neutral-70;
$prompt-accent: $primary-60;
// The body block sits deeper than the card. Without this it renders the same
// $neutral-20 as the card and the prompt reads as loose monospace in a box.
$prompt-block-surface: $neutral-10;
$prompt-surface-light: $neutral-98;
$prompt-border-light: $neutral-94;
$prompt-text-light: $neutral-10;
$prompt-text-muted-light: $neutral-50;
$prompt-accent-light: $primary-40;
.prompt {
background: $prompt-surface;
@@ -79,9 +91,24 @@ $prompt-accent: $primary-60;
padding: 0 pxToRem(16) pxToRem(16);
}
// The fenced block Chroma emits inside the body.
// The block Chroma emits inside the body.
.highlight {
margin: 0;
background: $prompt-block-surface;
}
// A prompt is prose, not code. Its line breaks come from how the author
// wrapped the source file, so a fixed-width <pre> clips every line at any
// window narrower than the wrap width instead of reflowing. Sideways
// scrolling is a fair bargain for code and a bad one for a paragraph.
// pre-wrap keeps the deliberate line structure in prompts that have one.
.highlight > pre {
white-space: pre-wrap;
overflow-wrap: break-word;
// copy-code.js absolutely positions its button at the top right of
// .highlight. Wrapped text now reaches the full width, so the first line
// would run underneath it.
padding-right: pxToRem(56);
}
&__skill {
@@ -99,9 +126,9 @@ $prompt-accent: $primary-60;
}
[data-theme='light'] & {
background: $neutral-98;
border-color: $neutral-94;
border-left-color: $primary-40;
background: $prompt-surface-light;
border-color: $prompt-border-light;
border-left-color: $prompt-accent-light;
}
}
@@ -109,25 +136,25 @@ $prompt-accent: $primary-60;
// lands in the descendant position, where it can never match, because the
// theme attribute sits on <html>.
[data-theme='light'] .prompt__summary {
color: $neutral-10;
color: $prompt-text-light;
}
[data-theme='light'] .prompt__summary::before {
border-right-color: $primary-40;
border-bottom-color: $primary-40;
border-right-color: $prompt-accent-light;
border-bottom-color: $prompt-accent-light;
}
[data-theme='light'] .prompt__summary:hover {
color: $primary-40;
color: $prompt-accent-light;
}
[data-theme='light'] .prompt__skill,
[data-theme='light'] .prompt__kind {
color: $neutral-50;
color: $prompt-text-muted-light;
}
[data-theme='light'] .prompt__kind {
border-right-color: $neutral-94;
border-right-color: $prompt-border-light;
}
@media (prefers-reduced-motion: reduce) {
@@ -3,10 +3,15 @@
Usage: {{< prompt "set-up-monitoring" >}}
The prompt file's body is plain text. This template wraps it in a fenced
block and runs it through markdownify so Chroma produces a real
`.highlight > pre`, which copy-code.js finds and adds a copy button to. That
is why this element needs no JavaScript of its own.
The prompt file's body is plain text. `highlight` hands it to Chroma as a
value, producing a real `.highlight > pre`, which copy-code.js finds and adds
a copy button to. That is why this element needs no JavaScript of its own.
It is deliberately not wrapped in a fence and run through markdownify. A body
containing its own ``` would close that outer fence early, truncating the
prompt and spilling the rest of it onto the page as loose markdown, with a
clean build and a green check. `highlight` never re-parses the body, so a
prompt can contain any characters at all.
The Markdown output format has its own variant, prompt.markdown.md, which
deliberately drops the body so an agent reading index.md is not handed an
@@ -15,7 +20,7 @@
{{- $id := .Get 0 -}}
{{- $p := site.GetPage (printf "documentation/headless/prompts/%s" $id) -}}
{{- if not $p -}}
{{- errorf "prompt: no prompt file found for id %q (looked in content/documentation/headless/prompts/). Called from %s" $id .Page.File.Path -}}
{{- errorf "prompt: no prompt file found for id %q (looked in content/documentation/headless/prompts/). Called from %s" $id .Page.RelPermalink -}}
{{- end -}}
<details class="prompt" id="prompt-{{ $id }}"{{ if $p.Params.open }} open{{ end }}>
<summary class="prompt__summary">
@@ -27,7 +32,7 @@
<span class="prompt__summary-label">{{ $p.Title }}</span>
</summary>
<div class="prompt__body">
{{ printf "```text\n%s\n```" (trim $p.RawContent "\n") | markdownify }}
{{ highlight (trim $p.RawContent "\n") "text" "" }}
{{- with $p.Params.skill }}
<p class="prompt__skill">
Uses the