You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pinot.apache.org by xi...@apache.org on 2026/03/22 04:15:25 UTC
(pinot-site) branch fix/factual-consistency-ssot created (now b255c56d)
This is an automated email from the ASF dual-hosted git repository.
xiangfu pushed a change to branch fix/factual-consistency-ssot
in repository https://gitbox.apache.org/repos/asf/pinot-site.git
at b255c56d Fix factual consistency: add SSOT, normalize positioning, clean up data
This branch includes the following new commits:
new b255c56d Fix factual consistency: add SSOT, normalize positioning, clean up data
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org
(pinot-site) 01/01: Fix factual consistency: add SSOT, normalize positioning, clean up data
Posted by xi...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
xiangfu pushed a commit to branch fix/factual-consistency-ssot
in repository https://gitbox.apache.org/repos/asf/pinot-site.git
commit b255c56d0a6e86d8edb381db823c148502cd90db
Author: Xiang Fu <xi...@startree.ai>
AuthorDate: Sat Mar 21 21:15:06 2026 -0700
Fix factual consistency: add SSOT, normalize positioning, clean up data
- Create data/pinot-meta.json as single source of truth for version,
tagline, capabilities, and terminology
- Wire SSOT into siteMetadata.js, HeroSection, and download page
- Remove 7 duplicate 1.1.0 entries from downloadsData.ts
- Add "Latest" badge to download tables from SSOT
- Show latest release version/date on download page header
- Normalize feature titles to canonical terminology (Sub-Second Queries,
Real-Time Streaming Ingestion)
- Add doc links to Upserts, Joins, SQL, and Multitenancy feature claims
- Add "last verified" markers to Features, Benchmarks, and Use Cases
- Add consistency CI check script (scripts/check-consistency.mjs)
- Update README.md with canonical positioning sentence
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
README.md | 2 +-
app/download/page.tsx | 6 +-
components/BenchmarkSection.tsx | 5 +
components/DownloadTable/DesktopDownloadTable.tsx | 10 +-
components/DownloadTable/MobileDownloadTable.tsx | 10 +-
components/Features.tsx | 5 +
components/HeroSection.tsx | 8 +-
components/UseCases.tsx | 5 +
data/downloadsData.ts | 133 --------------------
data/featuresData.ts | 36 ++++--
data/pinot-meta.json | 35 ++++++
data/siteMetadata.js | 6 +-
package.json | 3 +-
scripts/check-consistency.mjs | 142 ++++++++++++++++++++++
14 files changed, 254 insertions(+), 152 deletions(-)
diff --git a/README.md b/README.md
index f551ec01..0cd8822b 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@
This is the private repository for the Apache Pinot blog and documentation website. It contains all the source code and materials required for the development and deployment of the site. The website serves as a central platform for the Apache Pinot community to access the blog posts, tutorials, and comprehensive documentation.
-Apache Pinot is an open-source, distributed OLAP datastore designed to deliver real-time analytics with low latency and high throughput. The goal of this website is to provide an informative, responsive, and engaging user experience to all community members.
+Apache Pinot is an open-source distributed OLAP datastore for user-facing and agent-facing real-time analytics, delivering sub-second queries on fresh data at very high concurrency. The goal of this website is to provide an informative, responsive, and engaging user experience to all community members.
## Getting Started
diff --git a/app/download/page.tsx b/app/download/page.tsx
index 745bd7c4..6a4e2d73 100644
--- a/app/download/page.tsx
+++ b/app/download/page.tsx
@@ -3,10 +3,11 @@ import { allDownloads } from 'contentlayer/generated';
import { genPageMetadata } from '../seo';
import { transformAndSortDownloads } from '../lib/download.utils';
import Downloads from '@/components/DownloadTable/Downloads';
+import pinotMeta from '@/data/pinot-meta.json';
export const metadata = genPageMetadata({
title: 'Download',
- description: 'Download Apache Pinot'
+ description: `Download Apache Pinot ${pinotMeta.latestVersion} - ${pinotMeta.shortDescription}`
});
const Download = () => {
@@ -19,6 +20,9 @@ const Download = () => {
<h1 className="mb-6 text-3xl font-bold md:text-5xl">
Apache Pinot™ Download
</h1>
+ <p className="mb-2 text-lg font-medium text-vine-100">
+ Latest release: {pinotMeta.latestVersion} ({pinotMeta.latestReleaseDate})
+ </p>
<p className="text-lg md:mb-12">
Be sure to verify your downloads by these{' '}
<Link
diff --git a/components/BenchmarkSection.tsx b/components/BenchmarkSection.tsx
index cbb2a7f1..5f666b4c 100644
--- a/components/BenchmarkSection.tsx
+++ b/components/BenchmarkSection.tsx
@@ -1,4 +1,5 @@
import benchmarkData from '@/data/benchmarkData';
+import pinotMeta from '@/data/pinot-meta.json';
const BenchmarkSection: React.FC = () => {
return (
@@ -38,6 +39,10 @@ const BenchmarkSection: React.FC = () => {
users. Your results will vary based on hardware, schema design, and query
complexity.
</p>
+ <p className="mt-2 text-xs text-gray-500 dark:text-gray-500">
+ Last verified against Apache Pinot {pinotMeta.lastVerifiedVersion} on{' '}
+ {pinotMeta.lastVerified}
+ </p>
</div>
</div>
</section>
diff --git a/components/DownloadTable/DesktopDownloadTable.tsx b/components/DownloadTable/DesktopDownloadTable.tsx
index 02625479..780f3be4 100644
--- a/components/DownloadTable/DesktopDownloadTable.tsx
+++ b/components/DownloadTable/DesktopDownloadTable.tsx
@@ -8,6 +8,7 @@ import {
TableRow
} from '@/components/ui/table';
import { type DownloadData } from '@/data/downloadsData';
+import pinotMeta from '@/data/pinot-meta.json';
import Link from '../Link';
interface DownloadTableProps {
@@ -39,7 +40,14 @@ const DesktopDownloadTable: React.FC<DownloadTableProps> = ({ data }) => {
<TableBody>
{data.map((download) => (
<TableRow key={download.version} className="border-t border-neutral-400">
- <TableCell className="align-top text-lg">{download.version}</TableCell>
+ <TableCell className="align-top text-lg">
+ {download.version}
+ {download.version === pinotMeta.latestVersion && (
+ <span className="ml-2 inline-block rounded bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-800">
+ Latest
+ </span>
+ )}
+ </TableCell>
<TableCell className="align-top text-lg">{download.date}</TableCell>
<TableCell className="align-top">
<div className="flex space-x-2 text-lg font-semibold">
diff --git a/components/DownloadTable/MobileDownloadTable.tsx b/components/DownloadTable/MobileDownloadTable.tsx
index b10f7849..aa070e28 100644
--- a/components/DownloadTable/MobileDownloadTable.tsx
+++ b/components/DownloadTable/MobileDownloadTable.tsx
@@ -1,6 +1,7 @@
import React from 'react';
import Link from '../Link';
import { type DownloadData } from '@/data/downloadsData';
+import pinotMeta from '@/data/pinot-meta.json';
interface DownloadTableProps {
data: DownloadData[];
@@ -15,7 +16,14 @@ const MobileDownloadTable: React.FC<DownloadTableProps> = ({ data }) => {
<div className="flex w-72 justify-between">
<div className="flex flex-col">
<div className="font-semibold">Version</div>
- <div>{download.version}</div>
+ <div>
+ {download.version}
+ {download.version === pinotMeta.latestVersion && (
+ <span className="ml-2 inline-block rounded bg-green-100 px-2 py-0.5 text-xs font-semibold text-green-800">
+ Latest
+ </span>
+ )}
+ </div>
</div>
<div className="flex flex-col">
<div className="font-semibold">Date</div>
diff --git a/components/Features.tsx b/components/Features.tsx
index e3cddb90..93a54984 100644
--- a/components/Features.tsx
+++ b/components/Features.tsx
@@ -1,5 +1,6 @@
import Feature from './Feature';
import featuresData from '@/data/featuresData';
+import pinotMeta from '@/data/pinot-meta.json';
const Features: React.FC = () => {
return (
@@ -18,6 +19,10 @@ const Features: React.FC = () => {
/>
))}
</div>
+ <p className="mt-12 text-center text-xs text-gray-500 dark:text-gray-500">
+ Last verified against Apache Pinot {pinotMeta.lastVerifiedVersion} on{' '}
+ {pinotMeta.lastVerified}
+ </p>
</div>
</section>
);
diff --git a/components/HeroSection.tsx b/components/HeroSection.tsx
index 2a277fdb..cd91d106 100644
--- a/components/HeroSection.tsx
+++ b/components/HeroSection.tsx
@@ -2,6 +2,7 @@ import Image from 'next/image';
import { Button } from './ui/button';
import Link from 'next/link';
import siteMetadata from '@/data/siteMetadata';
+import pinotMeta from '@/data/pinot-meta.json';
import ResponsiveImage from './ResponsiveImage';
const HeroSection = () => {
@@ -11,13 +12,10 @@ const HeroSection = () => {
<section className="md:mx-auto md:max-w-screen-outerLiveArea">
<div className="p-8 text-center md:pb-12 md:pt-24">
<h1 className="mb-4 text-4xl font-bold leading-[45px] md:text-[3.5rem] md:leading-[70px]">
- Real-Time Analytics at Extreme Scale
+ {pinotMeta.heroHeadline}
</h1>
<p className="m-auto mb-8 max-w-4xl text-lg md:leading-[28.80px]">
- Apache Pinot™ is a real-time distributed OLAP datastore that delivers
- sub-second queries over streaming and batch data. Purpose-built for user-facing
- analytics, it handles hundreds of thousands of queries per second with
- millisecond latency at petabyte scale.
+ {pinotMeta.heroDescription}
</p>
<div className="flex justify-center gap-4">
<Button
diff --git a/components/UseCases.tsx b/components/UseCases.tsx
index cf4a4b07..b14d81ca 100644
--- a/components/UseCases.tsx
+++ b/components/UseCases.tsx
@@ -1,5 +1,6 @@
import UseCase from './UseCase';
import useCasesData from '@/data/useCasesData';
+import pinotMeta from '@/data/pinot-meta.json';
const UseCases: React.FC = () => {
return (
@@ -17,6 +18,10 @@ const UseCases: React.FC = () => {
<UseCase key={useCase.id} {...useCase} />
))}
</div>
+ <p className="mt-12 text-center text-xs text-gray-500 dark:text-gray-500">
+ Last verified against Apache Pinot {pinotMeta.lastVerifiedVersion} on{' '}
+ {pinotMeta.lastVerified}
+ </p>
</div>
</section>
);
diff --git a/data/downloadsData.ts b/data/downloadsData.ts
index d0f2025e..ad37bdd5 100644
--- a/data/downloadsData.ts
+++ b/data/downloadsData.ts
@@ -54,139 +54,6 @@ const downloadData: DownloadData[] = [
releaseNotes:
'This release brings significant improvements, including enhancements to the multistage query engine and the introduction of an experimental time series query engine for efficient analysis. Key features include database query quotas, cursor-based pagination for large result sets, multi-stream ingestion, and new function support for URL and GeoJson. Security vulnerabilities and several bug fixes and performance enhancements have been addressed, ensuring a more robust and versa [...]
},
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
- {
- version: '1.1.0',
- date: '3/25/2024',
- href: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- officialSource: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-src.tar.gz.asc'
- },
- binary: {
- download:
- 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz',
- sha512: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.sha512',
- asc: 'https://apachepinot.gateway.scarf.sh/pinot/1.1.0/apache-pinot-1.1.0-bin.tar.gz.asc'
- },
- releaseNotes:
- 'This release includes new multi-stage query engine features, enhancements, and bug fixes.'
- },
{
version: '1.1.0',
date: '3/25/2024',
diff --git a/data/featuresData.ts b/data/featuresData.ts
index dabedc23..8d63bb61 100644
--- a/data/featuresData.ts
+++ b/data/featuresData.ts
@@ -8,9 +8,9 @@ interface Feature {
const featuresData: Feature[] = [
{
imageSrc: '/static/images/features/fast_queries.svg',
- title: 'Fast Queries',
+ title: 'Sub-Second Queries',
description: [
- 'Filter and aggregate petabyte data sets with P90 latencies in the tens of milliseconds—fast enough to return live results interactively in the UI.'
+ 'Filter and aggregate petabyte data sets with P90 latencies in the tens of milliseconds — fast enough to return live results interactively in the UI.'
]
},
{
@@ -22,7 +22,7 @@ const featuresData: Feature[] = [
},
{
imageSrc: '/static/images/features/batch_ingest.svg',
- title: 'Batch and Streaming Ingest',
+ title: 'Real-Time Streaming Ingestion',
description: [
'Ingest from ',
{ text: 'Apache Kafka', url: 'https://kafka.apache.org/' },
@@ -37,13 +37,25 @@ const featuresData: Feature[] = [
imageSrc: '/static/images/features/upsert.svg',
title: 'Upserts',
description: [
- 'Ingest the same record many times, but see only the latest value at query time. Upserts are built-in and production-tested since version 0.6.'
+ 'Ingest the same record many times, but see only the latest value at query time. ',
+ {
+ text: 'Upserts',
+ url: 'https://docs.pinot.apache.org/basics/data-import/upsert'
+ },
+ ' are built-in and production-tested since version 0.6.'
]
},
{
imageSrc: '/static/images/features/versatile_joins.svg',
title: 'Versatile Joins',
- description: ['Perform arbitrary fact/dimension and fact/fact joins on petabyte data sets.']
+ description: [
+ 'Perform arbitrary ',
+ {
+ text: 'fact/dimension and fact/fact joins',
+ url: 'https://docs.pinot.apache.org/users/user-guide-query/querying-pinot#joins'
+ },
+ ' on petabyte data sets.'
+ ]
},
{
imageSrc: '/static/images/features/options.svg',
@@ -97,14 +109,24 @@ const featuresData: Feature[] = [
imageSrc: '/static/images/features/sql_query.svg',
title: 'SQL Query Interface',
description: [
- 'The highly standard SQL query interface is accessible through a built-in query editor and a REST API.'
+ 'The highly standard ',
+ {
+ text: 'SQL query interface',
+ url: 'https://docs.pinot.apache.org/users/user-guide-query/querying-pinot'
+ },
+ ' is accessible through a built-in query editor and a REST API.'
]
},
{
imageSrc: '/static/images/features/multitenancy.svg',
title: 'Built-in Multitenancy',
description: [
- 'Manage and secure data in isolated logical namespaces for cloud-friendly resource management.'
+ 'Manage and secure data in isolated logical namespaces for cloud-friendly resource management. ',
+ {
+ text: 'Learn more about multitenancy',
+ url: 'https://docs.pinot.apache.org/basics/concepts/tenant'
+ },
+ '.'
]
}
];
diff --git a/data/pinot-meta.json b/data/pinot-meta.json
new file mode 100644
index 00000000..7d679e04
--- /dev/null
+++ b/data/pinot-meta.json
@@ -0,0 +1,35 @@
+{
+ "latestVersion": "1.4.0",
+ "latestReleaseDate": "2025-09-30",
+ "previousVersion": "1.3.0",
+ "previousReleaseDate": "2025-02-17",
+ "tagline": "Apache Pinot is an open-source distributed OLAP datastore for user-facing and agent-facing real-time analytics, delivering sub-second queries on fresh data at very high concurrency.",
+ "heroHeadline": "Real-Time Analytics at Extreme Scale",
+ "heroDescription": "Apache Pinot\u2122 is a real-time distributed OLAP datastore that delivers sub-second queries over streaming and batch data. Purpose-built for user-facing analytics, it handles hundreds of thousands of queries per second with millisecond latency at petabyte scale.",
+ "shortDescription": "Real-time distributed OLAP datastore for user-facing analytics",
+ "capabilities": [
+ "real-time streaming ingestion",
+ "upserts",
+ "versatile joins",
+ "rich indexing",
+ "high-concurrency (100K+ QPS)",
+ "sub-second latency",
+ "SQL query interface",
+ "built-in multitenancy"
+ ],
+ "ingestionSources": {
+ "streaming": ["Apache Kafka", "Apache Pulsar", "AWS Kinesis"],
+ "batch": ["Apache Hadoop", "Apache Spark", "AWS S3"]
+ },
+ "terminology": {
+ "latency": "sub-second / millisecond latency",
+ "ingestion": "real-time streaming ingestion",
+ "workload": "user-facing analytics",
+ "concurrency": "high-concurrency (100K+ QPS)",
+ "scale": "petabyte scale"
+ },
+ "docsUrl": "https://docs.pinot.apache.org/",
+ "githubUrl": "https://github.com/apache/pinot",
+ "lastVerified": "2025-09-30",
+ "lastVerifiedVersion": "1.4.0"
+}
diff --git a/data/siteMetadata.js b/data/siteMetadata.js
index 066f9940..6b306a57 100644
--- a/data/siteMetadata.js
+++ b/data/siteMetadata.js
@@ -1,3 +1,5 @@
+const pinotMeta = require('./pinot-meta.json');
+
/** @type {import("pliny/config").PlinyConfig } */
// create type
// type SiteMetadata = typeof siteMetadata;
@@ -5,7 +7,7 @@ const siteMetadata = {
title: 'Apache Pinot™',
author: 'Apache Pinot™',
headerTitle: '',
- description: 'Realtime distributed OLAP datastore',
+ description: pinotMeta.shortDescription,
language: 'en-us',
// theme: 'system', // system, dark or light
theme: 'light', // system, dark or light
@@ -27,7 +29,7 @@ const siteMetadata = {
description: 'Apache Pinot',
heading: 'What is Apache Pinot?',
paragraphs: [
- 'Originally developed at LinkedIn, Apache PinotTM is a real-time distributed OLAP datastore, purpose-built to provide ultra low-latency analytics at extremely high throughput.',
+ `Originally developed at LinkedIn, ${pinotMeta.tagline}`,
'With its distributed architecture and columnar storage, Apache Pinot empowers businesses to gain valuable insights from real-time data, supporting data-driven decision-making and applications.'
]
},
diff --git a/package.json b/package.json
index 4eef7576..f6f23b8f 100644
--- a/package.json
+++ b/package.json
@@ -14,7 +14,8 @@
"check": "npx prettier --check .",
"format": "npx prettier --write .",
"postinstall": "husky install && node ./scripts/patch-contentlayer.mjs",
- "test": "node --test tests/matomo.test.cjs"
+ "test": "node --test tests/matomo.test.cjs",
+ "check:consistency": "node ./scripts/check-consistency.mjs"
},
"dependencies": {
"@next/bundle-analyzer": "14.0.3",
diff --git a/scripts/check-consistency.mjs b/scripts/check-consistency.mjs
new file mode 100644
index 00000000..287b88e0
--- /dev/null
+++ b/scripts/check-consistency.mjs
@@ -0,0 +1,142 @@
+#!/usr/bin/env node
+
+/**
+ * Consistency check script for Apache Pinot website.
+ * Validates that version numbers and positioning language across the site
+ * match the single source of truth in data/pinot-meta.json.
+ *
+ * Run: node scripts/check-consistency.mjs
+ * Add to CI: exits with code 1 on mismatch.
+ */
+
+import { readFileSync, existsSync } from 'fs';
+import { resolve, dirname } from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = dirname(fileURLToPath(import.meta.url));
+const root = resolve(__dirname, '..');
+
+let errors = 0;
+
+function error(msg) {
+ console.error(` FAIL: ${msg}`);
+ errors++;
+}
+
+function pass(msg) {
+ console.log(` OK: ${msg}`);
+}
+
+// Load SSOT
+const metaPath = resolve(root, 'data/pinot-meta.json');
+if (!existsSync(metaPath)) {
+ console.error('FATAL: data/pinot-meta.json not found');
+ process.exit(1);
+}
+const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
+
+console.log(`\nChecking consistency against pinot-meta.json (v${meta.latestVersion})...\n`);
+
+// 1. Check siteMetadata.js pulls from SSOT
+console.log('[siteMetadata.js]');
+const siteMetaSrc = readFileSync(resolve(root, 'data/siteMetadata.js'), 'utf-8');
+if (siteMetaSrc.includes("require('./pinot-meta.json')")) {
+ pass('imports pinot-meta.json');
+} else {
+ error('siteMetadata.js does not import pinot-meta.json — description may drift');
+}
+
+// 2. Check downloadsData.ts has no duplicate versions
+console.log('\n[downloadsData.ts]');
+const downloadsSrc = readFileSync(resolve(root, 'data/downloadsData.ts'), 'utf-8');
+const versionMatches = [...downloadsSrc.matchAll(/version:\s*'([^']+)'/g)].map((m) => m[1]);
+const versionCounts = {};
+for (const v of versionMatches) {
+ versionCounts[v] = (versionCounts[v] || 0) + 1;
+}
+let hasDuplicates = false;
+for (const [v, count] of Object.entries(versionCounts)) {
+ if (count > 1) {
+ error(`version ${v} appears ${count} times (should be 1)`);
+ hasDuplicates = true;
+ }
+}
+if (!hasDuplicates) {
+ pass('no duplicate versions');
+}
+
+// 3. Check that latest version in downloads MDX matches SSOT
+console.log('\n[downloads MDX]');
+const latestMdxPath = resolve(root, `data/downloads/${meta.latestVersion}.mdx`);
+if (existsSync(latestMdxPath)) {
+ pass(`${meta.latestVersion}.mdx exists`);
+} else {
+ error(`${meta.latestVersion}.mdx missing — download page won't show latest version`);
+}
+
+// 4. Check HeroSection uses SSOT
+console.log('\n[HeroSection.tsx]');
+const heroSrc = readFileSync(resolve(root, 'components/HeroSection.tsx'), 'utf-8');
+if (heroSrc.includes('pinotMeta.heroHeadline') || heroSrc.includes('pinot-meta.json')) {
+ pass('uses pinot-meta.json for headline');
+} else {
+ error('HeroSection has hardcoded headline — may drift from SSOT');
+}
+if (heroSrc.includes('pinotMeta.heroDescription') || heroSrc.includes('pinot-meta.json')) {
+ pass('uses pinot-meta.json for description');
+} else {
+ error('HeroSection has hardcoded description — may drift from SSOT');
+}
+
+// 5. Scan for hardcoded version numbers in key component files
+console.log('\n[Hardcoded versions in components]');
+const componentFiles = [
+ 'components/HeroSection.tsx',
+ 'components/BenchmarkSection.tsx',
+ 'components/Features.tsx',
+ 'components/UseCases.tsx',
+ 'app/download/page.tsx'
+];
+const versionPattern = /\b1\.\d+\.\d+\b/g;
+for (const file of componentFiles) {
+ const filePath = resolve(root, file);
+ if (!existsSync(filePath)) continue;
+ const content = readFileSync(filePath, 'utf-8');
+ const hardcodedVersions = [...content.matchAll(versionPattern)].map((m) => m[0]);
+ if (hardcodedVersions.length > 0) {
+ error(`${file} has hardcoded version(s): ${[...new Set(hardcodedVersions)].join(', ')}`);
+ } else {
+ pass(`${file} — no hardcoded versions`);
+ }
+}
+
+// 6. Check that pinot-meta.json has required fields
+console.log('\n[pinot-meta.json schema]');
+const requiredFields = [
+ 'latestVersion',
+ 'latestReleaseDate',
+ 'tagline',
+ 'heroHeadline',
+ 'heroDescription',
+ 'shortDescription',
+ 'capabilities',
+ 'lastVerified',
+ 'lastVerifiedVersion'
+];
+for (const field of requiredFields) {
+ if (meta[field]) {
+ pass(`field "${field}" present`);
+ } else {
+ error(`field "${field}" missing or empty`);
+ }
+}
+
+// Summary
+console.log(`\n${'='.repeat(50)}`);
+if (errors === 0) {
+ console.log('All consistency checks passed.\n');
+ process.exit(0);
+} else {
+ console.error(`${errors} consistency error(s) found.\n`);
+ process.exit(1);
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@pinot.apache.org
For additional commands, e-mail: commits-help@pinot.apache.org