You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@apisix.apache.org by we...@apache.org on 2026/06/22 03:36:00 UTC
(apisix-website) branch feat/seo-technical-fixes created (now 5528ff16b0e)
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a change to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
at 5528ff16b0e chore(seo): noindex the auxiliary Netlify deploy
This branch includes the following new commits:
new 4b7c95423eb fix(seo): remove redundant hreflang plugin
new 1001edab1ac feat(seo): enrich Plugin Hub metadata and add catalog structured data
new c8f7c7f746d feat(seo): add SoftwareApplication and FAQPage structured data to homepage
new 49ba121b261 feat(seo): add an H1 heading to the blog list page
new 5528ff16b0e chore(seo): noindex the auxiliary Netlify deploy
The 5 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.
(apisix-website) 05/05: chore(seo): noindex the auxiliary Netlify deploy
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a commit to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
commit 5528ff16b0ee87b2a029282bf4f08a8e1fed2b77
Author: Ming Wen <mo...@gmail.com>
AuthorDate: Mon Jun 22 11:34:49 2026 +0800
chore(seo): noindex the auxiliary Netlify deploy
Production (apisix.apache.org) is served by Apache infra + Fastly and does not
read netlify.toml. apache-apisix.netlify.app is a mirror that should not
compete with production in search results; add X-Robots-Tag: noindex.
---
netlify.toml | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/netlify.toml b/netlify.toml
new file mode 100644
index 00000000000..6ea98ed6b60
--- /dev/null
+++ b/netlify.toml
@@ -0,0 +1,13 @@
+# The production site (https://apisix.apache.org) is served by Apache
+# infrastructure (Apache httpd + Fastly) and does NOT read this file.
+#
+# This config exists only to keep the auxiliary Netlify deploy
+# (apache-apisix.netlify.app and PR deploy previews) OUT of search indexes, so
+# they don't compete with the canonical production site for rankings. Netlify
+# applies these headers to every deploy it builds from this repo; Apache infra
+# ignores the file entirely.
+[[headers]]
+ for = "/*"
+
+ [headers.values]
+ X-Robots-Tag = "noindex"
(apisix-website) 03/05: feat(seo): add SoftwareApplication and FAQPage structured data to homepage
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a commit to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
commit c8f7c7f746dc32fe4e44b79a0b7ce4e52b33601d
Author: Ming Wen <mo...@gmail.com>
AuthorDate: Mon Jun 22 11:34:49 2026 +0800
feat(seo): add SoftwareApplication and FAQPage structured data to homepage
---
website/src/pages/index.tsx | 64 +++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 64 insertions(+)
diff --git a/website/src/pages/index.tsx b/website/src/pages/index.tsx
index 97212bb9bdd..a57c738c3c3 100644
--- a/website/src/pages/index.tsx
+++ b/website/src/pages/index.tsx
@@ -14,6 +14,68 @@ import Comparison from '../components/sections/Comparison';
import OpensourcePromo from '../components/sections/OpensourcePromo';
import EndCTA from '../components/sections/Endcta';
+// Structured data for the homepage. Organization + WebSite are already injected
+// globally by config/schema-org.js; these add product-level (SoftwareApplication)
+// and FAQ markup to improve rich results and AI-answer eligibility.
+const SOFTWARE_APPLICATION_SCHEMA = {
+ '@context': 'https://schema.org',
+ '@type': 'SoftwareApplication',
+ name: 'Apache APISIX',
+ applicationCategory: 'DeveloperApplication',
+ applicationSubCategory: 'API Gateway',
+ operatingSystem: 'Linux, Docker, Kubernetes',
+ description:
+ 'Apache APISIX is a dynamic, high-performance, open-source API gateway and AI gateway with load balancing, authentication, rate limiting, observability, and 100+ plugins.',
+ url: 'https://apisix.apache.org/',
+ license: 'https://www.apache.org/licenses/LICENSE-2.0',
+ isAccessibleForFree: true,
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
+ author: {
+ '@type': 'Organization',
+ name: 'The Apache Software Foundation',
+ url: 'https://www.apache.org/',
+ },
+};
+
+const HOMEPAGE_FAQ_SCHEMA = {
+ '@context': 'https://schema.org',
+ '@type': 'FAQPage',
+ mainEntity: [
+ {
+ '@type': 'Question',
+ name: 'What is Apache APISIX?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'Apache APISIX is an open-source, high-performance API gateway and AI gateway. It is a top-level project of the Apache Software Foundation and provides load balancing, authentication, rate limiting, observability, and 100+ plugins for managing API and LLM traffic at scale.',
+ },
+ },
+ {
+ '@type': 'Question',
+ name: 'Is Apache APISIX free and open source?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'Yes. Apache APISIX is licensed under the Apache License 2.0 and is completely free and open source, with no open-core paywall — all plugins and features are available in the open-source project.',
+ },
+ },
+ {
+ '@type': 'Question',
+ name: 'What is the difference between an API gateway and an AI gateway?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'An API gateway manages traffic for general APIs, while an AI gateway adds capabilities optimized for LLM workloads such as multi-provider AI proxying, LLM load balancing, token-based rate limiting, retries and fallback, and prompt security. Apache APISIX provides both.',
+ },
+ },
+ {
+ '@type': 'Question',
+ name: 'Does Apache APISIX support Kubernetes?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'Yes. Apache APISIX runs on Kubernetes and provides an Ingress Controller, along with Helm charts and a Docker image for cloud-native deployments.',
+ },
+ },
+ ],
+};
+
const ThemeResetComponent = () => {
const { isDarkTheme, setLightTheme } = useThemeContext();
const windowType = useWindowType();
@@ -70,6 +132,8 @@ const Index: FC = () => (
name="twitter:description"
content="Apache APISIX is a dynamic, high-performance, open-source API gateway and AI gateway. Features include load balancing, authentication, rate limiting, AI proxying, LLM load balancing, and 100+ plugins."
/>
+ <script type="application/ld+json">{JSON.stringify(SOFTWARE_APPLICATION_SCHEMA)}</script>
+ <script type="application/ld+json">{JSON.stringify(HOMEPAGE_FAQ_SCHEMA)}</script>
</Head>
<HeroSection />
<Architecture />
(apisix-website) 01/05: fix(seo): remove redundant hreflang plugin
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a commit to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
commit 4b7c95423eb5676f93541a7b4d3183506efcf85e
Author: Ming Wen <mo...@gmail.com>
AuthorDate: Mon Jun 22 11:34:49 2026 +0800
fix(seo): remove redundant hreflang plugin
Docusaurus already emits canonical and hreflang alternate links natively
(via react-helmet) on every page. The custom postBuild plugin in
config/hreflang.js (loaded only by the website/ instance) merely re-added a
second, duplicate set of hreflang tags. Remove it to keep one source of truth.
---
config/hreflang.js | 82 --------------------------------------------
website/docusaurus.config.js | 1 -
2 files changed, 83 deletions(-)
diff --git a/config/hreflang.js b/config/hreflang.js
deleted file mode 100644
index a0ef7d88dd0..00000000000
--- a/config/hreflang.js
+++ /dev/null
@@ -1,82 +0,0 @@
-const SITE_URL = 'https://apisix.apache.org';
-
-/**
- * Docusaurus plugin that injects hreflang <link> tags and canonical URLs
- * into every HTML page during the post-build phase.
- *
- * For each page, it generates:
- * <link rel="alternate" hreflang="en" href="https://apisix.apache.org/..." />
- * <link rel="alternate" hreflang="zh" href="https://apisix.apache.org/zh/..." />
- * <link rel="alternate" hreflang="x-default" href="https://apisix.apache.org/..." />
- * <link rel="canonical" href="..." /> (if not already present)
- */
-module.exports = function hreflangPlugin() {
- return {
- name: 'hreflang',
-
- async postBuild({ outDir }) {
- const fs = require('fs');
- const path = require('path');
-
- function findHtmlFiles(dir) {
- const results = [];
- const entries = fs.readdirSync(dir, { withFileTypes: true });
- for (const entry of entries) {
- const fullPath = path.join(dir, entry.name);
- if (entry.isDirectory()) {
- results.push(...findHtmlFiles(fullPath));
- } else if (entry.name.endsWith('.html')) {
- results.push(fullPath);
- }
- }
- return results;
- }
-
- const htmlFiles = findHtmlFiles(outDir);
-
- for (const filePath of htmlFiles) {
- let html = fs.readFileSync(filePath, 'utf-8');
-
- // Determine relative path from outDir
- const relativePath = path.relative(outDir, filePath);
-
- // Determine the current locale based on file path
- const isZh = relativePath.startsWith('zh' + path.sep);
-
- // Compute the path without locale prefix
- const pathWithoutLocale = isZh
- ? relativePath.slice(3) // remove "zh/"
- : relativePath;
-
- // Normalize path separators for URL
- const urlPath = pathWithoutLocale.split(path.sep).join('/');
-
- // Build URLs
- const enUrl = `${SITE_URL}/${urlPath}`.replace(/\/index\.html$/, '/');
- const zhUrl = `${SITE_URL}/zh/${urlPath}`.replace(/\/index\.html$/, '/');
- const currentUrl = isZh ? zhUrl : enUrl;
-
- // Build hreflang tags
- const hreflangTags = [
- `<link rel="alternate" hreflang="en" href="${enUrl}" />`,
- `<link rel="alternate" hreflang="zh" href="${zhUrl}" />`,
- `<link rel="alternate" hreflang="x-default" href="${enUrl}" />`,
- ].join('\n ');
-
- // Add canonical tag if not already present
- const hasCanonical = html.includes('rel="canonical"');
- const canonicalTag = hasCanonical
- ? ''
- : `<link rel="canonical" href="${currentUrl}" />`;
-
- // Inject before </head>
- const injection = [hreflangTags, canonicalTag]
- .filter(Boolean)
- .join('\n ');
- html = html.replace('</head>', ` ${injection}\n </head>`);
-
- fs.writeFileSync(filePath, html, 'utf-8');
- }
- },
- };
-};
diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js
index 0cb370dfac7..ec15903c283 100644
--- a/website/docusaurus.config.js
+++ b/website/docusaurus.config.js
@@ -109,7 +109,6 @@ module.exports = {
],
['docusaurus-plugin-sass', {}],
require.resolve('../config/schema-org'),
- require.resolve('../config/hreflang'),
],
themeConfig: {
navbar: {
(apisix-website) 02/05: feat(seo): enrich Plugin Hub metadata and add catalog structured data
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a commit to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
commit 1001edab1acb88fa3fdbfb6f3ecfba01a31d5114
Author: Ming Wen <mo...@gmail.com>
AuthorDate: Mon Jun 22 11:34:49 2026 +0800
feat(seo): enrich Plugin Hub metadata and add catalog structured data
- Title: 'Plugin Hub' -> 'Plugin Hub: 100+ API Gateway & AI Plugins'
- Fix stale plugin count in description (80+ -> 100+; actual is 105)
- Add CollectionPage + ItemList JSON-LD enumerating all plugins
- Add FAQPage JSON-LD for rich results / AI answers
---
website/src/pages/plugins.tsx | 65 +++++++++++++++++++++++++++++++++++++++++--
1 file changed, 62 insertions(+), 3 deletions(-)
diff --git a/website/src/pages/plugins.tsx b/website/src/pages/plugins.tsx
index 0b64fc95805..74d30760c1b 100644
--- a/website/src/pages/plugins.tsx
+++ b/website/src/pages/plugins.tsx
@@ -233,12 +233,71 @@ const Plugins: FC = () => {
);
});
+ // Structured data for the plugin catalog: a CollectionPage whose ItemList
+ // enumerates every plugin, plus an FAQPage to surface in rich results / AI answers.
+ const allPlugins = plugins.flatMap((section) => section.plugins);
+ const collectionSchema = {
+ '@context': 'https://schema.org',
+ '@type': 'CollectionPage',
+ name: 'Apache APISIX Plugin Hub',
+ description:
+ 'Browse 100+ Apache APISIX plugins for authentication, security, traffic control, observability, serverless, and AI.',
+ url: 'https://apisix.apache.org/plugins/',
+ isPartOf: { '@type': 'WebSite', name: 'Apache APISIX', url: 'https://apisix.apache.org' },
+ mainEntity: {
+ '@type': 'ItemList',
+ numberOfItems: allPlugins.length,
+ itemListElement: allPlugins.map((plugin, index) => {
+ const slug = plugin.name.indexOf('serverless') !== -1 ? 'serverless' : plugin.name;
+ const basePath = plugin.beta ? 'next/plugins' : 'plugins';
+ return {
+ '@type': 'ListItem',
+ position: index + 1,
+ name: plugin.name,
+ url: `https://apisix.apache.org/docs/apisix/${basePath}/${slug}`,
+ };
+ }),
+ },
+ };
+ const faqSchema = {
+ '@context': 'https://schema.org',
+ '@type': 'FAQPage',
+ mainEntity: [
+ {
+ '@type': 'Question',
+ name: 'How many plugins does Apache APISIX have?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'Apache APISIX ships with 100+ plugins covering authentication, security, traffic control, observability, serverless, and AI gateway use cases, all available in the open-source project.',
+ },
+ },
+ {
+ '@type': 'Question',
+ name: 'What can Apache APISIX plugins do?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'APISIX plugins extend the gateway with capabilities such as key, JWT and OpenID Connect authentication, rate limiting, CORS, request and response transformation, Prometheus and OpenTelemetry observability, and AI proxying for LLM providers.',
+ },
+ },
+ {
+ '@type': 'Question',
+ name: 'Can I write custom plugins for Apache APISIX?',
+ acceptedAnswer: {
+ '@type': 'Answer',
+ text: 'Yes. You can write custom plugins in Lua, or use the Java, Go, and Python plugin runners and Wasm to develop plugins in other languages.',
+ },
+ },
+ ],
+ };
+
return (
- <Layout title={translate({ message: 'Plugin Hub' })}>
+ <Layout title={translate({ id: 'plugins.meta.title', message: 'Plugin Hub: 100+ API Gateway & AI Plugins' })}>
<Head>
- <meta name="description" content={translate({ id: 'plugins.meta.description', message: 'Explore 80+ Apache APISIX plugins for authentication, security, traffic control, observability, and AI. Powerful integrations for your API Gateway.' })} />
- <meta property="og:description" content={translate({ id: 'plugins.meta.ogDescription', message: 'Explore 80+ Apache APISIX plugins for authentication, security, traffic control, observability, and AI.' })} />
+ <meta name="description" content={translate({ id: 'plugins.meta.description', message: 'Explore 100+ Apache APISIX plugins for authentication, security, traffic control, observability, and AI. Powerful integrations for your API Gateway.' })} />
+ <meta property="og:description" content={translate({ id: 'plugins.meta.ogDescription', message: 'Explore 100+ Apache APISIX plugins for authentication, security, traffic control, observability, and AI.' })} />
<script src="/js/plugin-icon.js" defer />
+ <script type="application/ld+json">{JSON.stringify(collectionSchema)}</script>
+ <script type="application/ld+json">{JSON.stringify(faqSchema)}</script>
</Head>
<Page>
<PageTitle>
(apisix-website) 04/05: feat(seo): add an H1 heading to the blog list page
Posted by we...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
moonming pushed a commit to branch feat/seo-technical-fixes
in repository https://gitbox.apache.org/repos/asf/apisix-website.git
commit 49ba121b261c117f3aafab870b6718f5fb3a4c04
Author: Ming Wen <mo...@gmail.com>
AuthorDate: Mon Jun 22 11:34:49 2026 +0800
feat(seo): add an H1 heading to the blog list page
The default Docusaurus blog index renders no H1, an on-page SEO gap.
---
blog/src/theme/BlogListPage/index.tsx | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/blog/src/theme/BlogListPage/index.tsx b/blog/src/theme/BlogListPage/index.tsx
index 531ae9cf479..6b850461ec1 100644
--- a/blog/src/theme/BlogListPage/index.tsx
+++ b/blog/src/theme/BlogListPage/index.tsx
@@ -22,6 +22,9 @@ const BlogListPage: FC<Props> = (props) => {
const { blogDescription, blogTitle, permalink } = metadata;
const isBlogOnlyMode = permalink === '/';
const title = isBlogOnlyMode ? siteTitle : blogTitle;
+ // Visible H1 for the blog list page. The default Docusaurus blog index ships
+ // without one, which is an on-page SEO gap (every indexable page needs an H1).
+ const headingTitle = isBlogOnlyMode ? siteTitle : `${siteTitle} ${blogTitle}`;
return (
<BlogLayout
@@ -34,6 +37,7 @@ const BlogListPage: FC<Props> = (props) => {
sidebar={sidebar}
toc={false}
>
+ <h1 className="margin-bottom--lg">{headingTitle}</h1>
<BlogPosts
itemType="http://schema.org/Blog"
items={items}