Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
26bdf96
start client split
Deflaimun Jun 9, 2025
2b6c660
docs: initial client-split cleanup for NodeJS
Jun 16, 2025
a785ee2
docs: initial client-split cleanup for Python
Jun 16, 2025
00c4d54
docs: initial client split cleanup for Rust
Jun 16, 2025
b279058
docs: client split work - fixing broken image link
Jun 16, 2025
4df00f4
docs: initial client split cleanup for Java
Jun 16, 2025
b473bce
docs: initial client split cleanup for Go
Jun 16, 2025
afb4160
docs: initial client split cleanup for C#
Jun 16, 2025
6413532
docs: client split cleanup - tighten up release notes topic
Jun 16, 2025
7237167
docs: client split cleanup - fix subscription topic
Jun 17, 2025
1ba2d0f
docs: client split cleanup - tighten up required packages sections
Jun 17, 2025
f9506ba
docs: removed old non-split client files
Jun 17, 2025
c849f01
docs: fix code sample
Jun 17, 2025
abc4080
Update samples script and adjust navbar
Deflaimun Jun 17, 2025
c739bd4
remove "client" from headers
Deflaimun Jun 17, 2025
9af6713
Merge branch 'master' into client-split
stktung Jul 9, 2025
2529767
Renamed c# dir to dotnet, javascript dir to nodejs
stktung Jul 9, 2025
3ff3a80
Update nav and sidebar for language split
stktung Jul 9, 2025
dac7101
Remove remaining snippets with multiple languages
stktung Jul 10, 2025
b5fb901
Removed links to observability samples of unrelated languages
stktung Jul 10, 2025
265d03a
MD cleanup
stktung Jul 10, 2025
fd54ab2
Made note that delete projection is not available for dotnet client
stktung Jul 10, 2025
3150a91
Removed unnecessary package installation instructions
stktung Jul 10, 2025
7f6f698
Removed observability page for python since it's not available
stktung Jul 10, 2025
d7071b3
Removed user cert samples for unrelated languages
stktung Jul 10, 2025
d8acd1e
Re-added the old pages to help redirect to right lang
stktung Jul 10, 2025
f28ef57
Fixed breadcrumbs
stktung Jul 10, 2025
e94e6bc
Updated custom browser title for SEO
stktung Jul 10, 2025
f8e94d9
Ask SEO not to index the old client pages anymore
stktung Jul 10, 2025
e67cce1
Added missing rust user cert sample
stktung Jul 10, 2025
370d65e
Added redirects for language pages straight to getting started
stktung Jul 10, 2025
15be5cd
Fixed custom title of .net client appending events
stktung Jul 11, 2025
d9d75ca
[DEV-367] Import client docs (#903)
w1am Jul 28, 2025
0b831b6
Sync with master
w1am Jul 28, 2025
3d2825b
Add redirects for latest
w1am Jul 29, 2025
2c62338
Add clients page
w1am Jul 29, 2025
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
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -344,3 +344,7 @@ generated-versions.json
docs/.vuepress/.temp/
docs/.vuepress/.cache/
docs/.vuepress/dist/

config.ts.*.mjs

docs/clients/grpc/**/*
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ Configuration for sidebars can be found in the `/docs/.vuepress/configs/sidebar.

```typescript
export const sidebarEn: EsSidebarOptions = {
"/clients/grpc/": "structure",
"/clients/": "structure",
"/cloud/": "structure",
}
```
Expand Down
84 changes: 61 additions & 23 deletions docs/.vuepress/client.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import {defineClientConfig, useRoute} from 'vuepress/client';
import "iconify-icon";
import {onMounted} from "vue";
import type {RouteLocationNormalized, Router} from "vue-router";
import type {RouteLocationNormalized} from "vue-router";
import {defineClientConfig, useRoute} from 'vuepress/client';
import CloudBanner from "./components/CloudBanner.vue";
import ClientsGrid from "./components/ClientsGrid.vue";
import KapaWidget from './components/KapaWidget.vue';
import UserFeedback from './components/TocWithFeedback';
import {usePostHog} from "./lib/usePosthog";
import SidebarLayout from "./layouts/SidebarLayout.vue";
import {usePostHog} from "./lib/usePosthog";

declare const __VERSIONS__: { latest: string, selected: string, all: string[] }
declare const __VERSIONS__: {
latest: string,
selected: string,
all: {
id: string,
group: string,
basePath: string,
versions: {
version: string,
path: string,
startPage: string,
preview?: boolean,
deprecated?: boolean,
hide?: boolean
}[]
}[]
}

const storageKey = "VUEPRESS_TAB_STORE";

const clients = ":lang(dotnet|golang|java|node|python|rust)"

const findMetaKey = (record: any[], key: string) => {
if (record[0] !== "meta") return null;
const data = record[1];
Expand All @@ -31,15 +50,6 @@ const findEsMeta = (route) => {
}
}

// interface ClientConfig {
// enhance?: (context: {
// app: any;
// router: Router;
// siteData: any;
// }) => void | Promise<void>;
// setup?: () => void;
// }

const removeHtml = (path: string) => path.replace(".html", "");

const reload = () => {
Expand All @@ -64,9 +74,9 @@ export default defineClientConfig({
},
enhance({app, router, _}) {
app.component("CloudBanner", CloudBanner);
app.component("ClientsGrid", ClientsGrid);
app.component("KapaWidget", KapaWidget);
app.component("UserFeedback", UserFeedback);
const apiPath = __VERSIONS__.latest.replace("server", "http-api");
const addFixedRoute = (from: string, to: string) => router.addRoute({
path: from, redirect: _ => {
reload();
Expand All @@ -83,7 +93,7 @@ export default defineClientConfig({
});

// Router configuration
addFixedRoute("/http-api/", `${apiPath}/introduction`);
addFixedRoute("/server/http-api/", `/${__VERSIONS__.latest}/http-api/introduction`);
addFixedRoute("/cloud/", `/cloud/introduction.html`);
router.afterEach(() => {
setTimeout(() => { // to ensure this runs after DOM updates
Expand All @@ -102,18 +112,46 @@ export default defineClientConfig({
}
}, 0);
});
const operatorLatest = __VERSIONS__.all.filter(x => x.id == 'kubernetes-operator')[0].versions[0].version;
const operatorLatest = __VERSIONS__.all.filter(x => x.id === 'kubernetes-operator')[0].versions[0].version;
addDynamicRoute("/server/kubernetes-operator", to => `/server/kubernetes-operator/${operatorLatest}/getting-started/`);
addDynamicRoute("/server/kubernetes-operator/:version", to => `/server/kubernetes-operator/${to.params.version}/getting-started/`);

// Clients routes
addFixedRoute(`/clients/grpc/:pathMatch(.*)*`, "/clients/");

addDynamicRoute(`/clients/${clients}/latest/:pathMatch(.*)*`, to => {
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions[0]
return `/clients/${to.params.lang}/${latestVersion?.version}/${to.params.pathMatch}`;
});
addDynamicRoute(`/clients/${clients}/latest`, to => {
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions[0]
return `/clients/${to.params.lang}/${latestVersion?.version}/${latestVersion?.startPage}`;
});
addDynamicRoute(`/clients/${clients}/legacy/:version`, to => {
const version = to.params.version;
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions.find(v => v.path === `legacy/${version}`)
return `/clients/${to.params.lang}/legacy/${to.params.version}/${latestVersion?.startPage}`;
});
addDynamicRoute(`/clients/${clients}/legacy`, to => {
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions.find(v => v.path.startsWith('legacy/'))
return `/clients/${to.params.lang}/${latestVersion?.path}/${latestVersion?.startPage}`;
})
addDynamicRoute(`/clients/${clients}/:version`, to => {
const version = to.params.version;
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions.find(v => v.path === version)
return `/clients/${to.params.lang}/${version}/${latestVersion?.startPage}`;
});
addDynamicRoute(`/clients/${clients}`, to => {
const latestVersion = __VERSIONS__.all.find(x => x.id === `${to.params.lang}-client`)?.versions[0]
return `/clients/${to.params.lang}/${latestVersion?.path}/${latestVersion?.startPage}`;
})


// Add fixed routes for server versions because they don't use the same sidebar structure as the other versions
addFixedRoute("/server/v22.10", "/server/v22.10/introduction.html");
addFixedRoute("/server/v5", "/server/v5/introduction.html");

addDynamicRoute("/server/:version", to => `/server/${to.params.version}/quick-start/`);
addDynamicRoute('/client/:lang',
to => {
const lang = to.params.lang === "csharp" ? "C#" : to.params.lang;
const stored = JSON.parse(localStorage.getItem(storageKey) ?? "{}");
localStorage.setItem(storageKey, JSON.stringify({...stored, code: lang}));
return '/clients/grpc/getting-started.html';
});
addDynamicRoute('/latest/:pathMatch(.*)*', to => to.path.replace(/^\/latest/, `/${__VERSIONS__.latest}`));
addFixedRoute("/server/latest", `/${__VERSIONS__.latest}/quick-start/`);
addFixedRoute("/latest", `/${__VERSIONS__.latest}/quick-start/`);
Expand Down
144 changes: 144 additions & 0 deletions docs/.vuepress/components/ClientsGrid.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
<script setup lang="ts">
import { useRouter } from 'vue-router'

interface Client {
id: string
name: string
icon: string
path: string
}

const router = useRouter()

const clients: Client[] = [
{
id: 'dotnet-client',
name: '.NET',
icon: 'dotnet',
path: '/clients/dotnet/latest'
},
{
id: 'java-client',
name: 'Java',
icon: 'java',
path: '/clients/java/latest'
},
{
id: 'node-client',
name: 'Node.js',
icon: 'nodejs',
path: '/clients/node/latest'
},
{
id: 'python-client',
name: 'Python',
icon: 'python',
path: '/clients/python/latest'
},
{
id: 'golang-client',
name: 'Go',
icon: 'go',
path: '/clients/golang/latest'
},
{
id: 'rust-client',
name: 'Rust',
icon: 'rust',
path: '/clients/rust/latest'
}
]

const navigate = (client: Client): void => {
router.push(client.path)
}
</script>

<template>
<div class="clients-grid">
<div class="grid">
<div
v-for="client in clients"
:key="client.id"
class="client-card"
@click="navigate(client)"
>
<div class="client-icon">
<img
:src="`https://skillicons.dev/icons?i=${client.icon}`"
:alt="client.name"
class="skill-icon"
/>
</div>
<p>{{ client.name }}</p>
</div>
</div>
</div>
</template>

<style lang="scss" scoped>
.clients-grid {
padding: 2rem 0;
}

.grid {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
gap: 1.5rem;
max-width: 1200px;
}

.client-card {
background: var(--vp-c-bg-soft);
border: 1px solid var(--vp-c-border);
border-radius: 12px;
padding: 2rem;
text-align: center;
cursor: pointer;
position: relative;
overflow: hidden;

p {
margin: 0;
color: var(--vp-c-text-2);
font-size: 0.95rem;
line-height: 1.5;
text-align: center;
}
}

.client-icon {
margin-bottom: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
}

.skill-icon {
width: 48px;
height: 48px;
pointer-events: none;
}

.dark .client-card {
background: var(--vp-c-bg-alt);
}

@media (max-width: 768px) {
.grid {
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
gap: 1.5rem;
padding: 0 0.5rem;
}

.client-card {
padding: 1.5rem;
}
}

@media (max-width: 480px) {
.grid {
grid-template-columns: 1fr;
}
}
</style>
13 changes: 10 additions & 3 deletions docs/.vuepress/components/VersionDropdown.vue
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ const latestVersion = computed(() => props.versions[0]?.version);
const currentVersions = computed(() => props.versions.filter(v => !v.deprecated && !v.hide));
const deprecatedVersions = computed(() => props.versions.filter(v => v.deprecated && !v.hide));

watch(() => props.current, (newCurrent) => selectedVersion.value = newCurrent);
watch(() => props.current, (newCurrent) => {
selectedVersion.value = newCurrent;
});

const toggleDropdown = (): void => {
isOpen.value = !isOpen.value;
Expand All @@ -32,8 +34,13 @@ const closeDropdown = (): void => {
}

const handleVersionSelect = (version: VersionDetail): void => {
const base = route.path.split('/').filter(seg => seg)[0];
router.replace(`/${base}/${version.path}/${version.startPage}`);
const currentVersionPath = `/${props.current.path}/`;
const newVersionPath = `/${version.path}/`;

if (route.path.includes(currentVersionPath)) {
const basePart = route.path.split(currentVersionPath)[0];
router.replace(`${basePart}${newVersionPath}${version.startPage}`);
}

closeDropdown();
}
Expand Down
3 changes: 1 addition & 2 deletions docs/.vuepress/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,10 @@ export default defineUserConfig({
extendsMarkdown: md => {
md.use(replaceLinkPlugin, {
replaceLink: (link: string, _) => link
.replace("@server/", "/server/{version}/")
.replace("@server/", `/${ver.latest}/`)
.replace("@clients/grpc/", "/clients/grpc/")
.replace("@client/dotnet/5.0/", "/clients/tcp/dotnet/21.2/")
.replace("@httpapi/data/", projectionSamplesPath)
.replace("@httpapi/", "/server/v5/http-api/")
// Add tutorial and use case redirects
.replace(/^\/tutorials\/(.*)/, "/dev-center/tutorials/$1")
.replace(/^\/getting-started\/use-cases\/(.*)\/tutorial-([1-5])\.(md|html)/, "/dev-center/use-cases/$1/tutorial/tutorial-$2.$3")
Expand Down
44 changes: 20 additions & 24 deletions docs/.vuepress/configs/navbar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,8 @@ import type {NavbarOptions} from "vuepress-theme-hope";
import {instance as ver} from "../lib/versioning";

export const navbarEn: NavbarOptions = [
{
text: "Getting Started",
link: "/getting-started/introduction.html",
},
{
text: "Kurrent Cloud",
link: "/cloud/introduction",
},
{text: "Getting Started", link: "/getting-started/introduction.html"},
{text: "Kurrent Cloud", link: "/cloud/introduction"},
{
text: "KurrentDB",
children: [
Expand All @@ -23,28 +17,30 @@ export const navbarEn: NavbarOptions = [
{
text: "Clients",
children: [
{text: "KurrentDB clients", link: "/clients/grpc/getting-started"},
],
{text: ".NET", link: "/clients/dotnet/"},
{text: "Python", link: "/clients/python/"},
{text: "Node.js", link: "/clients/node/"},
{text: "Java", link: "/clients/java/"},
{text: "Go", link: "/clients/golang/"},
{text: "Rust", link: "/clients/rust/"},
]
},
{
text: "Deprecated",
children: [{text: "Legacy TCP clients", link: "/clients/tcp/"}],
},
}
],
},

{
text: "Developer Resources",
children: [
{
text: "Tutorials & Use cases",
link: "/dev-center/",
},
{text: "Community forum", link: "https://discuss.kurrent.io/"},
{text: "Community Discord ", link: "https://discord.gg/Phn9pmCw3t"},
{text: "Blogs", link: "https://www.kurrent.io/blog"},
{text: "Webinars", link: "https://www.kurrent.io/webinars"},
{text: "Kurrent Academy", link: "https://academy.kurrent.io"},
],
},
children:
[
{text: "Tutorials & Use cases", link: "/dev-center/"},
{text: "Community forum", link: "https://discuss.kurrent.io/"},
{text: "Community Discord ", link: "https://discord.gg/Phn9pmCw3t"},
{text: "Blogs", link: "https://www.kurrent.io/blog"},
{text: "Webinars", link: "https://www.kurrent.io/webinars"},
{text: "Kurrent Academy", link: "https://academy.kurrent.io"},
],
}
];
Loading
Loading