diff --git a/docusaurus.config.en.js b/docusaurus.config.en.js index ad0d063e997..8cf07d2299d 100644 --- a/docusaurus.config.en.js +++ b/docusaurus.config.en.js @@ -302,6 +302,7 @@ const config = { plugins: [ "docusaurus-plugin-sass", + "./plugins/version-extractor", function (context, options) { return { name: "docusaurus-plugin", diff --git a/package.json b/package.json index af6e79be15e..d59e8d7141b 100644 --- a/package.json +++ b/package.json @@ -43,7 +43,11 @@ "@docusaurus/preset-classic": "3.7.0", "@docusaurus/theme-mermaid": "3.7.0", "@docusaurus/theme-search-algolia": "^3.7.0", + "@emotion/react": "^11.14.0", + "@emotion/styled": "^11.14.1", "@mdx-js/react": "^3.1.0", + "@mui/material": "^7.3.0", + "@mui/styled-engine-sc": "^7.3.0", "@radix-ui/react-navigation-menu": "^1.2.13", "@redocly/cli": "^1.34.0", "axios": "^1.11.0", @@ -73,6 +77,7 @@ "sass": "^1.89.1", "search-insights": "^2.17.3", "short-uuid": "^5.2.0", + "styled-components": "^6.1.19", "unist-util-visit": "^5.0.0" }, "devDependencies": { diff --git a/plugins/version-extractor/index.js b/plugins/version-extractor/index.js new file mode 100644 index 00000000000..a5502f160a7 --- /dev/null +++ b/plugins/version-extractor/index.js @@ -0,0 +1,138 @@ +const fs = require('fs'); +const path = require('path'); + +function extractVersions(siteDir) { + // Extract latest OSS version from index.md (2025 changelog) + function getLatestOSSVersion() { + try { + // Check 2025 changelog first (index.md) + const changelog2025Path = path.join(siteDir, 'docs/whats-new/changelog/index.md'); + if (fs.existsSync(changelog2025Path)) { + const content = fs.readFileSync(changelog2025Path, 'utf8'); + + // Look for the first version pattern like "25.7" + const versionMatch = content.match(/ClickHouse release v(\d+\.\d+)/); + if (versionMatch) { + const version = versionMatch[1]; + // Create anchor link (e.g., "25.7" -> "#257") + const anchor = version.replace('.', ''); + return { + version: `v${version}`, + link: `/docs/whats-new/changelog#${anchor}` + }; + } + } + + // Fallback to 2024 changelog + const changelog2024Path = path.join(siteDir, 'docs/whats-new/changelog/2024.md'); + const content = fs.readFileSync(changelog2024Path, 'utf8'); + + // Look for the first version pattern like "24.12" + const versionMatch = content.match(/ClickHouse release (?:v)?(\d+\.\d+)/); + const version = versionMatch ? versionMatch[1] : '24.12.1'; + return { + version: `v${version}`, + link: `/docs/whats-new/changelog/2024` + }; + } catch (error) { + console.warn('Could not extract OSS version:', error.message); + return { + version: 'v25.7', + link: '/docs/whats-new/changelog#257' + }; + } + } + + // Extract latest Cloud version from changelog directory + function getLatestCloudVersion() { + try { + const changelogDir = path.join(siteDir, 'docs/cloud/changelogs'); + const files = fs.readdirSync(changelogDir) + .filter(file => file.endsWith('.md')) + .map(file => { + const match = file.match(/(\d+)_(\d+)\.md$/); + if (match) { + // Convert "06" to "6", "04" to "4", etc. + const major = match[1]; + const minor = parseInt(match[2], 10).toString(); + return { + version: `${major}.${minor}`, + file: file, + link: `/docs/changelogs/${major}.${minor}` + }; + } + return null; + }) + .filter(Boolean) + .sort((a, b) => { + // Sort by version number (descending) + const [aMajor, aMinor] = a.version.split('.').map(Number); + const [bMajor, bMinor] = b.version.split('.').map(Number); + + if (aMajor !== bMajor) return bMajor - aMajor; + return bMinor - aMinor; + }); + + if (files.length > 0) { + return { + version: `v${files[0].version}`, + link: files[0].link + }; + } + + return { + version: 'v25.6', + link: '/docs/changelogs/25.6' + }; + } catch (error) { + console.warn('Could not extract Cloud version:', error.message); + return { + version: 'v25.6', + link: '/docs/changelogs/25.6' + }; + } + } + + const ossVersionInfo = getLatestOSSVersion(); + const cloudVersionInfo = getLatestCloudVersion(); + + return { + oss: { + version: ossVersionInfo.version, + link: ossVersionInfo.link + }, + cloud: { + version: cloudVersionInfo.version, + link: cloudVersionInfo.link + }, + generatedAt: new Date().toISOString() + }; +} + +module.exports = function versionExtractorPlugin(context, options) { + return { + name: 'version-extractor-plugin', + + async loadContent() { + const versions = extractVersions(context.siteDir); + return versions; + }, + + async contentLoaded({ content, actions }) { + const { createData } = actions; + + // Create a JSON file that can be imported + await createData('versions.json', JSON.stringify(content, null, 2)); + + // Also create a JS module for easier importing + const jsContent = `export default ${JSON.stringify(content, null, 2)};`; + await createData('versions.js', jsContent); + + console.log('๐Ÿ” Extracted versions:', content); + }, + + getClientModules() { + return []; + } + }; +}; \ No newline at end of file diff --git a/scripts/settings/beta-settings.sql b/scripts/settings/beta-settings.sql index 8d376f29178..ec373ab1b54 100644 --- a/scripts/settings/beta-settings.sql +++ b/scripts/settings/beta-settings.sql @@ -13,7 +13,7 @@ WITH FROM system.settings WHERE tier = 'Beta' AND alias_for='' -AND NOT (name LIKE 'vector_search_with_rescoring' OR name LIKE 'vector_search_postfilter_multiplier' OR name LIKE 'vector_search_index_fetch_multiplier')), +AND NOT (name LIKE 'vector_search_with_rescoring' OR name LIKE 'vector_search_postfilter_multiplier' OR name LIKE 'vector_search_index_fetch_multiplier' OR name LIKE 'allow_experimental_vector_similarity_index')), beta_mergetree_settings AS ( SELECT diff --git a/src/css/custom.scss b/src/css/custom.scss index 9161e8722e0..fb284b91958 100644 --- a/src/css/custom.scss +++ b/src/css/custom.scss @@ -141,6 +141,10 @@ body { color: white; } +.footer { + z-index: 100; +} + [data-theme='dark'] .footer { background-color: var(--click-color-background); } diff --git a/src/css/default.scss b/src/css/default.scss index 08bdf0e4814..769a92c0a97 100644 --- a/src/css/default.scss +++ b/src/css/default.scss @@ -114,6 +114,7 @@ --icon: none; } + /* Add dark theme */ [data-theme='dark'] { --ifm-menu-color: #FFFFF; diff --git a/src/hooks/useAnchorFix.js b/src/hooks/useAnchorFix.js index b1eb138ac0c..36cc467fd87 100644 --- a/src/hooks/useAnchorFix.js +++ b/src/hooks/useAnchorFix.js @@ -12,7 +12,9 @@ export function useAnchorFix() { if (hash) { // Wait for content to load, then scroll setTimeout(() => { - const element = document.querySelector(hash); + // CSS selectors that start with a digit are invalid, so we need to escape them + const escapedHash = hash.replace(/^#(\d)/, '#\\3$1 '); + const element = document.querySelector(escapedHash); if (element) { element.scrollIntoView({ behavior: 'smooth' }); } diff --git a/src/hooks/useVersions.js b/src/hooks/useVersions.js new file mode 100644 index 00000000000..c84837edc64 --- /dev/null +++ b/src/hooks/useVersions.js @@ -0,0 +1,29 @@ +import { useState, useEffect } from 'react'; + +// Hook to get version information +export function useVersions() { + const [versions, setVersions] = useState({ + oss: { version: 'v24.12.1', link: '/docs/whats-new/changelog' }, + cloud: { version: 'v25.6', link: '/docs/changelogs/25.6' } + }); + + useEffect(() => { + // Try to load the generated versions data + const loadVersions = async () => { + try { + // This will work when the plugin generates the data + const versionData = await import('@generated/version-extractor-plugin/default/versions.js'); + if (versionData.default) { + setVersions(versionData.default); + } + } catch (error) { + console.warn('Could not load generated versions, using defaults:', error); + // Fallback to defaults already set in useState + } + }; + + loadVersions(); + }, []); + + return versions; +} \ No newline at end of file diff --git a/src/pages/homepage_styles.module.scss b/src/pages/homepage_styles.module.scss new file mode 100644 index 00000000000..6c47a1efd73 --- /dev/null +++ b/src/pages/homepage_styles.module.scss @@ -0,0 +1,239 @@ +@use '../css/breakpoints.scss' as breakpoints; + +.yellowStrip { + height: 3px; + background: linear-gradient(to right, transparent, #faff69, transparent); + width: 100%; +} + +.topLevelContainer { + position: absolute; + left: 0; + top: 4rem; + width: 100%; + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + padding-bottom: 60px; +} + +@media (min-width: breakpoints.$laptop-breakpoint) { + .topLevelContainer { + top: 7.5rem; + } +} + +[data-theme='dark'] .topLevelContainer { + background-color: #1a1a1a; +} + +.exploreDocs { + width: 100%; + max-width: 1000px; + margin-bottom: 2rem; + margin-top: 2rem; +} + +.panel { + margin: 0px 5px; + background-color: rgba(0, 0, 0, 0); + box-shadow: lch(6.77 0 0 / 0.15) 0px 4px 6px -1px, lch(6.77 0 0 / 0.15) 0px 2px 4px -1px; + padding: 1rem; + border-radius: 10px; + margin: 0px 20px; +} + +[data-theme='dark'] .panel { + border: 1px solid rgb(50, 50, 50); +} + +[data-theme='light'] .panel { + border: 1px solid rgb(230, 231, 233); +} + +.panel_links { + display: flex; + flex-direction: column; + font-size: 16px; +} + +.panel_heading { + display: flex; + + h2 { + margin-left: 16px; + } +} + +.navatticDemoSection { + display: flex; + justify-content: center; + align-items: center; + flex-direction: column; + max-width: 1000px; + margin-bottom: 6rem; +} + +.heroSection { + display: flex; + flex-direction: column; + justify-items: center; + align-items: center; + max-width: 600px; + + h2 { + text-align: center; + } + + .logo { + width: 300px; + height: auto; + } + + [data-theme='dark'] .logo { + color: white; + } + + [data-theme='light'] .logo { + color: black !important; + } +} + + +.navatticDemo { + display: flex; + align-items: center; + justify-content: center; + width: 90%; +} + +/* Styling for the browser window illusion around the demo */ + +.browser_mockup { + background: #f6f8fa; + border-radius: 8px; + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); + width: 90%; + max-width: 1200px; + overflow: hidden; + position: relative; +} + +.browser_header { + background: linear-gradient(180deg, #e8e8e8 0%, #d1d1d1 100%); + padding: 12px 16px; + display: flex; + align-items: center; + gap: 12px; + border-bottom: 1px solid #c0c0c0; +} + +.traffic_lights { + display: flex; + gap: 8px; +} + +.traffic_light { + width: 12px; + height: 12px; + border-radius: 50%; + border: 1px solid rgba(0, 0, 0, 0.1); +} + +.close { + background: #ff5f57; + background: linear-gradient(135deg, #ff6b5a, #ff4d3d); +} + +.minimize { + background: #ffbd2e; + background: linear-gradient(135deg, #ffc843, #ffab00); +} + +.maximize { + background: #28ca42; + background: linear-gradient(135deg, #32d74b, #1eb932); +} + +.address_bar { + flex: 1; + background: white; + border: 1px solid #ccc; + border-radius: 6px; + padding: 6px 12px; + font-size: 13px; + color: #666; + margin-left: 20px; + position: relative; +} + +.address_bar::before { + content: "๐Ÿ”’"; + position: absolute; + left: 8px; + top: 50%; + transform: translateY(-50%); + font-size: 11px; +} + +.address_bar_text { + margin-left: 18px; +} + +.browser_controls { + display: flex; + gap: 8px; + margin-left: 12px; +} + +.control_btn { + width: 28px; + height: 28px; + border-radius: 4px; + background: transparent; + border: 1px solid transparent; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 14px; + color: #666; +} + +.control_btn:hover { + background: rgba(0, 0, 0, 0.05); + border-color: rgba(0, 0, 0, 0.1); +} + +.browser_content { + background: white; + position: relative; + height: 600px; +} + +.try_it_out { + position: relative; + top: 15px; + left: -50px; + width: 135px; + background: #fdff73; + color: black; + padding: 8px 16px; + border-radius: 20px; + font-size: 13px; + font-weight: 600; + white-space: nowrap; + z-index: 10; + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + transform: rotate(0); + display: flex; + align-items: center; + gap: 8px; +} + +.try_it_out::after { + content: 'โคต'; + font-size: 16px; +} + diff --git a/src/pages/index.js b/src/pages/index.js new file mode 100644 index 00000000000..ad930b05455 --- /dev/null +++ b/src/pages/index.js @@ -0,0 +1,932 @@ +import React from 'react'; +import Layout from '@theme/Layout'; +import homepage_styles from './homepage_styles.module.scss' +import {useColorMode} from "@docusaurus/theme-common"; +import Link from '@docusaurus/Link'; +import useBaseUrl from '@docusaurus/useBaseUrl'; +import { useVersions } from '@site/src/hooks/useVersions'; +import ClickHouseLogoDark from '@site/static/img/ch_logo_docs_dark.svg'; +import ClickHouseLogoLight from '@site/static/img/ch_logo_docs.svg'; +import ClickHouseLogo from '@site/src/icons/ClickHouseLogo'; +import SearchBar from '@theme/SearchBar'; +import clsx from 'clsx'; +import Card from '@mui/material/Card'; +import CardContent from '@mui/material/CardContent'; +import CardMedia from '@mui/material/CardMedia'; +import CardActionArea from '@mui/material/CardActionArea'; +import Box from '@mui/material/Box'; +import Typography from '@mui/material/Typography'; +import Button from '@mui/material/Button'; +import Grid from '@mui/material/Grid'; +import ColorModeToggle from "@theme-original/ColorModeToggle"; +import { ThemeProvider, createTheme } from '@mui/material/styles'; +import CssBaseline from '@mui/material/CssBaseline'; + + +const NavatticDemo = ({ + demoId = "cmbj9y9dx000004lbbeus84ns", + width = "100%", + height = "600px", + className = "" +}) => { + const src = `https://capture.navattic.com/${demoId}`; + return ( +
+
Try out Cloud
+
+
+
+
+
+
+ +
+
https://console.clickhouse.cloud
+
+
+ +
+
+