This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-website.git
The following commit(s) were added to refs/heads/main by this push:
new 32b61f87 CAMEL-23788: Generate versioned offline documentation bundles
(#1667)
32b61f87 is described below
commit 32b61f8795d98046e52f569d707e803a1b3d5cfe
Author: Claus Ibsen <[email protected]>
AuthorDate: Thu Jun 18 13:48:07 2026 +0200
CAMEL-23788: Generate versioned offline documentation bundles (#1667)
* CAMEL-23788: Generate versioned offline documentation bundles
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23788: drop camel-spring-boot from offline bundle
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23788: drop kamelets from offline bundle, keep pure core camel
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23788: use connectors/components wording for AI clarity
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23788: include Camel Catalog and YAML DSL schema in offline bundle
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* CAMEL-23788: document zip directory structure in llms.txt for AI agents
Co-Authored-By: Claude Opus 4.6 <[email protected]>
* chore: update llms.txt with camel-a2a component link and description
Co-Authored-By: Claude Opus 4.6 <[email protected]>
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>
---
.github/workflows/offline-bundle.yml | 69 +++++++++++++++
llms-txt-template.md | 26 +++++-
scripts/generate-offline-bundle.js | 158 +++++++++++++++++++++++++++++++++++
3 files changed, 252 insertions(+), 1 deletion(-)
diff --git a/.github/workflows/offline-bundle.yml
b/.github/workflows/offline-bundle.yml
new file mode 100644
index 00000000..c2c9206d
--- /dev/null
+++ b/.github/workflows/offline-bundle.yml
@@ -0,0 +1,69 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Generate Offline Documentation Bundle
+
+on:
+ workflow_dispatch:
+ inputs:
+ camel_version:
+ description: 'Camel version to bundle (e.g. 4.18)'
+ required: true
+ type: string
+
+jobs:
+ generate-bundle:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v5
+
+ - name: Install dependencies
+ run: yarn workspaces foreach --all install
+
+ - name: Build site
+ run: yarn build
+ env:
+ CAMEL_ENV: production
+ HUGO_OPTIONS: --buildFuture
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+ - name: Generate versioned bundle
+ run: node scripts/generate-offline-bundle.js ${{ inputs.camel_version
}}
+
+ - name: Create or update GitHub Release
+ run: |
+ TAG="docs-${{ inputs.camel_version }}"
+ FILE="public/camel-docs-${{ inputs.camel_version }}.zip"
+ TITLE="Apache Camel ${{ inputs.camel_version }} — Offline
Documentation"
+ NOTES="Offline documentation bundle for Apache Camel ${{
inputs.camel_version }}.
+
+ Contains 350+ connector/component docs (Markdown), the user manual,
the Camel Catalog (JSON metadata for all connectors/components, data formats,
languages, and EIPs), and the YAML DSL canonical JSON Schema.
+
+ Download and unzip locally for AI coding agents or environments with
restricted internet access."
+
+ # delete existing release if present so we can recreate it
+ gh release delete "$TAG" --yes 2>/dev/null || true
+
+ gh release create "$TAG" "$FILE" \
+ --title "$TITLE" \
+ --notes "$NOTES" \
+ --latest=false
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/llms-txt-template.md b/llms-txt-template.md
index badf76d9..98dd3929 100644
--- a/llms-txt-template.md
+++ b/llms-txt-template.md
@@ -7,6 +7,30 @@ For example:
- HTML:
`https://camel.apache.org/components/next/languages/simple-language.html`
- Markdown:
`https://camel.apache.org/components/next/languages/simple-language.md`
+## Offline documentation bundles
+
+For agents or environments with no or restricted internet access, versioned
offline documentation bundles are available as zip archives of all Markdown
files:
+- [Camel
4.18](https://github.com/apache/camel-website/releases/download/docs-4.18/camel-docs-4.18.zip)
+- [Camel
4.14](https://github.com/apache/camel-website/releases/download/docs-4.14/camel-docs-4.14.zip)
+
+Download the zip matching your Camel version, unzip it locally, and read the
files from there. Each bundle contains:
+
+```
+components/<version>/ — 350+ connector/component docs (Markdown)
+manual/ — user manual (Markdown)
+catalog/
+ components/ — 350+ connector/component metadata (JSON)
+ dataformats/ — data format metadata (JSON)
+ languages/ — expression language metadata (JSON)
+ models/ — EIP model metadata (JSON)
+ others/ — other component metadata (JSON)
+ schema/
+ camelYamlDsl-canonical.json — YAML DSL JSON Schema
+llms.txt — this file
+```
+
+The `catalog/` JSON files contain machine-readable metadata for every
connector/component, data format, language, and EIP — parameters, types,
defaults, and descriptions. The YAML DSL schema is the definitive spec for
validating and generating Camel YAML routes.
+
## Key facts
- Apache Camel is a **library**, not a platform — it embeds in your existing
Spring Boot or Quarkus application
@@ -57,7 +81,7 @@ For example:
- [Camel MCP Server](https://camel.apache.org/manual/camel-jbang-mcp.md):
Model Context Protocol server for AI coding assistants (Claude Code, GitHub
Copilot, Cursor, Gemini CLI).
- [Camel
LangChain4j](https://camel.apache.org/components/next/langchain4j-chat-component.md):
LLM integration via LangChain4j.
- [Camel
OpenAI](https://camel.apache.org/components/next/openai-component.md): Native
OpenAI component.
-- A2A (Agent-to-Agent): Camel supports the A2A protocol for connecting AI
agents to enterprise systems.
+- [Camel A2A](https://camel.apache.org/components/next/a2a-component.md):
Agent-to-Agent (A2A) protocol component — expose Camel routes as A2A agents or
call remote A2A agents. Supports HTTP+JSON and JSONRPC bindings,
OAuth/OIDC/API-key auth, and SSE streaming.
## Tooling
diff --git a/scripts/generate-offline-bundle.js
b/scripts/generate-offline-bundle.js
new file mode 100644
index 00000000..7de6cefe
--- /dev/null
+++ b/scripts/generate-offline-bundle.js
@@ -0,0 +1,158 @@
+const fs = require('fs');
+const path = require('path');
+const { execFileSync } = require('child_process');
+
+const PUBLIC_DIR = 'public';
+const CAMEL_REPO = 'apache/camel';
+const CATALOG_BASE =
'catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog';
+const YAML_SCHEMA_PATH =
'dsl/camel-yaml-dsl/camel-yaml-dsl/src/generated/resources/schema/camelYamlDsl-canonical.json';
+
+const CATALOG_DIRS = ['components', 'dataformats', 'languages', 'models',
'others'];
+
+const VERSION_DIRS = [
+ 'components'
+];
+
+const SHARED_DIRS = [
+ 'manual'
+];
+
+function fetchCatalogAndSchema(version) {
+ const branch = `camel-${version}.x`;
+ const catalogDir = path.join(PUBLIC_DIR, 'catalog');
+
+ console.log(`\nFetching catalog and YAML DSL schema from
${CAMEL_REPO}@${branch}...`);
+
+ // fetch YAML DSL canonical schema
+ const schemaDir = path.join(catalogDir, 'schema');
+ fs.mkdirSync(schemaDir, { recursive: true });
+ try {
+ const schema = execFileSync('gh', [
+ 'api', `repos/${CAMEL_REPO}/contents/${YAML_SCHEMA_PATH}?ref=${branch}`,
+ '--jq', '.content'
+ ], { encoding: 'utf8' });
+ fs.writeFileSync(
+ path.join(schemaDir, 'camelYamlDsl-canonical.json'),
+ Buffer.from(schema.trim(), 'base64').toString('utf8')
+ );
+ console.log(' Fetched schema/camelYamlDsl-canonical.json');
+ } catch (error) {
+ console.warn(` Could not fetch YAML DSL schema: ${error.message}`);
+ }
+
+ // fetch catalog JSON files for each category
+ for (const dir of CATALOG_DIRS) {
+ const targetDir = path.join(catalogDir, dir);
+ fs.mkdirSync(targetDir, { recursive: true });
+ try {
+ const files = execFileSync('gh', [
+ 'api',
`repos/${CAMEL_REPO}/contents/${CATALOG_BASE}/${dir}?ref=${branch}`,
+ '--jq', '.[].name'
+ ], { encoding: 'utf8' }).trim().split('\n').filter(f =>
f.endsWith('.json'));
+
+ console.log(` Fetching catalog/${dir}/ (${files.length} files)...`);
+
+ for (const file of files) {
+ try {
+ const content = execFileSync('gh', [
+ 'api',
`repos/${CAMEL_REPO}/contents/${CATALOG_BASE}/${dir}/${file}?ref=${branch}`,
+ '--jq', '.content'
+ ], { encoding: 'utf8' });
+ fs.writeFileSync(
+ path.join(targetDir, file),
+ Buffer.from(content.trim(), 'base64').toString('utf8')
+ );
+ } catch {
+ // skip individual file failures silently
+ }
+ }
+ } catch (error) {
+ console.warn(` Could not fetch catalog/${dir}: ${error.message}`);
+ }
+ }
+
+ return fs.existsSync(catalogDir);
+}
+
+function main() {
+ const version = process.argv[2];
+ if (!version) {
+ console.error('Usage: node scripts/generate-offline-bundle.js <version>');
+ console.error('Example: node scripts/generate-offline-bundle.js 4.18');
+ process.exit(1);
+ }
+
+ const versionDir = `${version}.x`;
+ const bundleName = `camel-docs-${version}.zip`;
+ const bundlePath = path.join(PUBLIC_DIR, bundleName);
+
+ if (!fs.existsSync(PUBLIC_DIR)) {
+ console.error(`Cannot generate ${bundleName}: '${PUBLIC_DIR}' directory
not found`);
+ process.exit(1);
+ }
+
+ // collect paths to include (relative to public/)
+ const includePaths = [];
+
+ for (const dir of VERSION_DIRS) {
+ const fullPath = path.join(PUBLIC_DIR, dir, versionDir);
+ if (fs.existsSync(fullPath)) {
+ includePaths.push(`${dir}/${versionDir}/*`);
+ console.log(` Including ${dir}/${versionDir}/`);
+ } else {
+ console.warn(` Skipping ${dir}/${versionDir}/ (not found)`);
+ }
+ }
+
+ for (const dir of SHARED_DIRS) {
+ const fullPath = path.join(PUBLIC_DIR, dir);
+ if (fs.existsSync(fullPath)) {
+ includePaths.push(`${dir}/*`);
+ console.log(` Including ${dir}/`);
+ }
+ }
+
+ if (includePaths.length === 0) {
+ console.error(`No documentation directories found for version ${version}`);
+ process.exit(1);
+ }
+
+ // always include llms.txt if present
+ if (fs.existsSync(path.join(PUBLIC_DIR, 'llms.txt'))) {
+ includePaths.push('llms.txt');
+ }
+
+ // fetch catalog and YAML DSL schema from the camel repo
+ if (fetchCatalogAndSchema(version)) {
+ includePaths.push('catalog/*');
+ }
+
+ // remove stale bundle
+ if (fs.existsSync(bundlePath)) {
+ fs.unlinkSync(bundlePath);
+ }
+
+ // build zip: include .md files from doc dirs, plus .json from catalog, plus
llms.txt
+ const zipArgs = ['-r', '-q', bundleName, '.'];
+ for (const p of includePaths) {
+ if (p === 'llms.txt') {
+ zipArgs.push('-i', 'llms.txt');
+ } else if (p.startsWith('catalog/')) {
+ zipArgs.push('-i', `${p}.json`);
+ } else {
+ zipArgs.push('-i', `${p}.md`);
+ }
+ }
+
+ try {
+ execFileSync('zip', zipArgs, { cwd: PUBLIC_DIR, stdio: 'inherit' });
+
+ const sizeMb = (fs.statSync(bundlePath).size / (1024 * 1024)).toFixed(1);
+ console.log(`\nGenerated ${bundleName} (${sizeMb} MB)`);
+ } catch (error) {
+ console.error(`Failed to generate ${bundleName}:`, error.message);
+ process.exit(1);
+ }
+}
+
+main();