From a6a67a31cb9ccca64c652ea4d3af88af0bf88eec Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 06:11:03 +0000 Subject: [PATCH 1/6] design first draft #63 --- docs/getting-started.mdx | 5 +- src/css/custom.css | 959 ++++++++++++++++++++++++++++++++++++--- src/pages/index.tsx | 423 +++++++++-------- 3 files changed, 1140 insertions(+), 247 deletions(-) diff --git a/docs/getting-started.mdx b/docs/getting-started.mdx index 085c59c..7011bdf 100644 --- a/docs/getting-started.mdx +++ b/docs/getting-started.mdx @@ -57,6 +57,7 @@ Key features of Typesense Kubernetes Operator include: ## Disclaimer +:::warning read this carefully before you proceed TyKO is an independent and unofficial implementation and **is not affiliated with or endorsed by Typesense, Inc**. TyKO is provided **as-is** without any warranties or guarantees. Use at your own risk. While every effort has been made to ensure correctness and reliability, the maintainers are not responsible for any data loss, downtime, or other issues arising from the use of this software in production or other environments. @@ -67,5 +68,5 @@ Before deploying in a critical environment, we strongly recommend: - Testing in a safe, non-production setting, - Keeping up to date with issues and pull requests. -By using TyKO, you agree that you assume full responsibility for any outcomes related to its use. - +**By using TyKO, you agree that you assume full responsibility for any outcomes related to its use.** +::: diff --git a/src/css/custom.css b/src/css/custom.css index 2af8141..f0d0b45 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -1,63 +1,904 @@ /** - * Any CSS included here will be global. The classic template - * bundles Infima by default. Infima is a CSS framework designed to - * work well for content-centric websites. + * TyKO – Docusaurus custom theme + * Drop-in replacement for src/css/custom.css + * + * Design system: + * - Ember/orange accent pulled from the TyKO logo + * - Deep charcoal-navy for dark mode, warm paper for light mode + * - Inter for UI/body, JetBrains Mono for code + display accents + * - Semantic tokens only — no ad-hoc colors in components */ -/* You can override the default Infima variables here. */ +/* ---------- Fonts ---------- */ +@import url("https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500;600;700&display=swap"); + +/* ============================================================ + * Design Tokens + * ============================================================ */ :root { - --ifm-color-primary: #2e3c85; - --ifm-color-primary-dark: #293678; - --ifm-color-primary-darker: #273371; - --ifm-color-primary-darkest: #202a5d; - --ifm-color-primary-light: #334292; - --ifm-color-primary-lighter: #354599; - --ifm-color-primary-lightest: #3c4ead; - --ifm-code-font-size: 95%; - --ifm-font-family-base: 'JetBrains Mono', monospace; - --ifm-heading-font-family: 'JetBrains Mono', monospace; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); -} - -/* For readability concerns, you should choose a lighter palette in dark mode. */ -[data-theme='dark'] { - --ifm-color-primary: #c6c8d2; - --ifm-color-primary-dark: #afb2c0; - --ifm-color-primary-darker: #a4a7b7; - --ifm-color-primary-darkest: #82869c; - --ifm-color-primary-light: #dddee4; - --ifm-color-primary-lighter: #e8e9ed; - --ifm-color-primary-lightest: #ffffff; - --ifm-background-color: #2e3c85; - --ifm-background-surface-color: #2e3c85; - --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.3); -} - - /* Github */ - - .navbar--github-link { - width: 36px; - height: 36px; - padding: 6px; - margin-right: 12px; - margin-left: 6px; - border-radius: 50%; - transition: background var(--ifm-transition-fast); - } - - .navbar--github-link:hover { - background: var(--ifm-color-emphasis-200); - } - - .navbar--github-link:before { - content: ''; - height: 100%; - display: block; - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 25 25' width='25' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; - } - - html[data-theme='dark'] .navbar--github-link:before { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 25 25' width='25' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") - no-repeat; - } + /* Brand — from TyKO logo */ + --tyko-ember: #f26d3d; + --tyko-ember-bright: #ff8a5b; + --tyko-ember-deep: #c94a1e; + + /* Compatibility aliases used by later homepage sections */ + --tyko-charcoal: #14100d; + --tyko-ember-light: var(--tyko-ember-bright); + --tyko-ember-dark: var(--tyko-ember-deep); + --tyko-ember-glow: rgba(242, 109, 61, 0.35); + + /* Docusaurus primary mapping (Infima) */ + --ifm-color-primary: #ea5a24; + --ifm-color-primary-dark: #d24d1a; + --ifm-color-primary-darker: #c64719; + --ifm-color-primary-darkest: #a53a14; + --ifm-color-primary-light: #ef7a48; + --ifm-color-primary-lighter: #f28a5c; + --ifm-color-primary-lightest: #f8ad8c; + + /* Surfaces */ + --tyko-bg: #fbfaf7; + --tyko-bg-elevated: #ffffff; + --tyko-surface: #ffffff; + --tyko-surface-muted: #f4f2ed; + --tyko-border: #e7e3db; + --tyko-border-strong: #d6d1c6; + + /* Footer — alternates with the preceding homepage section */ + --tyko-footer-bg: var(--tyko-surface-muted); + --tyko-footer-text: var(--tyko-text-muted); + --tyko-footer-link: var(--tyko-ember-deep); + --tyko-footer-link-hover: var(--tyko-text); + --tyko-footer-border: var(--tyko-border); + + /* Text */ + --tyko-text: #1a1613; + --tyko-text-muted: #6b655c; + --tyko-text-subtle: #8f8a80; + + /* Effects */ + --tyko-radius: 14px; + --tyko-radius-sm: 10px; + --tyko-radius-lg: 22px; + --tyko-shadow-sm: 0 1px 2px rgba(24, 20, 16, 0.04), + 0 1px 3px rgba(24, 20, 16, 0.06); + --tyko-shadow-md: 0 4px 12px rgba(24, 20, 16, 0.06), + 0 2px 4px rgba(24, 20, 16, 0.04); + --tyko-shadow-glow: 0 10px 40px -12px rgba(242, 109, 61, 0.35); + + --tyko-gradient-ember: linear-gradient( + 135deg, + var(--tyko-ember-bright) 0%, + var(--tyko-ember) 45%, + var(--tyko-ember-deep) 100% + ); + --tyko-gradient-hero: radial-gradient( + 1200px 600px at 85% -10%, + rgba(242, 109, 61, 0.18), + transparent 60% + ), + radial-gradient( + 800px 400px at 0% 20%, + rgba(242, 109, 61, 0.08), + transparent 60% + ); + + /* Typography */ + --ifm-font-family-base: "Inter", ui-sans-serif, system-ui, -apple-system, + "Segoe UI", Roboto, sans-serif; + --ifm-font-family-monospace: "JetBrains Mono", ui-monospace, SFMono-Regular, + "SF Mono", Menlo, monospace; + --ifm-heading-font-family: "Inter", var(--ifm-font-family-base); + --ifm-heading-font-weight: 700; + --ifm-h1-font-size: 2.75rem; + --ifm-h2-font-size: 2rem; + --ifm-line-height-base: 1.65; + + /* Infima overrides */ + --ifm-background-color: var(--tyko-bg); + --ifm-background-surface-color: var(--tyko-surface); + --ifm-color-content: var(--tyko-text); + --ifm-color-content-secondary: var(--tyko-text-muted); + --ifm-navbar-background-color: rgba(251, 250, 247, 0.75); + --ifm-navbar-shadow: none; + --ifm-navbar-height: 68px; + --ifm-footer-background-color: var(--tyko-footer-bg); + --ifm-footer-color: var(--tyko-footer-text); + --ifm-footer-link-color: var(--tyko-footer-link); + --ifm-footer-title-color: var(--tyko-text); + --ifm-toc-border-color: transparent; + --ifm-code-font-size: 92%; + --ifm-code-background: rgba(242, 109, 61, 0.08); + --docusaurus-highlighted-code-line-bg: rgba(242, 109, 61, 0.12); + + /* Button text defaults — keep labels readable in both themes */ + --ifm-button-color: var(--tyko-text); + --ifm-button-background-color: transparent; +} + + +/* ---------- Dark theme ---------- */ +[data-theme="dark"] { + --ifm-color-primary: #ff7d47; + --ifm-color-primary-dark: #f66a30; + --ifm-color-primary-darker: #e85d22; + --ifm-color-primary-darkest: #bf4b1c; + --ifm-color-primary-light: #ff9366; + --ifm-color-primary-lighter: #ffa07a; + --ifm-color-primary-lightest: #ffc0a5; + + --tyko-bg: #0e0c0a; + --tyko-bg-elevated: #16130f; + --tyko-surface: #17140f; + --tyko-surface-muted: #1e1a15; + --tyko-border: #2a2620; + --tyko-border-strong: #3a3428; + + --tyko-footer-bg: var(--tyko-surface-muted); + --tyko-footer-text: var(--tyko-text-muted); + --tyko-footer-link: var(--tyko-ember-bright); + --tyko-footer-link-hover: var(--tyko-text); + --tyko-footer-border: var(--tyko-border); + + --tyko-text: #f4efe6; + --tyko-text-muted: #b8b0a3; + --tyko-text-subtle: #7d7669; + + --tyko-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4); + --tyko-shadow-md: 0 8px 24px rgba(0, 0, 0, 0.5); + --tyko-shadow-glow: 0 10px 60px -10px rgba(255, 125, 71, 0.45); + + --tyko-gradient-hero: radial-gradient( + 1200px 600px at 85% -10%, + rgba(255, 125, 71, 0.22), + transparent 60% + ), + radial-gradient( + 800px 400px at 0% 20%, + rgba(255, 125, 71, 0.09), + transparent 60% + ); + + --ifm-background-color: var(--tyko-bg); + --ifm-background-surface-color: var(--tyko-surface); + --ifm-color-content: var(--tyko-text); + --ifm-color-content-secondary: var(--tyko-text-muted); + --ifm-navbar-background-color: rgba(14, 12, 10, 0.7); + --ifm-footer-background-color: var(--tyko-footer-bg); + --ifm-code-background: rgba(255, 125, 71, 0.1); + --docusaurus-highlighted-code-line-bg: rgba(255, 125, 71, 0.15); + --tyko-ember-glow: rgba(255, 125, 71, 0.45); +} + + +/* ============================================================ + * Base + * ============================================================ */ +html { + font-feature-settings: "ss01", "cv11"; +} + +body { + background: var(--tyko-bg); + color: var(--tyko-text); + -webkit-font-smoothing: antialiased; + text-rendering: optimizeLegibility; +} + +h1, h2, h3, h4 { + letter-spacing: -0.02em; +} + +/* Selection */ +::selection { + background: var(--tyko-ember); + color: #fff; +} + +/* ============================================================ + * Navbar — sticky, translucent, hairline border + * ============================================================ */ +.navbar { + backdrop-filter: saturate(180%) blur(16px); + -webkit-backdrop-filter: saturate(180%) blur(16px); + border-bottom: 1px solid var(--tyko-border); + padding: 0 1.25rem; +} + +.navbar__brand { + font-family: var(--ifm-font-family-monospace); + font-weight: 700; + letter-spacing: -0.01em; +} + +.navbar__logo { + height: 32px; + margin-right: 12px; +} + +.navbar__title { + font-size: 0.98rem; +} + +.navbar__link { + font-weight: 500; + font-size: 0.92rem; + color: var(--tyko-text-muted); + transition: color 0.15s ease; +} +.navbar__link:hover, +.navbar__link--active { + color: var(--tyko-text); +} + +.navbar__link--active::after { + content: ""; + display: block; + height: 2px; + width: 100%; + background: var(--tyko-gradient-ember); + border-radius: 2px; + margin-top: 2px; +} + +/* GitHub icon link in navbar */ +.header-github-link:hover { + opacity: 0.75; +} +.header-github-link::before { + content: ""; + width: 22px; + height: 22px; + display: flex; + background: currentColor; + mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1.1-.7.1-.7.1-.7 1.2.1 1.9 1.3 1.9 1.3 1.1 1.9 2.8 1.3 3.6 1 .1-.8.4-1.3.8-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6.1-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0c2.3-1.5 3.3-1.2 3.3-1.2.7 1.6.2 2.8.1 3.2.9.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.3v3.3c0 .3.1.7.8.6A12 12 0 0 0 12 .3'/%3E%3C/svg%3E") no-repeat center / contain; + mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .3a12 12 0 0 0-3.8 23.4c.6.1.8-.3.8-.6v-2c-3.3.7-4-1.6-4-1.6-.6-1.4-1.4-1.8-1.4-1.8-1.1-.7.1-.7.1-.7 1.2.1 1.9 1.3 1.9 1.3 1.1 1.9 2.8 1.3 3.6 1 .1-.8.4-1.3.8-1.6-2.7-.3-5.5-1.3-5.5-6 0-1.2.5-2.3 1.3-3.1-.2-.4-.6-1.6.1-3.2 0 0 1-.3 3.4 1.2a11.5 11.5 0 0 1 6 0c2.3-1.5 3.3-1.2 3.3-1.2.7 1.6.2 2.8.1 3.2.9.8 1.3 1.9 1.3 3.1 0 4.6-2.8 5.6-5.5 5.9.5.4.9 1.1.9 2.3v3.3c0 .3.1.7.8.6A12 12 0 0 0 12 .3'/%3E%3C/svg%3E") no-repeat center / contain; +} + +/* Search bar */ +.DocSearch-Button { + border-radius: 10px !important; + background: var(--tyko-surface-muted) !important; + border: 1px solid var(--tyko-border) !important; + height: 38px; + padding: 0 12px !important; +} +.DocSearch-Button:hover { + border-color: var(--tyko-border-strong) !important; + box-shadow: none !important; +} +.DocSearch-Button-Keys { + min-width: auto !important; +} +.DocSearch-Button, +.DocSearch-Button * { + color: var(--tyko-text) !important; +} +.DocSearch-Button-Placeholder { + color: var(--tyko-text-muted) !important; +} +.DocSearch-Button-Key { + color: var(--tyko-text-subtle) !important; +} + +/* ============================================================ + * Buttons + * ============================================================ */ +.button { + font-weight: 600; + border-radius: 12px; + padding: 0.75rem 1.4rem; + transition: transform 0.15s ease, box-shadow 0.2s ease, background 0.2s ease, color 0.2s ease; + border: 1px solid transparent; + letter-spacing: -0.005em; +} + +.button--primary, +.button--primary:link, +.button--primary:visited { + background: var(--tyko-gradient-ember); + border: none; + color: #fff !important; + box-shadow: var(--tyko-shadow-glow); +} +.button--primary:hover, +.button--primary:focus, +.button--primary:active { + transform: translateY(-1px); + color: #fff !important; + filter: brightness(1.05); +} + +.button--secondary, +.button--secondary:link, +.button--secondary:visited { + background: var(--tyko-surface); + color: var(--tyko-text) !important; + border: 1px solid var(--tyko-border-strong); + box-shadow: var(--tyko-shadow-sm); +} +.button--secondary:hover, +.button--secondary:focus, +.button--secondary:active { + background: var(--tyko-surface-muted); + color: var(--tyko-text) !important; + border-color: var(--tyko-text-muted); +} + +[data-theme="dark"] .button--secondary, +[data-theme="dark"] .button--secondary:link, +[data-theme="dark"] .button--secondary:visited { + background: var(--tyko-surface); + color: var(--tyko-text) !important; + border-color: var(--tyko-border-strong); +} +[data-theme="dark"] .button--secondary:hover, +[data-theme="dark"] .button--secondary:focus, +[data-theme="dark"] .button--secondary:active { + background: var(--tyko-surface-muted); + color: var(--tyko-text) !important; + border-color: var(--tyko-text-muted); +} +[data-theme="dark"] .button--primary { + color: #fff !important; +} + +/* ============================================================ + * Homepage — Hero + * ============================================================ */ +.tyko-hero { + position: relative; + padding: clamp(4rem, 10vw, 7rem) 0 clamp(3rem, 6vw, 5rem); + background: var(--tyko-gradient-hero), var(--tyko-bg); + overflow: hidden; +} + +.tyko-hero::before { + content: ""; + position: absolute; + inset: 0; + background-image: linear-gradient(var(--tyko-border) 1px, transparent 1px), + linear-gradient(90deg, var(--tyko-border) 1px, transparent 1px); + background-size: 48px 48px; + mask-image: radial-gradient(ellipse at 50% 0%, black 30%, transparent 70%); + opacity: 0.35; + pointer-events: none; +} + +.tyko-hero__inner { + position: relative; + display: grid; + grid-template-columns: 1.15fr 1fr; + gap: 3rem; + align-items: center; + max-width: 1200px; + margin: 0 auto; + padding: 0 1.5rem; +} + +@media (max-width: 900px) { + .tyko-hero__inner { + grid-template-columns: 1fr; + text-align: center; + } +} + +.tyko-hero__eyebrow { + display: inline-flex; + align-items: center; + gap: 8px; + font-family: var(--ifm-font-family-monospace); + font-size: 0.78rem; + font-weight: 500; + text-transform: uppercase; + letter-spacing: 0.08em; + color: var(--tyko-text-muted); + padding: 6px 12px; + border: 1px solid var(--tyko-border); + border-radius: 999px; + background: var(--tyko-surface); + margin-bottom: 1.5rem; +} +.tyko-hero__eyebrow::before { + content: ""; + width: 6px; + height: 6px; + border-radius: 999px; + background: var(--tyko-ember); + box-shadow: 0 0 0 4px rgba(242, 109, 61, 0.18); +} + +.tyko-hero__title { + font-size: clamp(2.75rem, 6vw, 4.5rem); + line-height: 1.02; + font-weight: 800; + letter-spacing: -0.035em; + margin: 0 0 1.25rem; +} + +.tyko-hero__title-accent { + background: var(--tyko-gradient-ember); + -webkit-background-clip: text; + background-clip: text; + -webkit-text-fill-color: transparent; +} + +.tyko-hero__subtitle { + font-size: clamp(1.05rem, 1.4vw, 1.2rem); + color: var(--tyko-text-muted); + max-width: 560px; + margin: 0 0 2rem; + line-height: 1.55; +} +@media (max-width: 900px) { + .tyko-hero__subtitle { + margin-left: auto; + margin-right: auto; + } +} + +.tyko-hero__cta { + display: flex; + gap: 12px; + flex-wrap: wrap; +} +@media (max-width: 900px) { + .tyko-hero__cta { + justify-content: center; + } +} + +.tyko-hero__logo { + position: relative; + display: flex; + justify-content: center; + align-items: center; +} +.tyko-hero__logo img { + width: min(420px, 90%); + height: auto; + filter: drop-shadow(0 30px 60px rgba(242, 109, 61, 0.35)); + animation: tyko-float 6s ease-in-out infinite; +} + +@keyframes tyko-float { + 0%, 100% { transform: translateY(0); } + 50% { transform: translateY(-10px); } +} + +/* ============================================================ + * Homepage — Features grid + * ============================================================ */ +.tyko-section { + padding: clamp(3rem, 6vw, 5rem) 1.5rem; + max-width: 1200px; + margin: 0 auto; +} + +.tyko-section__header { + text-align: center; + max-width: 640px; + margin: 0 auto clamp(2rem, 4vw, 3.5rem); +} +.tyko-section__eyebrow { + font-family: var(--ifm-font-family-monospace); + font-size: 0.78rem; + text-transform: uppercase; + letter-spacing: 0.1em; + color: var(--tyko-ember); + font-weight: 600; + margin-bottom: 0.75rem; +} +.tyko-section__title { + font-size: clamp(1.75rem, 3vw, 2.4rem); + letter-spacing: -0.025em; + font-weight: 700; + margin: 0 0 0.75rem; +} +.tyko-section__desc { + color: var(--tyko-text-muted); + font-size: 1.05rem; +} + +.tyko-features { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 20px; +} +@media (max-width: 960px) { + .tyko-features { grid-template-columns: repeat(2, 1fr); } +} +@media (max-width: 640px) { + .tyko-features { grid-template-columns: 1fr; } +} + +.tyko-feature { + position: relative; + padding: 1.75rem; + background: var(--tyko-surface); + border: 1px solid var(--tyko-border); + border-radius: var(--tyko-radius); + transition: transform 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease; + overflow: hidden; +} +.tyko-feature::before { + content: ""; + position: absolute; + top: 0; left: 0; right: 0; + height: 1px; + background: linear-gradient( + 90deg, + transparent, + var(--tyko-ember) 50%, + transparent + ); + opacity: 0; + transition: opacity 0.25s ease; +} +.tyko-feature:hover { + transform: translateY(-3px); + border-color: var(--tyko-border-strong); + box-shadow: var(--tyko-shadow-md); +} +.tyko-feature:hover::before { opacity: 1; } + +.tyko-feature__icon { + display: inline-flex; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + border-radius: 12px; + background: rgba(242, 109, 61, 0.1); + color: var(--tyko-ember); + margin-bottom: 1.1rem; +} +.tyko-feature__icon svg { + width: 22px; + height: 22px; + stroke-width: 1.75; +} + +.tyko-feature__title { + font-size: 1.08rem; + font-weight: 600; + margin: 0 0 0.5rem; + letter-spacing: -0.01em; +} +.tyko-feature__desc { + color: var(--tyko-text-muted); + font-size: 0.94rem; + line-height: 1.6; + margin: 0; +} + +/* ============================================================ + * Homepage — "How it works" steps + * ============================================================ */ +.tyko-steps-wrap { + background: var(--tyko-surface-muted); + border-top: 1px solid var(--tyko-border); + border-bottom: 1px solid var(--tyko-border); +} + +.tyko-steps { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 24px; + position: relative; +} +@media (max-width: 800px) { + .tyko-steps { grid-template-columns: 1fr; } +} + +.tyko-step { + padding: 1.75rem; + background: var(--tyko-surface); + border: 1px solid var(--tyko-border); + border-radius: var(--tyko-radius); + position: relative; +} + +.tyko-step__num { + font-family: var(--ifm-font-family-monospace); + font-weight: 700; + font-size: 0.85rem; + color: var(--tyko-ember); + background: rgba(242, 109, 61, 0.1); + display: inline-flex; + padding: 4px 10px; + border-radius: 6px; + margin-bottom: 1rem; + letter-spacing: 0.05em; +} +.tyko-step__title { + font-size: 1.1rem; + font-weight: 600; + margin: 0 0 0.4rem; +} +.tyko-step__desc { + color: var(--tyko-text-muted); + font-size: 0.94rem; + margin: 0; +} + +/* ============================================================ + * Doc pages — refined typography & sidebar + * ============================================================ */ +.main-wrapper { + background: var(--tyko-bg); +} + +.theme-doc-sidebar-container { + border-right: 1px solid var(--tyko-border) !important; +} + +.menu { + padding: 1rem 0.75rem !important; + font-size: 0.9rem; +} + +.menu__link { + border-radius: 8px; + color: var(--tyko-text-muted); + font-weight: 500; + padding: 0.4rem 0.75rem; + transition: background 0.15s ease, color 0.15s ease; +} +.menu__link:hover { + background: var(--tyko-surface-muted); + color: var(--tyko-text); +} +.menu__link--active { + background: rgba(242, 109, 61, 0.1); + color: var(--tyko-ember) !important; + font-weight: 600; +} +.menu__link--active:not(.menu__link--sublist) { + background: rgba(242, 109, 61, 0.12); +} + +.menu__list-item-collapsible:hover { + background: transparent; +} + +/* Article */ +article header h1 { + font-size: 2.5rem; + letter-spacing: -0.03em; +} + +.theme-doc-markdown h2 { + padding-top: 0.5rem; + margin-top: 2.5rem; + border-top: 1px solid var(--tyko-border); + padding-top: 2rem; +} + +/* Inline code */ +code { + background: var(--ifm-code-background); + border: 1px solid rgba(242, 109, 61, 0.15); + color: var(--tyko-ember-deep); + padding: 0.15rem 0.4rem; + border-radius: 6px; + font-size: 0.88em; + font-weight: 500; +} +[data-theme="dark"] code { + color: var(--tyko-ember-bright); + border-color: rgba(255, 125, 71, 0.2); +} +a code { color: inherit; } + +/* Code blocks */ +.theme-code-block { + border-radius: var(--tyko-radius) !important; + box-shadow: var(--tyko-shadow-sm) !important; + border: 1px solid var(--tyko-border); +} +.prism-code { + font-size: 0.88rem !important; + line-height: 1.6 !important; +} + +/* Admonitions */ +.admonition, +.alert { + border-radius: var(--tyko-radius) !important; + border: 1px solid var(--tyko-border) !important; + border-left: 3px solid var(--ifm-color-primary) !important; + background: var(--tyko-surface) !important; + box-shadow: var(--tyko-shadow-sm); +} + +/* Tables */ +table { + border-radius: var(--tyko-radius); + overflow: hidden; + border: 1px solid var(--tyko-border); + border-collapse: separate; + border-spacing: 0; +} +table thead { + background: var(--tyko-surface-muted); +} +table th, table td { + border: none; + border-bottom: 1px solid var(--tyko-border); +} + +/* Pagination nav */ +.pagination-nav__link { + border: 1px solid var(--tyko-border); + border-radius: var(--tyko-radius); + background: var(--tyko-surface); + transition: border-color 0.15s ease, transform 0.15s ease; +} +.pagination-nav__link:hover { + border-color: var(--ifm-color-primary); + transform: translateY(-1px); +} + +/* TOC */ +.table-of-contents__link { + color: var(--tyko-text-muted); + transition: color 0.15s ease; +} +.table-of-contents__link:hover, +.table-of-contents__link--active { + color: var(--tyko-ember) !important; + font-weight: 500; +} + +/* ============================================================ + * Footer + * ============================================================ */ +.footer { + padding: 4rem 1.5rem 2.5rem; + background: var(--tyko-footer-bg); + color: var(--tyko-footer-text); + border-top: 1px solid var(--tyko-footer-border); +} +.footer__title { + font-size: 0.8rem; + text-transform: uppercase; + letter-spacing: 0.1em; + opacity: 0.7; +} +.footer__link-item { + color: var(--tyko-footer-link); + transition: color 0.15s ease; +} +.footer__link-item:hover { + color: var(--tyko-footer-link-hover); + text-decoration: none; +} +.footer__copyright { + font-family: var(--ifm-font-family-monospace); + font-size: 0.8rem; + opacity: 0.55; + margin-top: 2rem; +} + + +/* ─────────────────────────────────────────────── + Homepage footer + ─────────────────────────────────────────────── */ +.tyko-home-footer { + padding: 2.5rem 0; + background: var(--tyko-footer-bg); + color: var(--tyko-footer-text); + text-align: center; + border-top: 1px solid var(--tyko-footer-border); +} + +.tyko-home-footer__copyright { + margin: 0 0 0.75rem; + font-size: 0.9rem; + color: var(--tyko-footer-text); +} + +.tyko-home-footer__links { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 0.5rem; + margin: 0; + font-size: 0.9rem; + font-weight: 500; +} + +.tyko-home-footer a { + color: var(--tyko-footer-link); + transition: color 0.2s ease; +} + +.tyko-home-footer a:hover { + color: var(--tyko-footer-link-hover); + text-decoration: none; +} + +.tyko-home-footer__divider { + color: var(--tyko-text-subtle); +} + + +/* ─────────────────────────────────────────────── + Bottom CTA + ─────────────────────────────────────────────── */ +.tyko-cta { + padding: 3.5rem 2rem; + border-radius: 1.25rem; + text-align: center; + background: var(--tyko-gradient-ember); + color: #fff; + box-shadow: 0 16px 40px var(--tyko-ember-glow); +} + +.tyko-cta__title { + font-size: clamp(1.5rem, 3.5vw, 2.25rem); + font-weight: 800; + letter-spacing: -0.02em; + margin-bottom: 0.75rem; + color: #fff; +} + +.tyko-cta__desc { + font-size: clamp(1rem, 2vw, 1.2rem); + margin: 0 auto 1.75rem; + max-width: 32rem; + opacity: 0.95; +} + +.tyko-cta__actions { + display: flex; + gap: 1rem; + justify-content: center; + flex-wrap: wrap; +} + +.tyko-cta .button--primary, +.tyko-cta .button--primary:link, +.tyko-cta .button--primary:visited { + background: #fff; + color: var(--tyko-ember-deep) !important; + box-shadow: 0 4px 14px rgba(0, 0, 0, 0.15); +} + +.tyko-cta .button--primary:hover, +.tyko-cta .button--primary:focus, +.tyko-cta .button--primary:active { + color: var(--tyko-ember-deep) !important; + box-shadow: 0 8px 22px rgba(0, 0, 0, 0.2); +} + +.tyko-cta .button--secondary { + background: rgba(255, 255, 255, 0.12); + border-color: rgba(255, 255, 255, 0.3); + color: #fff; +} + +.tyko-cta .button--secondary:hover { + background: rgba(255, 255, 255, 0.2); + border-color: #fff; + color: #fff; +} + +.tyko-cta .button--secondary:hover { + background: rgba(255, 255, 255, 0.2); + border-color: #fff; + color: #fff; +} + +.tyko-cta .button--tertiary { + background: rgba(255, 255, 255, 0.12); + border-color: rgba(255, 255, 255, 0.3); + color: white; +} + +.tyko-cta .button--tertiary:hover { + background: rgba(255, 255, 255, 0.2); + border-color: #fff; + color: white; +} \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index a638a9d..b720ca9 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,211 +1,262 @@ -import React from "react"; -import Layout from "@theme/Layout"; -import Link from "@docusaurus/Link"; +import React from 'react'; +import Link from '@docusaurus/Link'; +import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import useBaseUrl from '@docusaurus/useBaseUrl'; -import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; -import { BarChart3, Lock, HeartPulse, Rocket, CircleFadingArrowUp, Ship, Cable, HandPlatter, Archive } from "lucide-react"; +import Layout from '@theme/Layout'; +import Heading from "@theme/Heading"; -export default function Home(): JSX.Element { - const { siteConfig } = useDocusaurusContext(); - - return ( - - {/* HERO */} -
-
-
-
-

- TyKO -

-

- Your turnkey Typesense Kubernetes Operator
- for highly available self-healing Typesense clusters -

-
- - Get Started -{">"} - - - GitHub - -
-
- -
- TyKO Hero { (e.currentTarget as HTMLImageElement).style.display = 'none'; }} - /> -
-
-
-
- - {/* FEATURES */} -
-
- {features.map((f) => ( -
-
-
-
{f.icon}
-

{f.title}

-

{f.desc}

-
-
-
- ))} -
-
- - {/* HOW IT WORKS */} -
-
-
-
-

How it works

-

Three simple steps to set up a highly available Typesense cluster

-
-
-
- {steps.map((s, i) => ( -
-
-
-
-
- {i + 1} -
-

{s.title}

-
-

{s.desc}

- - Learn more -{">"} - -
-
-
- ))} -
-
-
- - {/* FOOTER-LIKE LAST SECTION (Lucide-style, fixed colors) */} -
- -
-
-
- - © 2024-{new Date().getFullYear()} {siteConfig.title}, GPL-3.0 Licensed - -
-
-
-
-
- -
- ); -} - -const features = [ +const FEATURES = [ { - title: "Self-healing clusters", - desc: "Automated failover, quorum recovery, and raft re-evaluation keep your Typesense clusters healthy without any manual intervention.", - icon: , + title: 'Self-healing clusters', + desc: 'Automated failover, quorum recovery, and raft re-evaluation keep your Typesense clusters healthy without any manual intervention.', + icon: ( + + + + ), }, { - title: "Zero-downtime updates", - desc: "Rolling updates with safe orchestration ensure you are always stay operational while you upgrade, downgrade or resize your Typesense clusters.", - icon: , + title: 'Zero-downtime updates', + desc: 'Rolling updates with safe orchestration ensure you stay operational while you upgrade, downgrade, or resize your Typesense clusters.', + icon: ( + + + + ), }, { - title: "Batteries-included", - desc: "StatefulSets, ConfigMaps, Secrets, Services, PodMetrics, HttpRoutes and many more, all managed for you.", - icon: , + title: 'Batteries-included', + desc: 'StatefulSets, ConfigMaps, Secrets, Services, PodMetrics, HttpRoutes and many more, all managed for you.', + icon: ( + + + + + ), }, { - title: "Ingress & Gateway APIs support", - desc: "Expose Typesense securely using Kubernetes Ingress or the Gateway API. Integrates with Shared Gateways & TLS termination.", - icon: , + title: 'Ingress & Gateway APIs', + desc: 'Expose Typesense securely using Kubernetes Ingress or the Gateway API. Integrates with Shared Gateways & TLS termination.', + icon: ( + + + + + + + ), }, { - title: "Observability", - desc: "Expose Typesense nodes health status and metrics to Prometheus for monitoring and alerting purposes.", - icon: , + title: 'Observability', + desc: 'Expose Typesense node health status and metrics to Prometheus for monitoring and alerting purposes.', + icon: ( + + + + + ), }, { - title: "Production-ready", - desc: "Opinionated defaults for secure production-ready clusters and sane resource limits.", - icon: , + title: 'Production-ready', + desc: 'Opinionated defaults for secure production-ready clusters and sane resource limits.', + icon: ( + + + + + ), }, { - title: "S3-compatible storage support", - desc: "Persist data on any S3-compatible object storage. Works with OBS, AWS S3, RustFS and many more for vendor-neutral storage.", - icon: , + title: 'S3-compatible storage', + desc: 'Persist data on any S3-compatible object storage. Works with OBS, AWS S3, RustFS and many more for vendor-neutral storage.', + icon: ( + + + + + + ), }, { - title: "Kubernetes-native", - desc: "Built with Go & Operator SDK, following Kubernetes best-practices. Extend TyKO to your needs if you wish.", - icon: , + title: 'Kubernetes-native', + desc: 'Built with Go & Operator SDK, following Kubernetes best practices. Extend TyKO to your needs if you wish.', + icon: ( + + + + + ), }, -] as const; +]; -const steps = [ +const STEPS = [ { - title: "Install the Operator", - desc: "Add the Helm repo and install to your cluster.", - href: "/docs/installation#deploy-using-helm", + n: '01', + title: 'Install the Operator', + desc: 'Deploy TyKO with a single Helm command into your Kubernetes cluster.', }, { - title: "Define your Cluster", - desc: "Apply a single manifest with the version, size and storage you need.", - href: "/docs/crds/crds-examples", + n: '02', + title: 'Declare a cluster', + desc: 'Create a TypesenseCluster custom resource describing size, storage, and exposure.', }, { - title: "Let TyKO do the rest", - desc: "TyKO provisions, configures, monitors and heals the cluster automatically.", - href: "/docs/how-it-works/", + n: '03', + title: 'Let TyKO run it', + desc: 'Sit back while TyKO handles quorum, failover, upgrades, and scaling automatically.', }, -] as const; +]; + +function Hero() { + const logo = useBaseUrl('/img/tyko-logo.png'); + return ( +
+
+
+ {/* Typesense Kubernetes Operator */} +

+ Turnkey Typesense.
+ Self-healing on Kubernetes. +

+

+ TyKO runs highly-available Typesense clusters for you — quorum recovery, + rolling upgrades, and zero-downtime operations, all Kubernetes-native. +

+
+ + Get Started → + + + View on GitHub + +
+
+
+ TyKO — Typesense Kubernetes Operator +
+
+
+ ); +} + +function Features() { + return ( +
+
+
Why TyKO
+

Everything you need to run Typesense on Kubernetes

+

+ Built with the Operator SDK.
+ Opinionated where it matters, flexible where it counts. +

+
+
+ {FEATURES.map((f) => ( +
+
{f.icon}
+

{f.title}

+

{f.desc}

+
+ ))} +
+
+ ); +} + +function HowItWorks() { + return ( +
+
+
+
How it works
+

From zero to HA in three steps

+

+ A highly-available Typesense cluster on Kubernetes, without the yak-shaving. +

+
+
+ {STEPS.map((s) => ( +
+
STEP {s.n}
+

{s.title}

+

{s.desc}

+
+ ))} +
+
+
+ ); +} + +function HomepageFooter(): JSX.Element { + return ( +
+
+

+ © {new Date().getFullYear()} TyKO. Released under the GNU General Public Version 3.0 + License. +

+

+ GitHub + + + Issues + +

+
+
+ ); +} + +function HomepageCta(): JSX.Element { + return ( +
+
+
+ + Ready to run Typesense on Kubernetes? + +

+ Deploy your first cluster in minutes. +

+
+ + Read the docs + + + Star on GitHub + +
+
+
+
+ ); +} + +export default function Home() { + const { siteConfig } = useDocusaurusContext(); + return ( + + +
+ + + +
+ + +
+ ); +} \ No newline at end of file From 11a9dbadaff15ed588a3a7b9e46ade8e03bd72fb Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 06:23:34 +0000 Subject: [PATCH 2/6] fix github navbar link, removed mono from faq #63 --- docs/faq.md | 4 ---- src/css/custom.css | 31 ++++++++++++++++++++++++++++++- src/pages/index.tsx | 4 ++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 2a87439..caeff7e 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -43,10 +43,6 @@ No. TyKO, after version 0.3.0, is a very stable release suitable for production Kindly review the [Disclaimer](/docs/getting-started#disclaimer) carefully once more. (aaaargh!!!) -### What font sorcery is this? - -It's [JetBrains Mono](https://www.jetbrains.com/lp/mono/), the opensource typeface by JetBrains. - ### Can we meet Tyko, the mascot? Nope-that can't do, he's a very busy fella! diff --git a/src/css/custom.css b/src/css/custom.css index f0d0b45..1c22dd6 100644 --- a/src/css/custom.css +++ b/src/css/custom.css @@ -901,4 +901,33 @@ table th, table td { background: rgba(255, 255, 255, 0.2); border-color: #fff; color: white; -} \ No newline at end of file +} + +/* Github */ + + .navbar--github-link { + width: 36px; + height: 36px; + padding: 6px; + margin-right: 12px; + margin-left: 6px; + border-radius: 50%; + transition: background var(--ifm-transition-fast); + } + + .navbar--github-link:hover { + background: var(--ifm-color-emphasis-200); + } + + .navbar--github-link:before { + content: ''; + height: 100%; + display: block; + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 25 25' width='25' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; + } + + html[data-theme='dark'] .navbar--github-link:before { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 25 25' width='25' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='white' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") + no-repeat; + } \ No newline at end of file diff --git a/src/pages/index.tsx b/src/pages/index.tsx index b720ca9..6f2046d 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -116,10 +116,10 @@ function Hero() { {/* Typesense Kubernetes Operator */}

Turnkey Typesense.
- Self-healing on Kubernetes. + Highly available on Kubernetes.

- TyKO runs highly-available Typesense clusters for you — quorum recovery, + TyKO runs highly-available Typesense clusters for you with quorum recovery, rolling upgrades, and zero-downtime operations, all Kubernetes-native.

From affe0da6d165534366414ea304538ef4ad4faeac Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 06:48:37 +0000 Subject: [PATCH 3/6] added adopters button #63 --- src/pages/index.tsx | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 6f2046d..5b838b1 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -236,7 +236,14 @@ function HomepageCta(): JSX.Element { > Star on GitHub + + Already running TyKO? Join the Adopters +
+ From 6add3d3537dea7017e50adfb4c65c937b9c3365f Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 07:03:33 +0000 Subject: [PATCH 4/6] replaced x with emojis #63 --- docs/crds/index.mdx | 168 ++++++++++++++++++++++---------------------- docs/healthcheck.md | 18 ++--- docs/metrics.md | 16 ++--- 3 files changed, 101 insertions(+), 101 deletions(-) diff --git a/docs/crds/index.mdx b/docs/crds/index.mdx index 9243a16..6266576 100644 --- a/docs/crds/index.mdx +++ b/docs/crds/index.mdx @@ -19,38 +19,38 @@ Typesense Kubernetes Operator is controlling the lifecycle of multiple Typesense ### TypesenseClusterSpec | Name | Description | Optional | Default | -| -------------------------------------- | ------------------------------------------------------------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| -------------------------------------- | ------------------------------------------------------------------------------ | :------: | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | image | Typesense image | | | -| imagePullSecrets | reference to the private registry authentication `Secret` | X | | -| adminApiKey | reference to the bootstrap `Secret` | X | | -| replicas | size of the cluster (allowed 1, 3, 5 or 7) | X | 3 | -| apiPort | REST/API port | X | 8108 | -| peeringPort | peering port | X | 8107 | -| resetPeersOnError | automatic reset of peers on error | X | true | -| enableCors | enables CORS | X | false | -| corsDomains | comma separated list of domains allowed for CORS | X | | -| resources | resources (request & limit) | X | 1000m/100m
512Mi/256Mi | -| healthProbeTimeoutInMilliseconds | timeout for waiting on the health endpoint response | X | 500 | -| affinity | group of affinity scheduling rules | X | | -| nodeSelector | node selection constraint | X | | -| tolerations | schedule pods with matching taints | X | | -| additionalServerConfiguration | a reference to a `ConfigMap` holding extra configuration | X | | -| statefulSetAnnotations | user-defined annotations | X | | -| podAnnotations | user-defined annotations | X | | -| podsInheritStatefulSetAnnotations | propagate all `StatefulSet` annotations to `Pods` | X | false | -| serviceAnnotations (deprecated) | user-defined annotations | X | | +| imagePullSecrets | reference to the private registry authentication `Secret` | 🟢 | | +| adminApiKey | reference to the bootstrap `Secret` | 🟢 | | +| replicas | size of the cluster (allowed 1, 3, 5 or 7) | 🟢 | 3 | +| apiPort | REST/API port | 🟢 | 8108 | +| peeringPort | peering port | 🟢 | 8107 | +| resetPeersOnError | automatic reset of peers on error | 🟢 | true | +| enableCors | enables CORS | 🟢 | false | +| corsDomains | comma separated list of domains allowed for CORS | 🟢 | | +| resources | resources (request & limit) | 🟢 | 1000m/100m
512Mi/256Mi | +| healthProbeTimeoutInMilliseconds | timeout for waiting on the health endpoint response | 🟢 | 500 | +| affinity | group of affinity scheduling rules | 🟢 | | +| nodeSelector | node selection constraint | 🟢 | | +| tolerations | schedule pods with matching taints | 🟢 | | +| additionalServerConfiguration | a reference to a `ConfigMap` holding extra configuration | 🟢 | | +| statefulSetAnnotations | user-defined annotations | 🟢 | | +| podAnnotations | user-defined annotations | 🟢 | | +| podsInheritStatefulSetAnnotations | propagate all `StatefulSet` annotations to `Pods` | 🟢 | false | +| serviceAnnotations (deprecated) | user-defined annotations | 🟢 | | | service | check `ServiceSpec` [below](#servicespec-optional) | | | | storage | check `StorageSpec` [below](#storagespec-optional) | | | -| ingress | check `IngressSpec` [below](#ingressspec-deprecated) | X | | -| httpRoutes | array of `HttpRouteSpec`; check [below](#httproutespec-optional) | X | | -| scrapers | array of `DocSearchScraperSpec`; check [below](#docsearchscraperspec-optional) | X | | -| metrics | check `MetricsSpec` [below](#metricsspec-optional) | X | | -| healthcheck | check `HealthCheckSpec` [below](#healthcheckspec-optional) | X | | -| topologySpreadConstraints | how to spread a group of pods across topology domains | X | | -| priorityClassName | reference to a pod priority and preemption class | X | | -| securityContext | check `SecurityContextSpec` [below](#metricsspec-optional) | X | | -| ignoreAnnotationsFromExternalMutations | annotations to ignore when calculating hash (e.g. cattle.io/) | X | | -| incrementalQuorumRecovery | add nodes gradually to the `StatefulSet` while recovering | X | false | +| ingress | check `IngressSpec` [below](#ingressspec-deprecated) | 🟢 | | +| httpRoutes | array of `HttpRouteSpec`; check [below](#httproutespec-optional) | 🟢 | | +| scrapers | array of `DocSearchScraperSpec`; check [below](#docsearchscraperspec-optional) | 🟢 | | +| metrics | check `MetricsSpec` [below](#metricsspec-optional) | 🟢 | | +| healthcheck | check `HealthCheckSpec` [below](#healthcheckspec-optional) | 🟢 | | +| topologySpreadConstraints | how to spread a group of pods across topology domains | 🟢 | | +| priorityClassName | reference to a pod priority and preemption class | 🟢 | | +| securityContext | check `SecurityContextSpec` [below](#metricsspec-optional) | 🟢 | | +| ignoreAnnotationsFromExternalMutations | annotations to ignore when calculating hash (e.g. cattle.io/) | 🟢 | | +| incrementalQuorumRecovery | add nodes gradually to the `StatefulSet` while recovering | 🟢 | false | :::note @@ -63,10 +63,10 @@ Typesense Kubernetes Operator is controlling the lifecycle of multiple Typesense ### ServiceSpec (optional) | Name | Description | Optional | Default | -| --------------------- | ------------------------ | -------- | ----------- | -| type | type of `Service` | X | `ClusterIP` | -| externalTrafficPolicy | external traffic policy | X | `Cluster` | -| annotations | user-defined annotations | X | | +| --------------------- | ------------------------ | :------: | ----------- | +| type | type of `Service` | 🟢 | `ClusterIP` | +| externalTrafficPolicy | external traffic policy | 🟢 | `Cluster` | +| annotations | user-defined annotations | 🟢 | | :::important As of **v0.4.1-rc.4**, `ServiceSpec` has been introduced: @@ -87,11 +87,11 @@ which may obscure the client's source IP, or `Local`, which preserves the client ### StorageSpec (optional) | Name | Description | Optional | Default | -| ---------------- | ------------------------------- | -------- | --------------- | -| size | size of the underlying `PV` | X | 100Mi | +| ---------------- | ------------------------------- | :------: | --------------- | +| size | size of the underlying `PV` | 🟢 | 100Mi | | storageClassName | `StorageClass` to be used | | standard | | accessMode | access mode for underlying `PV` | | `ReadWriteOnce` | -| annotations | user-defined annotations | X | | +| annotations | user-defined annotations | 🟢 | | :::important As of **v0.3.6**, storage `accessMode` is introduced that supports `ReadWriteOnce` and `ReadWriteMany`. @@ -139,31 +139,31 @@ _-The Ingress API is no longer being developed, and will have no further changes ::: | Name | Description | Optional | Default | -| ---------------------- | -------------------------------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| image | nginx image to use | X | [nginx:alpine](https://hub.docker.com/layers/library/nginx/alpine/images/sha256-e7e5b7fa7a0b1ab2f59d6066092a6d35984864cc8baf2cff7c088ee409657e57) | -| referer | FQDN allowed to access reverse proxy | X | empty or the value of `spec.corsDomains` if set | -| HttpDirectives | nginx proxy HttpDirectives | X | | -| serverDirectives | nginx proxy ServerDirectives | X | | -| locationDirectives | nginx proxy LocationDirectives | X | | +| ---------------------- | -------------------------------------------------------------------------------- | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| image | nginx image to use | 🟢 | [nginx:alpine](https://hub.docker.com/layers/library/nginx/alpine/images/sha256-e7e5b7fa7a0b1ab2f59d6066092a6d35984864cc8baf2cff7c088ee409657e57) | +| referer | FQDN allowed to access reverse proxy | 🟢 | empty or the value of `spec.corsDomains` if set | +| HttpDirectives | nginx proxy HttpDirectives | 🟢 | | +| serverDirectives | nginx proxy ServerDirectives | 🟢 | | +| locationDirectives | nginx proxy LocationDirectives | 🟢 | | | host | `Ingress` host | | | -| path | HTTP `Ingress` path | X | / | -| pathType | interpretation of the path matching | X | `ImplementationSpecific` | -| clusterIssuer | cert-manager `ClusterIssuer` | X | | -| tlsSecretName | TLS `Secret` name to use | X | | +| path | HTTP `Ingress` path | 🟢 | / | +| pathType | interpretation of the path matching | 🟢 | `ImplementationSpecific` | +| clusterIssuer | cert-manager `ClusterIssuer` | 🟢 | | +| tlsSecretName | TLS `Secret` name to use | 🟢 | | | ingressClassName | `Ingress` to be used | | | -| serviceAnnotations | user-defined annotations | X | | -| labels | user-defined labels | X | | -| annotations | user-defined annotations | X | | -| resources | resources (request & limit) | X | 150m/100m
64Mi/32Mi | -| readOnlyRootFilesystem | check `ReadOnlyRootFilesystemSpec` [below](#readonlyrootfilesystemspec-optional) | X | | +| serviceAnnotations | user-defined annotations | 🟢 | | +| labels | user-defined labels | 🟢 | | +| annotations | user-defined annotations | 🟢 | | +| resources | resources (request & limit) | 🟢 | 150m/100m
64Mi/32Mi | +| readOnlyRootFilesystem | check `ReadOnlyRootFilesystemSpec` [below](#readonlyrootfilesystemspec-optional) | 🟢 | | #### ReadOnlyRootFilesystemSpec (optional) | Name | Description | Optional | Default | -| --------------- | ---------------------------------- | -------- | ----------------------------------------------- | -| securityContext | security conf for the container | X | `SecurityContext{ReadOnlyRootFilesystem: true}` | -| volumes | additional volumes | X | | -| volumeMounts | additional mounts in the container | X | | +| --------------- | ---------------------------------- | :------: | ----------------------------------------------- | +| securityContext | security conf for the container | 🟢 | `SecurityContext{ReadOnlyRootFilesystem: true}` | +| volumes | additional volumes | 🟢 | | +| volumeMounts | additional mounts in the container | 🟢 | | :::note 1️⃣ This feature makes use of the existence of [cert-manager](https://cert-manager.io/) in the cluster, but **does not** actively enforce it with an error. If no clusterIssuer is specified a valid certificate must be stored in a secret and the secret name must be provided in the tlsSecretName config. @@ -180,16 +180,16 @@ It is highly recommended, from this operator's perspective, to always expose Typ ### HttpRouteSpec (optional) | Name | Description | Optional | Default | -| -------------- | -------------------------------------------------------------------------------------- | -------- | ------------------------ | +| -------------- | -------------------------------------------------------------------------------------- | :------: | ------------------------ | | name | name of the route | | | -| enabled | enable this route | X | true | +| enabled | enable this route | 🟢 | true | | parentRef | reference to the parent `Gateway`; check `GatewayParentRef` [below](#gatewayparentref) | | | | hostnames | array of hostnames to match for this route | | | -| path | path to match for this route | X | / | -| pathType | interpretation of the path matching | X | `ImplementationSpecific` | -| labels | user-defined labels | X | | -| annotations | user-defined annotations | X | | -| referenceGrant | enable cross-namespace reference to the parent `Gateway` | X | false | +| path | path to match for this route | 🟢 | / | +| pathType | interpretation of the path matching | 🟢 | `ImplementationSpecific` | +| labels | user-defined labels | 🟢 | | +| annotations | user-defined annotations | 🟢 | | +| referenceGrant | enable cross-namespace reference to the parent `Gateway` | 🟢 | false | :::warning @@ -212,22 +212,22 @@ will not be automatically deleted. It can be safely deleted manually, if not nee #### GatewayParentRef | Name | Description | Optional | Default | -| ----------- | -------------------------------------------------------------- | -------- | ------- | +| ----------- | -------------------------------------------------------------- | :------: | ------- | | name | name of the parent `Gateway` | | | | namespace | namespace of the parent `Gateway` | | | -| sectionName | section of the parent `Gateway` to route to (e.g. "websecure") | X | | +| sectionName | section of the parent `Gateway` to route to (e.g. "websecure") | 🟢 | | ### DocSearchScraperSpec (optional) | Name | Description | Optional | Default | -| ----------------- | ---------------------------------------------------- | -------- | ----------------------------------------- | +| ----------------- | ---------------------------------------------------- | :------: | ----------------------------------------- | | name | name of the scraper | | | -| image | container image to use | X | `typesense/docsearch-scraper:0.12.0.rc14` | -| host | target | X | | -| protocol | protocol to use (`http` or `https`) | X | `https` | -| config | config to use (bypass the autogenerated one ) | X | | +| image | container image to use | 🟢 | `typesense/docsearch-scraper:0.12.0.rc14` | +| host | target | 🟢 | | +| protocol | protocol to use (`http` or `https`) | 🟢 | `https` | +| config | config to use (bypass the autogenerated one ) | 🟢 | | | schedule | cron expression; no timezone; no seconds | | | -| authConfiguration | a reference to a `Secret` holding auth configuration | X | | +| authConfiguration | a reference to a `Secret` holding auth configuration | 🟢 | | :::note If you need to scrape a target that requires authentication, you can add the authentication configuration as environment variables via `authConfiguration`. In order to see which options are supported currently out of the box, consult the official documentation: https://typesense.org/docs/guide/docsearch.html#authentication @@ -250,12 +250,12 @@ You can follow the related thread in the Typesense Slack channel [here](https:// ### MetricsSpec (optional) | Name | Description | Optional | Default | -| --------- | ---------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| image | container image to use | X | [quay.io/akyriako/typesense-prometheus-exporter:0.1.9](https://github.com/akyriako/typesense-prometheus-exporter) | +| --------- | ---------------------------------------------------------- | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| image | container image to use | 🟢 | [quay.io/akyriako/typesense-prometheus-exporter:0.1.9](https://github.com/akyriako/typesense-prometheus-exporter) | | release | Prometheus release to become a target of | | | -| interval | interval in _seconds_ between two scrapes | X | 15 | -| resources | resources (request & limit) | X | 100m/100m
64Mi/32Mi | -| logLevel | defines the log [Level](https://pkg.go.dev/log/slog#Level) | X | 0 | +| interval | interval in _seconds_ between two scrapes | 🟢 | 15 | +| resources | resources (request & limit) | 🟢 | 100m/100m
64Mi/32Mi | +| logLevel | defines the log [Level](https://pkg.go.dev/log/slog#Level) | 🟢 | 0 | :::info `logLevel` follows the `slog/Level` type and only accepts one the following values `[-4, 0, 4, 8]`. For more details, see https://pkg.go.dev/log/slog#Level @@ -289,10 +289,10 @@ release=promstack ### HealthCheckSpec (optional) | Name | Description | Optional | Default | -| --------- | ---------------------------------------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| image | container image to use | X | [quay.io/akyriako/typesense-healthcheck:0.1.8](https://github.com/akyriako/typesense-healthcheck) | -| resources | resources (request & limit) | X | 100m/100m
64Mi/32Mi | -| logLevel | defines the log [Level](https://pkg.go.dev/log/slog#Level) | X | 0 | +| --------- | ---------------------------------------------------------- | :------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| image | container image to use | 🟢 | [quay.io/akyriako/typesense-healthcheck:0.1.8](https://github.com/akyriako/typesense-healthcheck) | +| resources | resources (request & limit) | 🟢 | 100m/100m
64Mi/32Mi | +| logLevel | defines the log [Level](https://pkg.go.dev/log/slog#Level) | 🟢 | 0 | :::info `logLevel` follows the `slog/Level` type and only accepts one the following values `[-4, 0, 4, 8]`. For more details, see https://pkg.go.dev/log/slog#Level @@ -301,11 +301,11 @@ release=promstack ### SecurityContextSpec (optional) | Name | Description | Optional | Default | -| ----------- | --------------------------- | -------- | ------------- | -| pod | pod security contenxt | X | _check specs_ | -| typesense | container security contenxt | X | | -| healthcheck | container security contenxt | X | | -| metric | container security contenxt | X | | +| ----------- | --------------------------- | :------: | ------------- | +| pod | pod security contenxt | 🟢 | _check specs_ | +| typesense | container security contenxt | 🟢 | | +| healthcheck | container security contenxt | 🟢 | | +| metric | container security contenxt | 🟢 | | ## TypesenseClusterStatus diff --git a/docs/healthcheck.md b/docs/healthcheck.md index 8d271a0..c6cab92 100644 --- a/docs/healthcheck.md +++ b/docs/healthcheck.md @@ -117,15 +117,15 @@ The library ships with an interactive, single-page monitoring UI built on Vue.js ## Configuration | Variable | Type | Default | Required | Description | -| ---------------------- | ------ | ---------------------------- | -------- | ---------------------------------------------------- | -| LOG_LEVEL | int | `0` | No | Log level | -| CLUSTER_NAMESPACE | string | `default` | No | K8s namespace where your Typesense StatefulSet lives | -| TYPESENSE_API_KEY | string | — | Yes | API key for accessing each Typesense node | -| TYPESENSE_PROTOCOL | string | `http` | No | Protocol for Typesense API (`http` or `https`) | -| TYPESENSE_API_PORT | uint | `8108` | No | Port for Typesense REST/API Port | -| TYPESENSE_PEERING_PORT | uint | `8107` | No | Port for Typesense Raft Peering Port | -| HEALTHCHECK_PORT | uint | `8808` | No | Port on which this healthcheck sidecar listens | -| TYPESENSE_NODES | string | `/usr/share/typesense/nodes` | No | Path for Typesense Raft nodes list | +| ---------------------- | ------ | ---------------------------- | :------: | ---------------------------------------------------- | +| LOG_LEVEL | int | `0` | | Log level | +| CLUSTER_NAMESPACE | string | `default` | | K8s namespace where your Typesense StatefulSet lives | +| TYPESENSE_API_KEY | string | — | 🔴 | API key for accessing each Typesense node | +| TYPESENSE_PROTOCOL | string | `http` | | Protocol for Typesense API (`http` or `https`) | +| TYPESENSE_API_PORT | uint | `8108` | | Port for Typesense REST/API Port | +| TYPESENSE_PEERING_PORT | uint | `8107` | | Port for Typesense Raft Peering Port | +| HEALTHCHECK_PORT | uint | `8808` | | Port on which this healthcheck sidecar listens | +| TYPESENSE_NODES | string | `/usr/share/typesense/nodes` | | Path for Typesense Raft nodes list | :::note All these values are automatically configured by the operator. diff --git a/docs/metrics.md b/docs/metrics.md index 4132584..15e5152 100644 --- a/docs/metrics.md +++ b/docs/metrics.md @@ -62,14 +62,14 @@ The exporter gathers various metrics from the Typesense /metrics.json endpoint, ## Configuration | Variable | Type | Default | Required | Description | -| ------------------ | ------ | ------- | -------- | ---------------------------------------------- | -| LOG_LEVEL | int | `0` | No | Log level | -| TYPESENSE_API_KEY | string | — | Yes | API key for accessing each Typesense node | -| TYPESENSE_HOST | string | — | Yes | Hostname or FQDN of the Typesense node | -| TYPESENSE_PORT | uint | `8108` | No | Port for Typesense REST/API Port | -| TYPESENSE_PROTOCOL | string | `http` | No | Protocol for Typesense API (`http` or `https`) | -| TYPESENSE_CLUSTER | string | — | Yes | Cluster identifier label for metrics | -| METRICS_PORT | uint | `8908` | No | Port on which `/metrics` is served | +| ------------------ | ------ | ------- | :------: | ---------------------------------------------- | +| LOG_LEVEL | int | `0` | | Log level | +| TYPESENSE_API_KEY | string | — | 🔴 | API key for accessing each Typesense node | +| TYPESENSE_HOST | string | — | 🔴 | Hostname or FQDN of the Typesense node | +| TYPESENSE_PORT | uint | `8108` | | Port for Typesense REST/API Port | +| TYPESENSE_PROTOCOL | string | `http` | | Protocol for Typesense API (`http` or `https`) | +| TYPESENSE_CLUSTER | string | — | 🔴 | Cluster identifier label for metrics | +| METRICS_PORT | uint | `8908` | | Port on which `/metrics` is served | :::note All these values are automatically configured by the operator. From bc1dbc7487cf7d2a3ffb46a07381c8cac2ccb4bf Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 08:16:17 +0000 Subject: [PATCH 5/6] fixed otc and dt references #63 --- docs/adopters.md | 2 +- docs/crds/examples.md | 10 +++++----- docs/crds/index.mdx | 4 ++-- docs/healthcheck.md | 2 +- docs/installation/index.md | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/adopters.md b/docs/adopters.md index ecc555e..e109de7 100644 --- a/docs/adopters.md +++ b/docs/adopters.md @@ -8,7 +8,7 @@ If TyKO handles the lifecycle of your Typesense clusters in Kubernetes, please a |Name| Description| |---|---| -|[Architecture Center of T Cloud Public](https://arch.otc-service.com/)|The Best Practices & Blueprints knowledge-hub of [T Cloud Public](https://public.t-cloud.com/en), the public cloud offering of [Deutsche Telekom AG](https://www.telekom.de/start).| +|[Architecture Center of T Cloud Public](https://arch.otc-service.com/)|The Best Practices & Blueprints knowledge-hub of [T Cloud Public](https://public.t-cloud.com/en), the public cloud offering of [Deutsche Telekom AG](https://www.telekom.com).| |[anny](https://anny.co)|Your flexible booking system for all kinds of resources.| |[Procure Ai](https://www.procure.ai/)|We enable people to run the world’s most intelligent procurement – human & artificial.| |[Hardcover.app](https://hardcover.app/)|Social network and book tracking for readers.| diff --git a/docs/crds/examples.md b/docs/crds/examples.md index 3c7b393..5334f51 100644 --- a/docs/crds/examples.md +++ b/docs/crds/examples.md @@ -79,10 +79,10 @@ As of **v0.3.6**, storage `accessMode` is introduced that supports `ReadWriteOnc :::warning -1. When working with [Open Telekom Cloud Object Storage Service (OBS)](https://www.open-telekom-cloud.com/en/products-services/core-services/object-storage-service), [JuiceFS](https://juicefs.com/en/) and [Redis](https://redis.io/) **are not** required in order to mount S3 bucket in the Pods. The `everest-csi-provisioner` takes care of the whole life-cycle of provisioning and mount bucket as volumes +1. When working with [T Cloud Public Object Storage Service (OBS)](https://www.open-telekom-cloud.com/en/products-services/core-services/object-storage-service), [JuiceFS](https://juicefs.com/en/) and [Redis](https://redis.io/) **are not** required in order to mount S3 bucket in the Pods. The `everest-csi-provisioner` takes care of the whole life-cycle of provisioning and mount bucket as volumes via annotations. You can skip this section entirely. -2. When working with [Amazon S3](https://aws.amazon.com/s3/), [Redis](https://redis.io/) **is not** required, as Amazon S3 comes with is own metadata endpoints. +1. When working with [Amazon S3](https://aws.amazon.com/s3/), [Redis](https://redis.io/) **is not** required, as Amazon S3 comes with is own metadata endpoints. ::: @@ -222,9 +222,9 @@ spec: This is by no means a production-ready Redis cluster nor a best-practice on how to deploy Redis on Kubernetes. It's just a quick spin of cluster in order to be able to work with JuiceFS. ::: -### Open Telekom Cloud OBS +### T Cloud Public OBS -If you are running on [Open Telekom Cloud](https://www.open-telekom-cloud.com/en), you can take advantage of the additional annotations field `csi.storage.k8s.io/fstype` +If you are running on [T Cloud Public](https://www.open-telekom-cloud.com/en), you can take advantage of the additional annotations field `csi.storage.k8s.io/fstype` that controls how an S3 bucket is mounted into a Kubernetes pod. - Using `csi.storage.k8s.io/fstype: s3fs` mounts an [SFS Turbo, Scalable File System](https://www.open-telekom-cloud.com/en/products-services/core-services/scalable-file-service) bucket using the S3-compatible API, @@ -258,7 +258,7 @@ spec: :::note One big advantage of using these annotations is that the respective S3 buckets will be provisioned dynamically by the CSI itself. -For more information about configuring Open Telekom Cloud `StorageClass` consult +For more information about configuring T Cloud Public `StorageClass` consult the [official documentation](https://docs.otc.t-systems.com/cloud-container-engine/umn/storage/storageclass.html). ::: diff --git a/docs/crds/index.mdx b/docs/crds/index.mdx index 6266576..20cec67 100644 --- a/docs/crds/index.mdx +++ b/docs/crds/index.mdx @@ -96,7 +96,7 @@ which may obscure the client's source IP, or `Local`, which preserves the client :::important As of **v0.3.6**, storage `accessMode` is introduced that supports `ReadWriteOnce` and `ReadWriteMany`. -* If you are running on [Open Telekom Cloud](https://www.open-telekom-cloud.com/en), you can take advantage of the additional annotations field `csi.storage.k8s.io/fstype` +* If you are running on [T Cloud Public](https://www.open-telekom-cloud.com/en), you can take advantage of the additional annotations field `csi.storage.k8s.io/fstype` that controls how an S3 bucket is mounted into a Kubernetes pod. Using `csi.storage.k8s.io/fstype: s3fs` mounts an [SFS Turbo, Scalable File System](https://www.open-telekom-cloud.com/en/products-services/core-services/scalable-file-service) bucket using the S3-compatible API, which is useful when you want simple “filesystem-like” access but are okay with object-storage semantics that may not fully match POSIX behavior. Using the annotation `csi.storage.k8s.io/fstype: obsfs` mounts the bucket using the native OBS filesystem driver and is generally the more “OBS-native” approach; @@ -168,7 +168,7 @@ _-The Ingress API is no longer being developed, and will have no further changes :::note 1️⃣ This feature makes use of the existence of [cert-manager](https://cert-manager.io/) in the cluster, but **does not** actively enforce it with an error. If no clusterIssuer is specified a valid certificate must be stored in a secret and the secret name must be provided in the tlsSecretName config. -If you are targeting [Open Telekom Cloud](https://www.open-telekom-cloud.com/en), you might be interested in provisioning additionally the designated DNS solver webhook for Open Telekom Cloud. You can find it [here](https://github.com/akyriako/cert-manager-webhook-opentelekomcloud). +If you are targeting [T Cloud Public](https://www.open-telekom-cloud.com/en), you might be interested in provisioning additionally the designated DNS solver webhook for T Cloud Public. You can find it [here](https://github.com/akyriako/cert-manager-webhook-opentelekomcloud). 2️⃣ Although in official Typesense documentation under _Production Best Practices_ -> _Configuration_ is stated: diff --git a/docs/healthcheck.md b/docs/healthcheck.md index c6cab92..82298cf 100644 --- a/docs/healthcheck.md +++ b/docs/healthcheck.md @@ -98,7 +98,7 @@ The *typesense-healthcheck* sidecar aggregates and reports the health of all nod ``` :::tip -You can configure external load balancers (e.g., AWS ALB or Open Telekom Cloud ELB) to probe the sidecar’s `/readyz` endpoint for continuous, real-time health checks of your cluster. +You can configure external load balancers (e.g., AWS ALB or T Cloud Public ELB) to probe the sidecar’s `/readyz` endpoint for continuous, real-time health checks of your cluster. ::: ## Web UI diff --git a/docs/installation/index.md b/docs/installation/index.md index ddb700c..188b1ac 100644 --- a/docs/installation/index.md +++ b/docs/installation/index.md @@ -66,7 +66,7 @@ Provision one of the samples available in **config/samples**: | | Generic | | standard | | azure | Microsoft Azure | disk.csi.azure.com | managed-csi | | aws | AWS | ebs.csi.aws.com | gp2 | -| opentelekomcloud | Open Telekom Cloud | disk.csi.everest.io
obs.csi.everest.io | csi-disk
csi-obs | +| opentelekomcloud | T Cloud Public | disk.csi.everest.io
obs.csi.everest.io | csi-disk
csi-obs | | gcp | Google Cloud Platform | pd.csi.storage.gke.io | standard-rwo | | bm | Bare Metal | democratic-csi-iscsi
democratic-csi-nfs | iscsi
nfs | | kind | KIND | | rancher.io/local-path | @@ -75,7 +75,7 @@ Provision one of the samples available in **config/samples**: kubectl apply -f config/samples/ts_v1alpha1_typesensecluster_{{Suffix}}.yaml ``` -e.g. for Open Telekom Cloud it would look like: +e.g. for T Cloud Public it would look like: ```yaml title=ts_v1alpha1_typesensecluster_opentelekomcloud.yaml apiVersion: v1 From f4a7921496dce48a0c55e98d3eea26fe91c645c1 Mon Sep 17 00:00:00 2001 From: Kyriakos Akriotis Date: Wed, 8 Jul 2026 08:30:07 +0000 Subject: [PATCH 6/6] added pdb explanation #63 --- docs/how-it-works/quorum-reconfiguration.md | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/docs/how-it-works/quorum-reconfiguration.md b/docs/how-it-works/quorum-reconfiguration.md index feab3f3..afa128e 100644 --- a/docs/how-it-works/quorum-reconfiguration.md +++ b/docs/how-it-works/quorum-reconfiguration.md @@ -59,3 +59,30 @@ A `StatefulSet` will be provisioned by the operator as next step of the reconcil ### 7. Evaluating Quorum The controller, in every reconciliation loop term, assesses the quorum's health by probing and collecting information about the state and the health of each member of the quorum (in our case for every `Pod` which represents a Typesense node). Based on the outcome, the controller devises an action plan for the next reconciliation loop. This process is detailed in the following section: + +## Why PodDisruptionBudgets are not used by the Operator? + +The Typesense Operator intentionally does **not** create a `PodDisruptionBudget` for the operator-managed Typesense `StatefulSet`. + +**This is a design decision.** + +The operator does not treat Kubernetes pod readiness as a simple container-health signal. Each Typesense pod includes a custom `PodReadinessGate`, and the operator updates that gate only after evaluating the underlying Typesense node and quorum state. A pod is considered `Ready` **only when the operator determines that the corresponding Typesense node is healthy and safe to serve traffic**. + +During quorum problems such as split brain, election deadlock, unavailable nodes, or failed recovery, the operator may deliberately mark pods as not ready, scale the `StatefulSet` down to one replica, update the nodes configuration, and under certain circumstances purge the pods as part of its automatic recovery flow. + +A `PodDisruptionBudget` works against this model. + +When the operator marks pods as not ready during recovery, a PDB would also see fewer healthy pods. As a result, `allowedDisruptions` would typically interfere exactly when the operator is trying to repair the cluster. This does not protect the quorum; instead, it blocks normal eviction-based operations such as node drains, cluster-autoscaler consolidation, and maintenance workflows. + +A PDB also does not protect against the operator’s own recovery actions. The operator deletes pods directly when purging or rebuilding quorum state, so a PDB would not provide meaningful protection at the point where recovery is actually happening. + +In practice, adding a PDB around the operator-managed `StatefulSet` can cause the opposite of the intended result: + +* node drains and autoscaler operations may become stuck; +* quorum recovery may be delayed, blocked or sent to an eternal loop; +* an allowed eviction can remove a peer at the wrong time and force another recovery cycle; +* the operator and the PDB may end up fighting over availability semantics. + +For this reason, it is finally recommended **not to add a PDB to the Typesense `StatefulSet` managed by the operator** by yourselves. + +Availability should instead be handled through the operator’s quorum-aware reconciliation, appropriate replica count, anti-affinity, topology spread constraints, resource sizing, persistent storage, and careful node maintenance procedures.