Skip to content
Merged
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
1 change: 1 addition & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ https://issues.hibernatingrhinos.com/issue/RDoc-...

- [ ] Content - docs
- [ ] Content - cloud
- [ ] Content - Quill
- [ ] Content - guides
- [ ] Content - start pages/other
- [ ] New docs feature (consider updating `/templates` or readme)
Expand Down
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ npm test # Run unit tests (custom Docusaurus plugins)
```
docs/ # Current (7.2) doc content — EDIT HERE
cloud/ # RavenDB Cloud portal docs
quill/ # Quill docs
guides/ # Community guides (frontmatter-driven, tag-indexed)
templates/ # Doc authoring templates
versioned_docs/version-X.Y/ # Per-version snapshots (Docusaurus-managed) — editable for bugfixes
Expand All @@ -43,6 +44,7 @@ scripts/ # Build/deploy automation
static/icons/ # SVG icon assets (source for icon type generation)
sidebars.ts # Main docs sidebar config
sidebarsCloud.js # Cloud docs sidebar
sidebarsQuill.js # Quill docs sidebar
sidebarsGuides.js # Guides sidebar
sidebarsTemplates.js # Templates sidebar
docusaurus.config.ts # Main Docusaurus config (versions, search, plugins)
Expand Down Expand Up @@ -484,6 +486,9 @@ related_resources:
### `cloud/` — RavenDB Cloud service documentation (~24 files)
Account management, instance configuration, security (TLS, MFA, certificates), pricing/billing, scaling, backup/restore, migration, AWS/Azure Marketplace setup, and the cloud portal UI (home, products, billing, backups, support tabs).

### `quill/` — Quill documentation (~1 file)
Docs for Quill, served at `/quill` by its own `content-docs` instance (versionless, same wiring as `cloud/`). Sidebar in `sidebarsQuill.js`.

### `guides/` — Practical how-to guides (~64 files, flat structure)
Community guides covering: connecting specific frameworks (ASP.NET Core, Next.js, SvelteKit, FastAPI), AI/ML integration, DevOps (Docker, Kubernetes/EKS, Helm, Ansible), observability (Datadog, Grafana/OpenTelemetry), data pipelines (Elasticsearch, Azure Queue, OLAP ETL), testing (unit test drivers for .NET/Java/Python), and troubleshooting specific problems.

Expand Down
10 changes: 10 additions & 0 deletions docusaurus.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,16 @@ const config: Config = {
editUrl: "https://github.com/ravendb/docs/edit/main",
},
],
[
"content-docs",
{
id: "quill",
path: "quill",
routeBasePath: "quill",
sidebarPath: require.resolve("./sidebarsQuill.js"),
editUrl: "https://github.com/ravendb/docs/edit/main",
},
],
[
"content-docs",
{
Expand Down
4 changes: 4 additions & 0 deletions quill/_category_.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"position": 13,
"label": "Quill"
}
13 changes: 13 additions & 0 deletions quill/home.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
slug: /
title: Quill Documentation
hide_title: true
pagination_next: null
pagination_prev: null
wrapperClassName: quillHomePage
hide_table_of_contents: true
---

import QuillComingSoon from "@site/src/components/Quill/QuillComingSoon";

<QuillComingSoon />
3 changes: 2 additions & 1 deletion scripts/ai/build-description-manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ def extract_frontmatter(content):
def get_section_path(filepath):
rel = os.path.relpath(filepath, BASE).replace(os.sep, "/")
parts = rel.split("/")
if parts[0] in ("docs", "cloud"):
if parts[0] in ("docs", "cloud", "quill"):
section_parts = parts[1:-1]
else:
section_parts = parts[:-1]
Expand Down Expand Up @@ -74,6 +74,7 @@ def find_csharp_partial(filepath):
patterns = [
os.path.join(BASE, "docs", "**", "*.mdx"),
os.path.join(BASE, "cloud", "**", "*.mdx"),
os.path.join(BASE, "quill", "**", "*.mdx"),
]

all_files = []
Expand Down
1 change: 1 addition & 0 deletions scripts/handle_redirects.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ async function handler(event) {
if (
normalizedUri.startsWith("/guides") ||
normalizedUri.startsWith("/cloud") ||
normalizedUri.startsWith("/quill") ||
normalizedUri.startsWith("/samples")
) {
try {
Expand Down
22 changes: 22 additions & 0 deletions sidebarsQuill.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file has to be in JavaScript, otherwise @docusaurus/plugin-content-docs doesn't work properly
export default {
quill: [
{
type: "category",
label: "Quill",
link: {
type: "doc",
id: "home",
},
collapsible: false,
items: [
{
type: "doc",
id: "home",
label: "Home",
className: "hidden", // <-- This makes the default item invisible, while still rendering the sidebar
},
],
},
],
};
3 changes: 2 additions & 1 deletion src/components/Common/contentSource.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { IconName } from "@site/src/typescript/iconName";

// Shared by See Also, sample related-resources, and search results.
export type ContentSource = "docs" | "cloud" | "guides" | "samples" | "external";
export type ContentSource = "docs" | "cloud" | "quill" | "guides" | "samples" | "external";

export const CONTENT_SOURCES: Record<ContentSource, { label: string; icon: IconName }> = {
docs: { label: "Docs", icon: "document2" },
cloud: { label: "Cloud", icon: "cloud" },
quill: { label: "Quill", icon: "sparkles" },
guides: { label: "Guide", icon: "guides" },
samples: { label: "Sample", icon: "code" },
external: { label: "External", icon: "newtab" },
Expand Down
31 changes: 31 additions & 0 deletions src/components/Quill/QuillComingSoon.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Blueprint grid background — masked to fade out toward the edges. */
.grid {
background-image:
linear-gradient(to right, var(--ifm-color-emphasis-200) 1px, transparent 1px),
linear-gradient(to bottom, var(--ifm-color-emphasis-200) 1px, transparent 1px);
background-size: 44px 44px;
mask-image: radial-gradient(ellipse 70% 70% at 50% 45%, #000 30%, transparent 100%);
-webkit-mask-image: radial-gradient(ellipse 70% 70% at 50% 45%, #000 30%, transparent 100%);
}

/* Soft brand-colored glow behind the content. */
.glow {
background: radial-gradient(circle, var(--ifm-color-primary) 0%, transparent 70%);
}

/* Pulsing dot in the "Coming soon" badge. */
.pulseDot {
animation: pulse 2s infinite;
}

@keyframes pulse {
0% {
box-shadow: 0 0 0 0 rgba(var(--quill-pulse-rgb, 15 118 110), 0.5);
}
70% {
box-shadow: 0 0 0 8px rgba(var(--quill-pulse-rgb, 15 118 110), 0);
}
100% {
box-shadow: 0 0 0 0 rgba(var(--quill-pulse-rgb, 15 118 110), 0);
}
}
46 changes: 46 additions & 0 deletions src/components/Quill/QuillComingSoon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { ReactNode } from "react";
import Link from "@docusaurus/Link";
import Heading from "@theme/Heading";
import { useLatestVersion } from "@docusaurus/plugin-content-docs/client";
import styles from "./QuillComingSoon.module.css";

export default function QuillComingSoon(): ReactNode {
const latestVersion = useLatestVersion("default");

return (
<section className="relative flex items-center justify-center overflow-hidden rounded-2xl px-6 py-16 min-h-[calc(100vh-var(--ifm-navbar-height)-4rem)]">
<div className={`${styles.grid} absolute inset-0 opacity-70`} aria-hidden="true" />
<div
className={`${styles.glow} pointer-events-none absolute top-[30%] left-1/2 h-[340px] w-[min(680px,90%)] -translate-x-1/2 -translate-y-1/2 opacity-[0.12] blur-xl`}
aria-hidden="true"
/>

<div className="relative z-10 flex max-w-3xl flex-col items-center gap-4 text-center">
<span className="inline-flex items-center gap-4 rounded-full border border-[var(--ifm-color-emphasis-200)] bg-[var(--ifm-color-primary-contrast-background)] px-3.5 py-1.5 text-[0.8125rem] font-semibold tracking-wide uppercase text-[var(--ifm-color-primary)]">
<span
className={`${styles.pulseDot} h-[7px] w-[7px] rounded-full bg-[var(--ifm-color-primary)]`}
aria-hidden="true"
/>
Coming soon
</span>
<div className="flex flex-col items-center gap-4">
<Heading as="h1">Quill documentation is on the way</Heading>

<p
style={{ margin: 0 }}
className="max-w-[34rem] text-md leading-relaxed text-[var(--ifm-color-emphasis-700)]"
>
We're busy writing the docs for Quill. In the meantime, explore the rest of the RavenDB
documentation or reach out if you have questions.
</p>
</div>

<div className="flex flex-wrap justify-center gap-3">
<Link to={`/${latestVersion.label}`} className="button button--primary">
Browse RavenDB docs
</Link>
</div>
</div>
</section>
);
}
11 changes: 8 additions & 3 deletions src/components/Samples/Overview/Partials/RelatedResource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { useLatestVersion } from "@site/src/hooks/useLatestVersion";

type ResourceType = "guide" | "documentation" | "video";

type DocumentationType = "docs" | "cloud";
type DocumentationType = "docs" | "cloud" | "quill";

const VERSIONLESS_DOC_AREAS: Partial<Record<DocumentationType, { basePath: string; icon: IconName }>> = {
cloud: { basePath: "/cloud", icon: "cloud" },
quill: { basePath: "/quill", icon: "sparkles" },
};

export interface RelatedResourceProps {
className?: string;
Expand Down Expand Up @@ -53,11 +58,11 @@ export default function RelatedResource({
return `/guides/${articleKey}`;
}

const basePath = documentationType === "cloud" ? "/cloud" : `/${latestVersion}`;
const basePath = VERSIONLESS_DOC_AREAS[documentationType]?.basePath ?? `/${latestVersion}`;
return `${basePath}/${articleKey}`;
}, [type, documentationType, articleKey, externalUrl, latestVersion]);

const icon = type === "documentation" && documentationType === "cloud" ? "cloud" : config.icon;
const icon = (type === "documentation" ? VERSIONLESS_DOC_AREAS[documentationType]?.icon : undefined) ?? config.icon;

return (
<Link
Expand Down
1 change: 1 addition & 0 deletions src/components/Search/SearchResultBadge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const BADGE_CLASSES: Record<ContentSource, string> = {
docs: "bg-black/5 dark:bg-white/5 text-ifm-menu border-black/10 dark:border-white/10",
guides: "bg-emerald-500/15 text-emerald-700 dark:text-emerald-300 border-emerald-600/25 dark:border-emerald-400/25",
cloud: "bg-sky-500/15 text-sky-700 dark:text-sky-300 border-sky-600/25 dark:border-sky-400/25",
quill: "bg-amber-500/15 text-amber-700 dark:text-amber-300 border-amber-600/25 dark:border-amber-400/25",
samples: "bg-violet-500/15 text-violet-700 dark:text-violet-300 border-violet-600/25 dark:border-violet-400/25",
external: "bg-black/5 dark:bg-white/5 text-ifm-menu border-black/10 dark:border-white/10",
};
Expand Down
2 changes: 2 additions & 0 deletions src/components/Search/searchSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ContentSource } from "@site/src/components/Common/contentSource";
const SOURCE_BY_PLUGIN_ID: Record<string, ContentSource> = {
default: "docs",
cloud: "cloud",
quill: "quill",
guides: "guides",
samples: "samples",
};
Expand Down Expand Up @@ -54,6 +55,7 @@ export const SEARCH_FILTER_GROUPS: SearchFilter[][] = [
{ label: "Docs", kind: "docs", pluginId: "default" },
{ label: "Guides", kind: "guides", pluginId: "guides" },
{ label: "Cloud", kind: "cloud", pluginId: "cloud" },
{ label: "Quill", kind: "quill", pluginId: "quill" },
],
[{ label: "Samples", kind: "samples", pluginId: "samples" }],
];
Expand Down
3 changes: 2 additions & 1 deletion src/components/SeeAlso/useVersionedLink.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ export function useVersionedLink() {
return link;
}

const isUnversionedSection = /^\/(cloud|guides|samples|templates)(\/|$)/.test(link);
const isUnversionedSection = /^\/(cloud|quill|guides|samples|templates)(\/|$)/.test(link);

if (isUnversionedSection) {
return link;
}

const versionToUse =
currentPluginId === "cloud" ||
currentPluginId === "quill" ||
currentPluginId === "guides" ||
currentPluginId === "samples" ||
currentPluginId === "templates"
Expand Down
2 changes: 2 additions & 0 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -590,6 +590,7 @@ hr {
/* Full width override */
.guidesHomePage [class*="docItemCol"],
.cloudHomePage [class*="docItemCol"],
.quillHomePage [class*="docItemCol"],
.docsHomePage [class*="docItemCol"],
.samplesHomePage [class*="docItemCol"],
.plugin-id-samples [class*="docItemCol"] {
Expand Down Expand Up @@ -719,6 +720,7 @@ a {
/* Disable navigation for Docs */
.plugin-id-default .pagination-nav,
.plugin-id-cloud .pagination-nav,
.plugin-id-quill .pagination-nav,
.plugin-id-samples .pagination-nav {
display: none;
}
Expand Down
2 changes: 2 additions & 0 deletions src/lib/split-sitemap/lib/split.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* and lets us re-ping only changed sections on deploy.
*
* /cloud/* → sitemap-cloud.xml
* /quill/* → sitemap-quill.xml
* /guides/* → sitemap-guides.xml
* /samples/* → sitemap-samples.xml
* /X.Y/* → sitemap-docs-X.Y.xml (if X.Y isn't legacy)
Expand Down Expand Up @@ -46,6 +47,7 @@ export interface SplitSucceeded {

const SECTION_MAP: Record<string, string> = {
cloud: "sitemap-cloud.xml",
quill: "sitemap-quill.xml",
guides: "sitemap-guides.xml",
samples: "sitemap-samples.xml",
};
Expand Down
6 changes: 5 additions & 1 deletion src/plugins/versioned-seo-plugin/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,11 @@ const versionedSeoPlugin = function versionedSeoPlugin(
// SeeAlso audit: currently-maintained versioned pages + unversioned content sections.
const shouldAuditSeeAlso =
(info && !LEGACY_VERSIONS.includes(info.version)) ||
(!info && (rel.startsWith("cloud/") || rel.startsWith("guides/") || rel.startsWith("samples/")));
(!info &&
(rel.startsWith("cloud/") ||
rel.startsWith("quill/") ||
rel.startsWith("guides/") ||
rel.startsWith("samples/")));
if (shouldAuditSeeAlso) {
seeAlsoRecords.push(
...fanoutSeeAlsoRecords(
Expand Down
12 changes: 7 additions & 5 deletions src/plugins/versioned-seo-plugin/lib/redirects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
export type RedirectMap = Map<string, { targetUrl: string; minimumVersion?: string }>;

/** Key prefixes whose content area has no version axis. */
const VERSIONLESS_KEY_PREFIXES = ["/guides/", "/cloud/"] as const;
const VERSIONLESS_KEY_PREFIXES = ["/guides/", "/cloud/", "/quill/"] as const;

function isVersionlessKey(key: string): boolean {
return VERSIONLESS_KEY_PREFIXES.some((p) => key.startsWith(p));
Expand Down Expand Up @@ -177,10 +177,12 @@
return errors;
}

/** /guides and /cloud are versionless content roots; everything else lives under docsRoot. */
/** /guides, /cloud and /quill are versionless content roots; everything else lives under docsRoot. */
const VERSIONLESS_ROOTS = new Set(["guides", "cloud", "quill"]);

function targetBasePath(target: string, projectRoot: string, docsRoot: string): string {
const [first, ...rest] = target.split("/").filter(Boolean);
return first === "guides" || first === "cloud"
return first && VERSIONLESS_ROOTS.has(first)
? path.join(projectRoot, first, ...rest)
: path.join(docsRoot, first ?? "", ...rest);
}
Expand All @@ -196,7 +198,7 @@

/**
* Check every targetUrl resolves to a real page. Versionless rules
* (/guides, /cloud) are checked once; versioned rules are checked against
* (/guides, /cloud, /quill) are checked once; versioned rules are checked against
* every version in `versions` where their `minimumVersion` gate fires.
*
* Targets are walked through `resolveChain` first — if a rule's target is
Expand All @@ -218,7 +220,7 @@

if (isVersionlessKey(rule.key)) {
// Versionless rule: target has no version axis, check once.
// Edge does single-hop for /guides + /cloud, so we don't chain.
// Edge does single-hop for /guides + /cloud + /quill, so we don't chain.
if (!fileExists(targetBasePath(target, projectRoot, currentDocsRoot))) {
errors.push({
index,
Expand All @@ -230,7 +232,7 @@
}

for (const version of versions) {
if (compareVersions(version, rule.value.minimumVersion!) < 0) continue;

Check warning on line 235 in src/plugins/versioned-seo-plugin/lib/redirects.ts

View workflow job for this annotation

GitHub Actions / build

Expected { after 'if' condition
const finalTarget = resolveChain(map, target, version);
const docsRoot =
version === currentVersion
Expand Down
Loading
Loading