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-jbang-examples.git


The following commit(s) were added to refs/heads/main by this push:
     new fb6f31c  CAMEL-24808: cleanup after the ladder: quick-start on the 
ladder, off-shape READMEs reshaped, two bugs in the docling example (#93)
fb6f31c is described below

commit fb6f31cbaa40e9f928be54835efc4ca6620cc91d
Author: Claus Ibsen <[email protected]>
AuthorDate: Mon Sep 28 07:20:54 2026 +0200

    CAMEL-24808: cleanup after the ladder: quick-start on the ladder, off-shape 
READMEs reshaped, two bugs in the docling example (#93)
    
    - The empty "Install Camel CLI" heading in 29 READMEs, a comment pointing 
at install.adoc, is now a one-line link to the root README; install.adoc is 
gone.
    - generate-catalog.sh: the group READMEs only promise a test where every 
example has one; the Needs column takes a free-text "needs" from metadata.json 
instead of mapping ciSkip to "a local model". PII redaction needs an 
OpenAI-compatible API, docling a local model; both are ciSkip.
    - AGENTS.md describes the ladder instead of the old flat layout, the README 
shape, and the checklist with generate-catalog.sh; CI runs Temurin 21.
    - quick-start: the four examples get the ladder-shaped README, a Citrus 
test each, and a place in the CI matrix; routes/ calls a plain POJO bean 
instead of a Processor.
    - camel-1-tribute, keycloak-security-rest, openai-pii-redaction and 
docling-langchain4j-rag READMEs reshaped; the PII one had output pasted in from 
the Watson example, its systemMessage is a folded block so camel validate is 
clean.
    - docling-langchain4j-rag: the chatModel bean, dropped by 60a70d8, is back 
so the example starts again; the batch timer gets a period instead of firing 
every second; documents/ and output/ are ignored.
    
    Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
---
 .github/workflows/build.yml                        |   8 +
 .gitignore                                         |   3 +
 AGENTS.md                                          |  48 +-
 README.md                                          |   6 +-
 ai/README.md                                       |   6 +-
 ai/docling-langchain4j-rag/README.md               | 642 +++------------------
 ai/docling-langchain4j-rag/application.properties  |   3 +-
 .../docling-langchain4j-rag.yaml                   |  17 +-
 ai/docling-langchain4j-rag/metadata.json           |   6 +-
 ai/langchain4j-chat/README.md                      |   3 +-
 ai/langchain4j-chat/metadata.json                  |   3 +-
 ai/mcp-server/README.md                            |   3 +-
 ai/openai-pii-redaction/README.md                  | 110 ++--
 ai/openai-pii-redaction/metadata.json              |   4 +-
 ai/openai-pii-redaction/pii-redaction.camel.yaml   |  11 +-
 camel-jbang-example-catalog.json                   |  18 +-
 cloud/README.md                                    |   2 +-
 cloud/aws-sqs/README.md                            |   3 +-
 connect-service/README.md                          |   2 +-
 connect-service/artemis/README.md                  |   3 +-
 connect-service/camel-1-tribute/README.md          | 125 ++--
 connect-service/ftp/README.md                      |   3 +-
 connect-service/kafka-orders/README.md             |   3 +-
 connect-service/mqtt/README.md                     |   3 +-
 connect-service/sql/README.md                      |   3 +-
 connect/README.md                                  |   2 +-
 connect/file-processing/README.md                  |   3 +-
 connect/http-client/README.md                      |   3 +-
 connect/stock-api/README.md                        |   3 +-
 contracts/README.md                                |   2 +-
 contracts/keycloak-security-rest/README.md         | 392 +++----------
 contracts/openapi-client/README.md                 |   3 +-
 contracts/openapi-server/README.md                 |   3 +-
 fail-well/README.md                                |   2 +-
 fail-well/circuit-breaker/README.md                |   3 +-
 fail-well/error-handling/README.md                 |   3 +-
 generate-catalog.sh                                |  12 +-
 install.adoc                                       |  24 -
 quick-start/README.md                              |   2 +-
 quick-start/rest-api/README.md                     |  75 ++-
 quick-start/rest-api/application.properties        |  17 +
 quick-start/rest-api/test/rest-api.citrus.it.yaml  |  40 ++
 quick-start/routes/Greeter.java                    |  40 +-
 quick-start/routes/README.md                       |  85 +--
 quick-start/routes/application.properties          |  23 +-
 quick-start/routes/beans.yaml                      |   8 +-
 quick-start/routes/routes.camel.yaml               |  12 +-
 quick-start/routes/test/routes.citrus.it.yaml      |  19 +
 quick-start/splitter/README.md                     |  74 ++-
 quick-start/splitter/test/splitter.citrus.it.yaml  |  19 +
 quick-start/timer-log/README.md                    |  70 ++-
 quick-start/timer-log/application.properties       |  17 +
 .../timer-log/test/timer-log.citrus.it.yaml        |  16 +
 route/README.md                                    |   2 +-
 route/aggregator/README.md                         |   3 +-
 route/content-based-router/README.md               |   3 +-
 route/filter-and-multicast/README.md               |   3 +-
 route/order-lines/README.md                        |   3 +-
 run/README.md                                      |   2 +-
 run/nightly-report/README.md                       |   3 +-
 run/order-generator/README.md                      |   3 +-
 run/properties-and-profiles/README.md              |   3 +-
 showcase/README.md                                 |   2 +-
 transform/README.md                                |   2 +-
 transform/csv-to-json/README.md                    |   3 +-
 transform/data-mapping/README.md                   |   3 +-
 transform/groovy/README.md                         |   3 +-
 transform/json-transform/README.md                 |   3 +-
 transform/xml-to-json/README.md                    |   3 +-
 transform/xslt/README.md                           |   3 +-
 70 files changed, 904 insertions(+), 1153 deletions(-)

diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 37bea03..05cc0cd 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -28,6 +28,14 @@ jobs:
     strategy:
       matrix:
         include:
+          - name: Timer log
+            path: quick-start/timer-log
+          - name: Routes
+            path: quick-start/routes
+          - name: Splitter
+            path: quick-start/splitter
+          - name: REST API
+            path: quick-start/rest-api
           - name: SQL database
             path: connect-service/sql
           - name: MQTT sensors
diff --git a/.gitignore b/.gitignore
index aaa583b..8bb9c74 100644
--- a/.gitignore
+++ b/.gitignore
@@ -13,3 +13,6 @@ parked/
 # written by the file-processing example at runtime
 inbox/
 archive/
+# written by the docling-langchain4j-rag example at runtime
+documents/
+output/
diff --git a/AGENTS.md b/AGENTS.md
index 4856b83..38aae00 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -15,7 +15,7 @@ essentials and adds what is specific to this examples 
repository.
 ## Project Info
 
 - Run with: Camel CLI (`jbang app install camel@apache/camel`) + JBang
-- Java: 17+ (CI uses Temurin 17)
+- Java: 17+ (CI uses Temurin 21)
 - Tests: [Citrus](https://citrusframework.org/) YAML tests
 - JIRA project: `CAMEL` (https://issues.apache.org/jira/projects/CAMEL)
 - Merge strategy (`.asf.yaml`): squash or rebase; protected `main`
@@ -38,11 +38,23 @@ essentials and adds what is specific to this examples 
repository.
 
 ## Repository structure
 
-- One example per top-level directory, lowercase and hyphenated
-  (e.g. `mqtt/`, `timer-log/`, `ftp/`). Related examples may be grouped under a
-  category directory (e.g. `aws/aws-sqs/`, `openapi/server/`).
+The examples form a ladder: one directory per group, one directory per example
+inside it, both lowercase and hyphenated (e.g. `route/aggregator/`,
+`connect-service/mqtt/`). The groups, in reading order, are `quick-start`, then
+the rungs `run`, `transform`, `route`, `fail-well`, `connect`, 
`connect-service`,
+`contracts`, `ai`, `cloud`, and `showcase` for tooling demos outside the 
ladder.
+The `README.md` at the root explains the ladder; `generate-catalog.sh` holds 
the
+group order and intros.
+
+- From the `run` rung onwards the examples share one fictional web shop and the
+  order shape that `run/order-generator` defines; a new example on the ladder
+  reuses that story and that JSON rather than inventing its own domain.
 - Each example carries a `metadata.json` that feeds the generated
-  `camel-jbang-example-catalog.json`. Do not hand-edit the catalog.
+  `camel-jbang-example-catalog.json` and the example tables in the root and 
group
+  READMEs. Do not hand-edit the catalog or those tables; run
+  `./generate-catalog.sh` after adding or changing a `metadata.json`.
+- `security/`, `transformation/` and the non-ladder examples in `cloud/` are
+  larger reference examples marked `"exclude": true`; they are not on the 
ladder.
 
 ## Anatomy of an example
 
@@ -51,10 +63,10 @@ essentials and adds what is specific to this examples 
repository.
 | `README.md` | What it does, how to run, expected output, how to test |
 | `<name>.camel.yaml` | The route(s) in Camel YAML DSL |
 | `application.properties` | Runtime properties (ASF license header required) |
-| `metadata.json` | Catalog entry: `name`, `title`, `description` (the 
behaviour you observe when it runs), `order` (its place in the group, the 
reading order the group page and the listings use), `level` (the group: 
`quick-start`, then the ladder rungs `run`, `transform`, `route`, `fail-well`, 
`connect`, `connect-service`, `contracts`, `ai`, `cloud`, or `showcase` for 
tooling demos), `teaches` (the `components`, `eips`, `languages` and 
`dataformats` it introduces), `tags`, `infraService [...]
+| `metadata.json` | Catalog entry: `title`, `description` (the behaviour you 
observe when it runs), `level` (the group), `order` (its place in the group, 
the reading order the group page and the listings use), `teaches` (the 
`components`, `eips`, `languages` and `dataformats` it introduces), `tags`, 
`infraServices` (what `camel infra run` must start), `needs` (anything else the 
*Needs* column should say, e.g. `a local model`), `ciSkip` (the test cannot run 
in CI) |
 | `compose.yaml` | Optional Docker Compose for required infra |
 | `beans.yaml` / `*.java` | Optional beans/processors (package 
`camel.example.*`) |
-| `test/<name>.citrus.it.yaml` | Optional Citrus integration test |
+| `test/<name>.citrus.it.yaml` | The Citrus integration test, run by CI |
 
 ## Build, run and validate
 
@@ -91,19 +103,27 @@ example. If your example ships a `test/`, add it to that 
workflow.
   `log: "..."`, `- simple:` in a `when` item) is deprecated and `camel run` 
warns
   about it. Check with `camel validate yaml --canonical <file>` (Camel 4.23+);
   `camel validate normalize` rewrites a file but drops its comments.
-- **README**: follow the existing examples — title, description, install CLI,
-  start infra, how to run, stop/cleanup, integration testing, community footer.
+- **README**: follow the existing examples, `run/order-generator/README.md` is
+  the reference. Title and a two-line description, then these sections in this
+  order: *What you will see* (the literal log output), *Install Camel CLI* (the
+  one-line link to the root README), *Run it* (including how to start the
+  service, if any, and how to stop), *How it works* (one bullet per file),
+  *Build it step by step* (numbered prompts a reader or an assistant can 
follow,
+  running after each), *Try changing*, *Integration testing*, and the
+  *Help and contributions* footer.
 
 ## Adding a new example (checklist)
 
-1. Create `<name>/` (or `<category>/<name>/`).
+1. Pick the group (rung) it belongs to and create `<group>/<name>/`.
 2. Add `README.md`, `<name>.camel.yaml`, `application.properties` (with 
header),
-   and a correct `metadata.json`.
-3. Add `compose.yaml` if infra is required; add `test/` Citrus tests where it
-   makes sense and wire them into `.github/workflows/build.yml`.
+   and a `metadata.json` with `level`, `order` and `teaches`.
+3. Add `test/<name>.citrus.it.yaml` and wire it into
+   `.github/workflows/build.yml`; the test starts the route, and the service if
+   it needs one, itself. Set `ciSkip` only when the test truly cannot run in 
CI.
 4. Run it locally with `camel run` and verify the README's expected output;
    `camel validate yaml --canonical` must report nothing.
-5. Open the PR from your fork, link the JIRA ticket, and request review from
+5. Run `./generate-catalog.sh` to refresh the catalog and the README tables.
+6. Open the PR from your fork, link the JIRA ticket, and request review from
    active committers.
 
 ## Links
diff --git a/README.md b/README.md
index df4aadf..28a194f 100644
--- a/README.md
+++ b/README.md
@@ -124,8 +124,8 @@ A local model writing text, routes exposed as MCP tools, 
RAG over documents, PII
 |---|---|---|
 | [LangChain4j chat](ai/langchain4j-chat/) | A local Ollama model started with 
camel infra writes the shipping notification for each of the three orders; the 
chat model is a bean built from properties, the prompt comes from the order, 
and the log shows the reply with its token counts. | `camel infra run ollama`, 
a local model |
 | [MCP server](ai/mcp-server/) | Two routes are exposed as MCP tools, 
stock_level by SKU and order_status by order id, on http://localhost:8080/mcp 
with nothing but properties to switch the server on; any MCP client, a coding 
agent included, can list and call them, and the log shows each call. | nothing |
-| [OpenAI PII Redaction](ai/openai-pii-redaction/) | Text typed on standard 
input is sent to an OpenAI-compatible model with a JSON schema that asks for 
the personal identifiers redacted, and the redacted text is printed on standard 
output. | nothing |
-| [Document Analysis with Docling and LangChain4j 
RAG](ai/docling-langchain4j-rag/) | Documents dropped in a directory are 
converted by a running Docling service, chunked and summarised by a local 
Ollama model through langchain4j-chat, and written to an output directory; an 
HTTP endpoint answers questions against the converted documents. | `camel infra 
run docling ollama` |
+| [OpenAI PII Redaction](ai/openai-pii-redaction/) | Text typed on standard 
input is sent to an OpenAI-compatible model with a JSON schema that asks for 
the personal identifiers redacted, and the redacted text is printed on standard 
output. | an OpenAI-compatible API |
+| [Document Analysis with Docling and LangChain4j 
RAG](ai/docling-langchain4j-rag/) | Documents dropped in a directory are 
converted to Markdown by a Docling service, analysed by a local Ollama model 
through langchain4j-chat, and written as a report to an output directory; an 
HTTP endpoint answers questions against the latest document. | `camel infra run 
docling ollama`, a local model |
 
 ### [Cloud](cloud/)
 
@@ -186,7 +186,7 @@ camel test run test/aggregator.citrus.it.yaml
 ```
 
 The test plugin installs on first use. The `build.yml` workflow runs every 
test on every pull request; the few
-examples marked `ciSkip` in their metadata, the ones that need a language 
model, are run by hand.
+examples marked `ciSkip` in their metadata, the ones that need a language 
model or an API key, are run by hand.
 
 ## Add an example
 
diff --git a/ai/README.md b/ai/README.md
index 59f7969..57614fb 100644
--- a/ai/README.md
+++ b/ai/README.md
@@ -7,10 +7,10 @@ A local model writing text, routes exposed as MCP tools, RAG 
over documents, PII
 |---|---|---|
 | [LangChain4j chat](langchain4j-chat/) | A local Ollama model started with 
camel infra writes the shipping notification for each of the three orders; the 
chat model is a bean built from properties, the prompt comes from the order, 
and the log shows the reply with its token counts. | `camel infra run ollama`, 
a local model |
 | [MCP server](mcp-server/) | Two routes are exposed as MCP tools, stock_level 
by SKU and order_status by order id, on http://localhost:8080/mcp with nothing 
but properties to switch the server on; any MCP client, a coding agent 
included, can list and call them, and the log shows each call. | nothing |
-| [OpenAI PII Redaction](openai-pii-redaction/) | Text typed on standard input 
is sent to an OpenAI-compatible model with a JSON schema that asks for the 
personal identifiers redacted, and the redacted text is printed on standard 
output. | nothing |
-| [Document Analysis with Docling and LangChain4j 
RAG](docling-langchain4j-rag/) | Documents dropped in a directory are converted 
by a running Docling service, chunked and summarised by a local Ollama model 
through langchain4j-chat, and written to an output directory; an HTTP endpoint 
answers questions against the converted documents. | `camel infra run docling 
ollama` |
+| [OpenAI PII Redaction](openai-pii-redaction/) | Text typed on standard input 
is sent to an OpenAI-compatible model with a JSON schema that asks for the 
personal identifiers redacted, and the redacted text is printed on standard 
output. | an OpenAI-compatible API |
+| [Document Analysis with Docling and LangChain4j 
RAG](docling-langchain4j-rag/) | Documents dropped in a directory are converted 
to Markdown by a Docling service, analysed by a local Ollama model through 
langchain4j-chat, and written as a report to an output directory; an HTTP 
endpoint answers questions against the latest document. | `camel infra run 
docling ollama`, a local model |
 
 Start with [LangChain4j chat](langchain4j-chat/); the examples read best in 
the order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing; the ones with a `test/` 
directory also say how to run their test with `camel test run`.
 <!-- group:end -->
diff --git a/ai/docling-langchain4j-rag/README.md 
b/ai/docling-langchain4j-rag/README.md
index 28b1915..ef5b184 100644
--- a/ai/docling-langchain4j-rag/README.md
+++ b/ai/docling-langchain4j-rag/README.md
@@ -1,573 +1,113 @@
 # Document Analysis with Docling and LangChain4j RAG
 
-This example demonstrates a complete RAG (Retrieval Augmented Generation) 
workflow using Apache Camel, combining:
+Documents dropped in a directory are converted to Markdown by a Docling 
service, analysed by a local Ollama
+model through `langchain4j-chat`, and written as a report to an output 
directory; an HTTP endpoint answers
+questions against the latest document. Both services are started with `camel 
infra`.
 
-* **Docling** - AI-powered document conversion (PDF, Word, PowerPoint -> 
Markdown/JSON)
-* **LangChain4j** - Integration with Large Language Models
-* **Ollama** - Local LLM inference
-
-## Overview
-
-This application provides intelligent document processing capabilities:
-
-* **Automatic Document Conversion** - Convert various document formats to 
Markdown using Docling
-* **AI-Powered Analysis** - Analyze documents using LLMs via LangChain4j
-* **Interactive Q&A** - Ask questions about your documents through REST API
-* **Batch Processing** - Summarize multiple documents automatically
-* **Structured Data Extraction** - Extract tables and structured information 
from documents
-
-## Architecture
-
-### Components
+## What you will see
 
 ```text
-Documents -> Docling (Convert) -> Markdown -> LangChain4j -> Ollama (LLM) -> 
Analysis
-```
-
-**Docling-Serve**: Python-based document conversion service running in Docker
-
-**Ollama**: Local LLM server running models like Llama 3.2
-
-**Camel Routes**: Orchestrate the workflow between components
-
-### Features
-
-* **Document Format Support**: PDF, DOCX, PPTX, HTML, Markdown
-* **Multiple Operations**: Analysis, Q&A, Summarization, Data Extraction
-* **Docker-based**: All services run in containers
-* **REST API**: HTTP endpoints for interaction
-* **Automatic Processing**: File watcher for automatic document processing
-
-## Prerequisites
-
-* JBang installed (https://www.jbang.dev)
-* Java 11 or later
-* Docker and Docker Compose
-
-## Project Structure
-
-```text
-docling-langchain4j-rag/
-├── docling-langchain4j-rag.yaml   # Main YAML configuration
-├── application.properties          # Configuration settings
-├── sample.md                       # Sample document (copy to documents/ for 
testing)
-├── README.md                       # This file
-├── documents/                      # Input directory (files auto-deleted 
after processing)
-└── output/                         # Analysis reports output
-```
-
-## Setup
-
-### Step 1: Start Required Services
-
-The Camel CLI starts both services in containers (Docker or Podman must be 
running):
-
-```sh
-$ camel infra run docling ollama
-```
-
-Docling serves on http://localhost:5001 and Ollama on http://localhost:11434, 
where the container pulls the
-`granite4:3b` model on first start; both match `application.properties`. Stop 
them later with
-`camel infra stop docling` and `camel infra stop ollama`.
-
-### Step 2: Create Required Directories
-
-The `documents/` and `output/` directories will be created automatically when 
needed, but you can create them manually:
-
-```sh
-$ mkdir -p documents output
-```
-
-> **Note:** Files placed in `documents/` will be automatically processed and 
then **deleted** after analysis is complete.
-
-### Step 3: Run the Camel Application
-
-```sh
-$ camel run *
-  --dep=camel:docling \
-  --dep=camel:langchain4j-chat \
-  --dep=camel:platform-http \
-  --dep=dev.langchain4j:langchain4j:1.6.0 \
-  --dep=dev.langchain4j:langchain4j-ollama:1.6.0 \
-  --properties=application.properties \
-  docling-langchain4j-rag.yaml
-```
-
-The application will start and listen on port 8080.
-
-## Usage
-
-### 1. Automatic Document Analysis
-
-Copy a document to the `documents/` directory for processing:
-
-```sh
-# Using the provided sample
 $ cp sample.md documents/
 
-# Or use your own document
-$ cp /path/to/your/document.pdf documents/
-```
-
-The system will:
-
-1. Detect the new file
-2. Convert it to Markdown using Docling
-3. Analyze it with the LLM
-4. Generate a comprehensive analysis report in `output/`
-5. **Automatically delete the source file** from `documents/` after processing
-
-**Example Output** (`output/sample.md_analysis.md`):
-
-```markdown
-# Document Analysis Report
-
-**File:** document.pdf
-**Date:** 2025-10-14 12:30:45
-
----
-
-## AI Analysis
-
-**Summary:** This document discusses the implementation of RAG systems...
-
-**Key Topics:**
-- Document processing pipelines
-- LLM integration patterns
-- Vector embeddings and similarity search
-
-**Important Findings:**
-- RAG improves LLM accuracy by 40%
-- Hybrid search outperforms pure vector search
-...
-
----
-
-## Full Document Content (Markdown)
-
-[Full converted markdown content here]
-```
-
-### 2. Interactive Q&A
-
-Ask questions about your documents via HTTP API:
-
-```sh
-$ curl -X POST http://localhost:8080/api/ask \
-  -H "Content-Type: text/plain" \
-  -d "What are the main topics discussed in the document?"
-```
-
-**Response:**
-
-```text
-The document discusses three main topics:
-1. RAG (Retrieval Augmented Generation) architecture
-2. Document processing with Docling
-3. Integration with LangChain4j for LLM orchestration
-```
-
-### 3. Structured Data Extraction
-
-Extract tables and structured data:
-
-```sh
-$ curl -X POST http://localhost:8080/api/extract \
-  -H "Content-Type: application/octet-stream" \
-  --data-binary "@documents/report.pdf"
+INFO ... docling-langchain4j-rag.yaml:27  : Processing document: sample.md
+INFO ... docling-langchain4j-rag.yaml:38  : Converting document to Markdown 
with Docling...
+INFO ... docling-langchain4j-rag.yaml:47  : Document converted to Markdown 
successfully
+INFO ... docling-langchain4j-rag.yaml:77  : Analyzing document with AI model...
+INFO ... docling-langchain4j-rag.yaml:89  : AI analysis completed
+INFO ... docling-langchain4j-rag.yaml:120 : Analysis report saved: 
sample.md_analysis.md
+INFO ... docling-langchain4j-rag.yaml:137 : Processing complete for: sample.md
 ```
 
-**Response:**
+and `output/sample.md_analysis.md` holds the report: the file name and date, 
the model's summary, key topics
+and findings, then the full document as Markdown. The wording of the analysis 
differs from run to run; the
+first one also takes a while, because the model is loaded.
 
 ```text
-**Document Type:** Financial Report
-
-**Key Data Fields:**
-- Revenue: $1.2M (Table 1, Row 3)
-- Expenses: $800K (Table 1, Row 5)
-- Net Profit: $400K (calculated)
-
-**Tables Identified:**
-1. Quarterly Financial Summary (5 rows, 4 columns)
-2. Department Breakdown (8 rows, 3 columns)
-...
-```
-
-### 4. Health Check
-
-Check system status:
-
-```sh
-$ curl http://localhost:8080/api/health
-```
-
-**Response:**
-
-```json
-{
-  "status": "healthy",
-  "components": {
-    "docling": {
-      "url": "http://localhost:5001";,
-      "status": "configured"
-    },
-    "ollama": {
-      "url": "http://localhost:11434";,
-      "model": "llama3.2",
-      "status": "configured"
-    }
-  },
-  "directories": {
-    "documents": "documents",
-    "output": "output"
-  }
-}
-```
-
-## Configuration
-
-### application.properties
-
-```properties
-# Directories
-documents.directory=documents
-output.directory=output
-
-# Docling-Serve URL
-docling.serve.url=http://localhost:5001
-
-# Ollama Configuration
-ollama.base.url=http://localhost:11434
-ollama.model.name=llama3.2
-
-# Server Port
-camel.server.port=8080
-```
-
-### Using Different Ollama Models
-
-Available models:
-
-* **llama3.2** (default) - Latest Llama model, good balance of speed and 
quality
-* **llama3.2:1b** - Smaller, faster model
-* **mistral** - Alternative high-quality model
-* **phi3** - Microsoft's efficient model
-* **gemma2** - Google's Gemma model
-
-To use a different model:
-
-1. Pull the model:
-
-```sh
-$ docker exec -it ollama ollama pull mistral
-```
-
-2. Update `application.properties`:
-
-```properties
-ollama.model.name=mistral
-```
-
-3. Restart the Camel application
-
-### Using Remote Ollama Instance
-
-To use Ollama running on a different machine:
-
-```properties
-ollama.base.url=http://remote-server:11434
-```
-
-## Routes Explanation
-
-### Route 1: document-analysis-workflow
-
-**Trigger:** New file in `documents/` directory
-
-**Flow:**
-
-1. Detect new document
-2. Convert to Markdown via Docling
-3. Send to LLM for analysis
-4. Generate comprehensive report
-5. Save to `output/` directory
-
-**Supported Formats:** PDF, DOCX, PPTX, HTML, MD
-
-### Route 2: document-qa-api
-
-**Endpoint:** `POST /api/ask`
-
-**Description:** Answer questions about the most recent document
-
-**Input:** Plain text question
-
-**Output:** AI-generated answer based on document content
-
-### Route 3: batch-summarization
-
-**Trigger:** Timer (configurable)
-
-**Description:** Process all documents in batch and generate summaries
-
-**Configuration:** Set `batch.delay` in application.properties (default: 
disabled)
-
-### Route 4: health-check
-
-**Endpoint:** `GET /api/health`
-
-**Description:** System health and configuration status
-
-### Route 5: extract-structured-data
-
-**Endpoint:** `POST /api/extract`
-
-**Description:** Extract tables and structured data from uploaded documents
-
-**Input:** Binary document data
-
-**Output:** AI analysis of extracted structured data
-
-## Advanced Usage
-
-### Batch Processing
-
-Enable automatic batch summarization:
-
-```properties
-# Run every 1 hour (3600000 ms)
-batch.delay=3600000
-```
-
-All documents in the `documents/` directory will be summarized periodically.
-
-### Custom Document Processing
-
-You can extend the routes to add custom processing logic:
-
-```yaml
-- route:
-    id: custom-processing
-    from:
-      uri: file:documents
-      parameters:
-        include: ".*\\.pdf"
-    steps:
-      # Your custom processing here
-      - to: docling:CONVERT_TO_HTML
-      - to: langchain4j-chat:custom
-```
-
-### Integration with Vector Stores
-
-For production RAG, consider adding vector embeddings:
-
-```yaml
-# Add after document conversion
-- to: langchain4j-embeddings:embed
-- to: your-vector-store
-```
-
-## Troubleshooting
-
-### Docling Not Responding
-
-**Check Docling service:**
-
-```sh
-$ docker logs docling-serve
-$ curl http://localhost:5001/
-```
-
-**Restart service:**
-
-```sh
-$ docker restart docling-serve
-```
-
-### Ollama Model Not Found
-
-**Pull the model:**
-
-```sh
-$ docker exec -it ollama ollama pull llama3.2
-```
-
-**Check available models:**
-
-```sh
-$ docker exec -it ollama ollama list
-```
-
-### Slow Document Processing
-
-**Causes:**
-
-* Large documents (>100 pages)
-* Complex layouts with many images
-* Limited CPU/memory
-
-**Solutions:**
-
-* Increase timeout in `application.properties`:
-
-```properties
-ollama.timeout=300
-```
-
-* Use a smaller/faster model (llama3.2:1b)
-* Process smaller documents first
-
-### Out of Memory
-
-**Increase Docker memory:**
-
-```sh
-# In Docker Desktop: Settings -> Resources -> Memory
-# Recommended: 8GB or more for LLMs
-```
-
-## Performance Considerations
-
-### Document Conversion
-
-* **PDF**: 1-5 seconds per page (depends on complexity)
-* **DOCX**: 0.5-2 seconds per page
-* **OCR-required**: 5-10 seconds per page (scanned PDFs)
-
-### LLM Inference
-
-* **llama3.2 (3B)**: 5-15 seconds per response
-* **llama3.2:1b**: 2-5 seconds per response
-* **Speed depends on**: Prompt length, context size, hardware
-
-### Recommended Hardware
-
-* **Minimum**: 8GB RAM, 4 CPU cores
-* **Recommended**: 16GB RAM, 8 CPU cores, GPU (optional)
-
-## Security Considerations
-
-### Current Implementation
-
-* **Development Setup** - Not production-ready
-* **No Authentication** - Open HTTP endpoints
-* **Local Processing** - Data stays on your machine
-
-### Production Recommendations
-
-**1. Authentication & Authorization**
-
-```yaml
-# Add to routes
-- setHeader:
-    name: Authorization
-    expression:
-      constant:
-        expression: "Bearer ${env:API_TOKEN}"
-```
-
-**2. Input Validation**
-
-* Validate file sizes
-* Check file types
-* Scan for malware
-
-**3. Rate Limiting**
-
-* Implement request throttling
-* Add queue management
-
-**4. Data Privacy**
-
-* Encrypt sensitive documents
-* Secure API endpoints with TLS
-* Implement access logging
-
-## Production Deployment
-
-### Using Kubernetes
-
-```yaml
-# See k8s-deployment.yaml (example)
-apiVersion: apps/v1
-kind: Deployment
-metadata:
-  name: docling-langchain4j-rag
-spec:
-  replicas: 3
-  ...
+$ curl -X POST localhost:8080/api/ask -H "Content-Type: text/plain" -d "What 
DSLs does Camel support?"
+The document lists four DSLs: Java, XML, YAML and Groovy.
 ```
 
-### Scaling Considerations
+## Install Camel CLI
 
-* **Horizontal**: Multiple Camel instances with load balancer
-* **Vertical**: Increase memory/CPU for Ollama container
-* **Caching**: Cache frequent document conversions
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-## Cleanup
+## Run it
 
-Stop all services:
+The example needs a running Docling and a running Ollama, which the Camel CLI 
starts for you in containers
+(Docker or Podman must be running). In one terminal:
 
-```sh
-# Docker Compose
-$ camel infra stop docling
-$ camel infra stop ollama
-
-# Or manual cleanup
-$ docker stop docling-serve ollama
-$ docker rm docling-serve ollama
-```
-
-Remove volumes (optional):
-
-```sh
-$ docker volume rm docling-langchain4j-rag_ollama_data
+```shell
+camel infra run docling ollama
 ```
 
-## Alternative Configurations
-
-### Using OpenAI Instead of Ollama
-
-```properties
-# application.properties
-openai.api.key=sk-your-api-key-here
-```
-
-```yaml
-# Update bean configuration
-- name: chatModel
-  type: dev.langchain4j.model.chat.ChatLanguageModel
-  scriptLanguage: groovy
-  script: |
-    import dev.langchain4j.model.openai.OpenAiChatModel
-
-    return OpenAiChatModel.builder()
-      .apiKey(context.resolvePropertyPlaceholders("{{openai.api.key}}"))
-      .modelName("gpt-4")
-      .temperature(0.3)
-      .build()
-```
-
-### Using Cloud Docling Service
-
-If you have a cloud-hosted Docling service:
-
-```properties
-docling.serve.url=https://your-docling-service.com
-docling.auth.token=your-auth-token
-```
-
-## References
-
-* **Docling**: https://github.com/DS4SD/docling
-* **LangChain4j**: https://github.com/langchain4j/langchain4j
-* **Ollama**: https://ollama.ai
-* **Apache Camel**: https://camel.apache.org
-* **Camel Docling Component**: 
/home/oscerd/workspace/apache-camel/camel/components/camel-ai/camel-docling/
-* **Camel LangChain4j Components**: 
/home/oscerd/workspace/apache-camel/camel/components/camel-ai/
-
-## Help and Contributions
+Docling serves on http://localhost:5001 and Ollama on http://localhost:11434, 
where the container pulls the
+`granite4:3b` model on first start, a download of a couple of gigabytes; both 
match `application.properties`.
+In another terminal:
+
+```shell
+camel run *
+```
+
+Then drop a document in the `documents` directory, the sample or one of your 
own (PDF, Word, PowerPoint,
+HTML or Markdown), and watch the log; the report lands in `output` and the 
source file is deleted once it is
+processed. Ask about the latest document with the `curl` above.
+
+Stop the example with `ctrl` + `c` and the services with `camel infra stop 
docling ollama`.
+
+## How it works
+
+- `docling-langchain4j-rag.yaml` starts with the bean `chatModel`, an 
`OllamaChatModel` built through its
+  LangChain4j builder from the URL and model name in `application.properties`; 
the `langchain4j-chat`
+  component picks it up as the one chat model in the registry.
+- `document-analysis-workflow` is the main route: a `file` consumer on 
`documents` with `include` for the
+  supported extensions. The body becomes the file's absolute path, the 
`docling` endpoint with
+  `CONVERT_TO_MARKDOWN` sends it to the Docling service and returns the 
Markdown, which is kept in an
+  exchange property. A `setBody` builds the prompt around it, 
`langchain4j-chat` sends it to the model, a
+  Groovy `script` assembles the report from the answer and the Markdown, and a 
`file` producer writes it to
+  `output` under the source name plus `_analysis.md`. A last script deletes 
the source file.
+- `document-qa-api` is `platform-http` on `POST /api/ask`: a script finds the 
newest file in `documents`,
+  Docling converts it, and the question and the Markdown go to the model in 
one prompt. That is retrieval
+  augmented generation in its simplest form, the whole document as context; 
with no document the route
+  answers an error text.
+- `batch-summarization` is a `timer` route, first after `batch.delay` and then 
every `batch.period`, that
+  converts and summarises every file in `documents` in a `split`, and logs 
each summary.
+- `health-check` on `GET /api/health` answers the configuration as JSON, and 
`extract-structured-data` on
+  `POST /api/extract` takes a document in the request body, asks Docling for 
its structured data with
+  `EXTRACT_STRUCTURED_DATA` and asks the model to describe the tables and 
fields in it.
+- `application.properties` holds the directories, the two service URLs, the 
model name, the batch timing and
+  the HTTP port.
+
+## Build it step by step
+
+Ask your assistant, or type it yourself, one step at a time, and run after 
each, with the two services running:
+
+1. A route from `file:documents` that logs the file name.
+2. Set the body to the file's absolute path and send it to `docling` with 
`CONVERT_TO_MARKDOWN` against the
+   Docling URL; log the Markdown.
+3. The `chatModel` bean from properties, a prompt around the Markdown, and a 
`langchain4j-chat` step; log the
+   answer.
+4. Write the answer and the Markdown to `output` as `<name>_analysis.md` with 
a `file` producer.
+5. A `platform-http` route on `/api/ask` that converts the newest document and 
asks the model the question in
+   the request body.
+
+## Try changing
+
+- `ollama.model.name=llama3.2` after `docker exec -it ollama ollama pull 
llama3.2`, or any other model Ollama
+  serves, and compare the analyses.
+- Change the prompt in `document-analysis-workflow` to ask for the summary in 
your language, or as five
+  bullet points.
+- `batch.period=60000` and drop three documents in `documents` to see the 
batch route summarise them
+  together every minute; the analysis route deletes them after its own run, so 
be quick.
+- For real retrieval, cut the Markdown into chunks with 
`langchain4j-tokenizer`, embed them with
+  `langchain4j-embeddings` into a vector store, and put only the chunks 
nearest the question in the prompt.
+
+## Integration testing
+
+The example has no Citrus test: it needs the Docling service and a language 
model, which take minutes to
+pull and load on a first run. Verify it with the steps under *Run it*.
+
+## Help and contributions
 
 If you hit any problem using Camel or have some feedback, then please
 [let us know](https://camel.apache.org/community/support/).
diff --git a/ai/docling-langchain4j-rag/application.properties 
b/ai/docling-langchain4j-rag/application.properties
index 601a6c1..9aa31ec 100644
--- a/ai/docling-langchain4j-rag/application.properties
+++ b/ai/docling-langchain4j-rag/application.properties
@@ -32,8 +32,9 @@ ollama.base.url=http://localhost:11434
 ollama.model.name=granite4:3b
 
 # Batch Processing Configuration
-# Set to -1 to disable batch processing
+# The batch summary of everything in the documents directory: first run after 
ten seconds, then hourly
 batch.delay=10000
+batch.period=3600000
 
 # HTTP Server Configuration
 camel.server.port=8080
diff --git a/ai/docling-langchain4j-rag/docling-langchain4j-rag.yaml 
b/ai/docling-langchain4j-rag/docling-langchain4j-rag.yaml
index ddd36c7..732ac88 100644
--- a/ai/docling-langchain4j-rag/docling-langchain4j-rag.yaml
+++ b/ai/docling-langchain4j-rag/docling-langchain4j-rag.yaml
@@ -1,3 +1,18 @@
+# Documents dropped in a directory are converted by Docling, analysed by a
+# local model and written to an output directory; an HTTP endpoint answers
+# questions against the latest document. The chat model is a bean built from
+# application.properties. Start the services with:
+# camel infra run docling ollama
+- beans:
+    - name: chatModel
+      type: dev.langchain4j.model.ollama.OllamaChatModel
+      builderClass: 
dev.langchain4j.model.ollama.OllamaChatModel$OllamaChatModelBuilder
+      builderMethod: build
+      properties:
+        baseUrl: "{{ollama.base.url}}"
+        modelName: "{{ollama.model.name}}"
+        temperature: 0.3
+
 - route:
     id: document-analysis-workflow
     from:
@@ -222,7 +237,7 @@
       parameters:
         timerName: batchSummarize
         delay: "{{batch.delay}}"
-        repeatCount: 0
+        period: "{{batch.period}}"
       steps:
         - log:
             message: Starting batch document summarization...
diff --git a/ai/docling-langchain4j-rag/metadata.json 
b/ai/docling-langchain4j-rag/metadata.json
index 7e2a571..92b2d1c 100644
--- a/ai/docling-langchain4j-rag/metadata.json
+++ b/ai/docling-langchain4j-rag/metadata.json
@@ -1,6 +1,6 @@
 {
     "title": "Document Analysis with Docling and LangChain4j RAG",
-    "description": "Documents dropped in a directory are converted by a 
running Docling service, chunked and summarised by a local Ollama model through 
langchain4j-chat, and written to an output directory; an HTTP endpoint answers 
questions against the converted documents.",
+    "description": "Documents dropped in a directory are converted to Markdown 
by a Docling service, analysed by a local Ollama model through 
langchain4j-chat, and written as a report to an output directory; an HTTP 
endpoint answers questions against the latest document.",
     "level": "ai",
     "order": 4,
     "teaches": {
@@ -33,5 +33,7 @@
         "docling",
         "ollama"
     ],
-    "requiresDocker": true
+    "requiresDocker": true,
+    "needs": "a local model",
+    "ciSkip": true
 }
diff --git a/ai/langchain4j-chat/README.md b/ai/langchain4j-chat/README.md
index 3a6a23f..8145c5e 100644
--- a/ai/langchain4j-chat/README.md
+++ b/ai/langchain4j-chat/README.md
@@ -15,7 +15,8 @@ The wording is the model's; `granite4:3b` writes plainly, a 
larger model writes
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/ai/langchain4j-chat/metadata.json 
b/ai/langchain4j-chat/metadata.json
index fc8cc23..4238555 100644
--- a/ai/langchain4j-chat/metadata.json
+++ b/ai/langchain4j-chat/metadata.json
@@ -33,5 +33,6 @@
     ],
     "requiresDocker": true,
     "bundled": false,
-    "ciSkip": true
+    "ciSkip": true,
+    "needs": "a local model"
 }
diff --git a/ai/mcp-server/README.md b/ai/mcp-server/README.md
index 9353f2d..2170f2f 100644
--- a/ai/mcp-server/README.md
+++ b/ai/mcp-server/README.md
@@ -21,7 +21,8 @@ INFO ... mcp-server.camel.yaml:81 : Tool 
order_status(ORD-1003): Order ORD-1003
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/ai/openai-pii-redaction/README.md 
b/ai/openai-pii-redaction/README.md
index ecc65e3..b64d1ce 100644
--- a/ai/openai-pii-redaction/README.md
+++ b/ai/openai-pii-redaction/README.md
@@ -1,67 +1,87 @@
-# OpenAI Personal Identifiable Information Redaction
+# OpenAI PII Redaction
 
-This example demonstrates how to use OpenAI-compatible LLM providers with 
Apache Camel to redact personal identifiable information from text.
+Text typed on standard input is sent to an OpenAI-compatible model with a JSON 
schema that asks for the
+personal identifiers redacted, and the redacted text is printed on standard 
output. Works with OpenAI itself
+or with any server that speaks its chat API, such as a local Ollama or 
llama.cpp.
 
-## Prerequisites
+## What you will see
 
-* Java 17/21
-* A running LLM service with exposed OpenAI-compatible API (for chat 
completions)
+```text
+$ echo 'Customer John Doe (email: [email protected]) requested a refund for 
order #998877.' | camel run *
+...
+{
+  "detectedPII": [
+    {"span": "John Doe", "type": "PERSON", "action": "REDACTED"},
+    {"span": "[email protected]", "type": "EMAIL", "action": "REDACTED"}
+  ],
+  "sanitizedText": "Customer [REDACTED] ([REDACTED]) requested a refund for 
order #998877."
+}
+```
+
+The order number stays: it is not a personal identifier. The exact wording 
differs from model to model.
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-## Configure OpenAI properties
+## Run it
 
-Edit the `application.properties` file or set the following environment 
properties:
+The example needs an OpenAI-compatible chat API. Point it at one with three 
environment variables, which
+`application.properties` reads:
 
-```properties
-export OPENAI_API_KEY=<your-openai-api-key>
-export OPENAI_BASE_URL=http://localhost:8181/v1
-export OPENAI_MODEL=unsloth/Ministral-3-8B-Instruct-2512-GGUF
+```shell
+export OPENAI_API_KEY=<your-api-key>
+export OPENAI_BASE_URL=https://api.openai.com/v1
+export OPENAI_MODEL=gpt-4o-mini
 ```
 
-**Important**: Replace `<your-openai-api-key>` with your actual OpenAI API key.
-
-## Example: Personal Identifiable Information Redaction
-
-This integration identifies personal identifiable information based on the 
provided schema details and redacts it.
-
-### How to run
+For a local server the key is whatever the server expects, often any non-empty 
string, and the URL is its
+`/v1` endpoint, for example `http://localhost:11434/v1` for Ollama with 
`OPENAI_MODEL` set to a model you have
+pulled. Then pipe the text in:
 
 ```shell
 echo 'Customer John Doe (email: [email protected]) requested a refund for 
order #998877.' | camel run *
 ```
 
-### What it does
+The example stops by itself after the one message, because of 
`camel.main.durationMaxMessages=1`.
 
-The integration:
-1. Reads the input from the console's standard input
-2. Analyzes analyze the user input and redacts all PII
-4. Returns the results to standard output in the specified JSON format
+## How it works
 
-### Expected Output
+- `pii-redaction.camel.yaml` holds two routes. The second is the plumbing: 
`from` the `stream` component's
+  standard input, `to` the `direct` route that does the work, `to` standard 
output.
+- The `direct` route is one `to` on the `openai` component with `operation: 
chat-completion`. The
+  `systemMessage` tells the model what to redact and what to leave alone, 
`temperature: 0.15` keeps it
+  predictable, and `jsonSchema` points at `pii.schema.json`, so the model must 
answer in that shape and the
+  body that comes back is the JSON you see.
+- `pii.schema.json` is the contract with the model: a list of `detectedPII` 
with the span, its type from a fixed
+  list, and the action, plus the `sanitizedText`.
+- `application.properties` sets the component's key, base URL and model from 
environment variables, adds the
+  `camel-openai` dependency, and limits the run to one message.
 
-```json
-{
-  "detectedPII": [
-    {
-      "span": "John Doe",
-      "type": "PERSON",
-      "action": "REDACTED"
-    },
-    {
-      "span": "[email protected]",
-      "type": "EMAIL",
-      "action": "REDACTED"
-    }
-  ],
-  "sanitizedText": "Customer [REDACTED] ([REDACTED]) requested a refund for 
order #998877."
-}
-Analyzing text: I love this product! It's absolutely amazing...
-Sentiment: positive (Score: 0.95)
-Detected Language: en
-```
+## Build it step by step
+
+Ask your assistant, or type it yourself, one step at a time, and run after 
each, with the environment
+variables set:
+
+1. A route from `stream:in` to `stream:out` that echoes what you pipe in; run 
it with `echo hello | camel run *`
+   and `camel.main.durationMaxMessages=1`.
+2. Put a `to: openai` with `operation: chat-completion` between them, with the 
key, URL and model in
+   `application.properties`; the model answers in free text.
+3. Add the `systemMessage` with the redaction rules.
+4. Write `pii.schema.json` and hand it to the endpoint with `jsonSchema`; the 
answer is now JSON in that shape.
+5. Move the work to a `direct` route so another route could call it.
+
+## Try changing
+
+- Add `"IBAN"` to the `type` enum in the schema and pipe in a bank account.
+- Change the system message to mask instead of redact, `J*** D**`, and see the 
`action` become `MASKED`.
+- Replace the `stream:in` route with a `file` consumer that redacts every text 
file dropped in a directory.
+
+## Integration testing
+
+The example has no Citrus test, because it needs a language model behind an 
API key; the `camel run` above
+is the test.
 
 ## Help and contributions
 
diff --git a/ai/openai-pii-redaction/metadata.json 
b/ai/openai-pii-redaction/metadata.json
index 364a781..717670d 100644
--- a/ai/openai-pii-redaction/metadata.json
+++ b/ai/openai-pii-redaction/metadata.json
@@ -16,5 +16,7 @@
         "privacy",
         "security"
     ],
-    "bundled": false
+    "bundled": false,
+    "needs": "an OpenAI-compatible API",
+    "ciSkip": true
 }
diff --git a/ai/openai-pii-redaction/pii-redaction.camel.yaml 
b/ai/openai-pii-redaction/pii-redaction.camel.yaml
index 14685bf..70e5c1c 100644
--- a/ai/openai-pii-redaction/pii-redaction.camel.yaml
+++ b/ai/openai-pii-redaction/pii-redaction.camel.yaml
@@ -9,12 +9,11 @@
             parameters:
               operation: chat-completion
               jsonSchema: resource:classpath:pii.schema.json
-              systemMessage: "You are a strict data privacy compliance 
assistant.\
-                \ Your goal is to analyze the user input, redact all PII, and 
return\
-                \ the results in the specified JSON format. RULES: 1. ONLY 
redact\
-                \ specific identifiers, 2. DO NOT redact generic titles, 
roles,\
-                \ or common nouns unless they are part of a proper noun. 3. 
Preserve\
-                \ the grammatical structure of the sentence."
+              systemMessage: >-
+                You are a strict data privacy compliance assistant. Your goal 
is to analyze the user input,
+                redact all PII, and return the results in the specified JSON 
format. RULES: 1. ONLY redact
+                specific identifiers, 2. DO NOT redact generic titles, roles, 
or common nouns unless they
+                are part of a proper noun. 3. Preserve the grammatical 
structure of the sentence.
               temperature: 0.15
 - route:
     from:
diff --git a/camel-jbang-example-catalog.json b/camel-jbang-example-catalog.json
index 0434afa..253edf0 100644
--- a/camel-jbang-example-catalog.json
+++ b/camel-jbang-example-catalog.json
@@ -2,7 +2,7 @@
     {
         "name": "ai/docling-langchain4j-rag",
         "title": "Document Analysis with Docling and LangChain4j RAG",
-        "description": "Documents dropped in a directory are converted by a 
running Docling service, chunked and summarised by a local Ollama model through 
langchain4j-chat, and written to an output directory; an HTTP endpoint answers 
questions against the converted documents.",
+        "description": "Documents dropped in a directory are converted to 
Markdown by a Docling service, analysed by a local Ollama model through 
langchain4j-chat, and written as a report to an output directory; an HTTP 
endpoint answers questions against the latest document.",
         "level": "ai",
         "teaches": {
             "components": [
@@ -42,6 +42,8 @@
             "docling",
             "ollama"
         ],
+        "needs": "a local model",
+        "ciSkip": true,
         "order": 4
     },
     {
@@ -88,6 +90,7 @@
         "infraServices": [
             "ollama"
         ],
+        "needs": "a local model",
         "ciSkip": true,
         "order": 1
     },
@@ -164,6 +167,8 @@
             "pii-redaction.camel.yaml",
             "pii.schema.json"
         ],
+        "needs": "an OpenAI-compatible API",
+        "ciSkip": true,
         "order": 3
     },
     {
@@ -827,8 +832,7 @@
             "error-handling.camel.yaml",
             "orders/order-1001.json",
             "orders/order-1002.json",
-            "orders/order-1003.json",
-            "parked/order-1003.json"
+            "orders/order-1003.json"
         ],
         "order": 1
     },
@@ -856,7 +860,7 @@
         ],
         "bundled": true,
         "requiresDocker": false,
-        "hasCitrusTests": false,
+        "hasCitrusTests": true,
         "files": [
             "README.md",
             "application.properties",
@@ -885,7 +889,7 @@
         ],
         "bundled": true,
         "requiresDocker": false,
-        "hasCitrusTests": false,
+        "hasCitrusTests": true,
         "files": [
             "Greeter.java",
             "README.md",
@@ -920,7 +924,7 @@
         ],
         "bundled": true,
         "requiresDocker": false,
-        "hasCitrusTests": false,
+        "hasCitrusTests": true,
         "files": [
             "README.md",
             "splitter.camel.yaml"
@@ -948,7 +952,7 @@
         ],
         "bundled": true,
         "requiresDocker": false,
-        "hasCitrusTests": false,
+        "hasCitrusTests": true,
         "files": [
             "README.md",
             "application.properties",
diff --git a/cloud/README.md b/cloud/README.md
index 7fd4172..5abae25 100644
--- a/cloud/README.md
+++ b/cloud/README.md
@@ -9,5 +9,5 @@ A cloud service, run locally through LocalStack and switched to 
the real thing b
 
 Start with [AWS SQS](aws-sqs/).
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/cloud/aws-sqs/README.md b/cloud/aws-sqs/README.md
index 5e28424..91e3a7e 100644
--- a/cloud/aws-sqs/README.md
+++ b/cloud/aws-sqs/README.md
@@ -17,7 +17,8 @@ INFO ... aws-sqs.camel.yaml:35 : Courier picked up ORD-1003 
for US: 3 line(s)
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect-service/README.md b/connect-service/README.md
index e1da701..a03f15c 100644
--- a/connect-service/README.md
+++ b/connect-service/README.md
@@ -14,5 +14,5 @@ SQL, JMS, MQTT, Kafka and FTP against a service the Camel CLI 
starts for you wit
 
 Start with [SQL database](sql/); the examples read best in the order above, 
each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/connect-service/artemis/README.md 
b/connect-service/artemis/README.md
index cad43b8..662051c 100644
--- a/connect-service/artemis/README.md
+++ b/connect-service/artemis/README.md
@@ -15,7 +15,8 @@ INFO ... artemis.camel.yaml:37 : Took ORD-1002 off the queue: 
1 line(s) for cust
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect-service/camel-1-tribute/README.md 
b/connect-service/camel-1-tribute/README.md
index 7ba2c5a..1ce81ee 100644
--- a/connect-service/camel-1-tribute/README.md
+++ b/connect-service/camel-1-tribute/README.md
@@ -1,16 +1,13 @@
-## Camel 1.0 Tribute - JMS to File
+# Camel 1.0 tribute
 
-A tribute to the very first Apache Camel example ever written.
+The very first Camel example of 2007, JMS to file, as it looks today: a timer 
sends ten messages to a queue
+on an ActiveMQ Artemis broker started with `camel infra`, and a consumer route 
writes each message to a file
+in `outbox`.
 
-When Apache Camel 1.0 was released in June 2007, the project shipped with just 
two examples.
-The first and most iconic was `camel-example-jms-file` - a simple route that 
consumed messages
-from a JMS queue and saved them to the file system.
-
-Back then, Camel was still part of the Apache ActiveMQ project. The README was 
signed
-_"The Apache ActiveMQ team"_, the website lived at `activemq.apache.org/camel`,
-and classes like `CamelTemplate` (later renamed to `ProducerTemplate`) were 
brand new.
-
-The original example looked like this:
+When Apache Camel 1.0 was released in June 2007, the project shipped with just 
two examples. The first was
+`camel-example-jms-file`: a route that consumed messages from a JMS queue and 
saved them to the file system.
+Camel was still part of the Apache ActiveMQ project, the README was signed 
_"The Apache ActiveMQ team"_, and
+classes like `CamelTemplate` (later renamed `ProducerTemplate`) were brand 
new. The original looked like this:
 
 ```java
 CamelContext context = new DefaultCamelContext();
@@ -34,61 +31,107 @@ for (int i = 0; i < 10; i++) {
 }
 ```
 
-That was 40+ lines of Java, a Maven project, ActiveMQ embedded in-process,
-and manual component wiring.
+Forty lines of Java, a Maven project, an embedded broker and manual component 
wiring. Today it is one YAML
+file and one command.
+
+## What you will see
+
+```text
+INFO ... jms-to-file.camel.yaml:32 : Sending: Test Message: 1
+INFO ... jms-to-file.camel.yaml:10 : Received: Test Message: 1
+INFO ... jms-to-file.camel.yaml:32 : Sending: Test Message: 2
+INFO ... jms-to-file.camel.yaml:10 : Received: Test Message: 2
+...
+INFO ... jms-to-file.camel.yaml:32 : Sending: Test Message: 10
+INFO ... jms-to-file.camel.yaml:10 : Received: Test Message: 10
+```
+
+and ten files in `outbox`, one per message.
+
+## Install Camel CLI
 
-Today, the same example is a single YAML file and one command.
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-### Running the example
+## Run it
 
 The example needs a running ActiveMQ Artemis broker, which the Camel CLI 
starts for you in a container
 (Docker or Podman must be running). In one terminal:
 
-```sh
-$ camel infra run artemis
+```shell
+camel infra run artemis
 ```
 
-It prints the broker URL, user and password; they match 
`application.properties`. In another terminal:
+It prints the connection details as JSON; they match `application.properties`. 
In another terminal:
 
-```sh
-$ camel run *
+```shell
+camel run *
 ```
 
-Camel will send 10 test messages to the `test.queue` JMS queue (just like the 
original)
-and consume them back, saving each message as a file in the `outbox` directory
-(the original wrote to a directory named `test`; here that name holds the 
integration test).
-Stop the broker with `camel infra stop artemis`.
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
artemis`.
 
-### What changed in 19 years
+## How it works
+
+- `jms-to-file.camel.yaml` holds two routes. `jms-to-file` is the original: 
`from` the `jms` queue
+  `test.queue`, log, `to` the `file` directory `outbox`. `send-test-messages` 
replaces the `for` loop: a
+  `timer` with `repeatCount: 10` sends "Test Message: N" to the same queue, 
with `N` from the
+  `CamelTimerCounter` header the timer sets when `includeMetadata` is on.
+- `application.properties` declares the connection factory as a bean, 
`camel.beans.artemisCF`, with the
+  broker URL, user and password `camel infra` printed, and hands it to the 
`jms` component with
+  `camel.component.jms.connection-factory`. That is the `addComponent` of the 
original, as properties.
+- The original wrote to a directory named `test`; here that name holds the 
integration test, so the files go
+  to `outbox`.
+
+What changed in 19 years:
 
 | | Camel 1.0 (2007) | Camel CLI (today) |
 |---|---|---|
-| **Language** | Java (40+ lines) | YAML (25 lines) |
+| **Language** | Java (40+ lines) | YAML (35 lines) |
 | **Build** | Maven project with pom.xml | No build needed |
 | **Broker** | Embedded ActiveMQ (in-process) | Apache ActiveMQ Artemis 
(container) |
-| **Component setup** | Manual `ConnectionFactory` wiring | Auto-configured 
via properties |
+| **Component setup** | Manual `ConnectionFactory` wiring | Configured by 
properties |
 | **Run command** | `mvn camel:run` | `camel run *` |
-| **Dependencies** | Declared in pom.xml | Auto-downloaded |
+| **Dependencies** | Declared in pom.xml | Downloaded on first run |
 
-What stayed the same: `from("jms:queue:test.queue").to("file://test")` - the 
core routing idea
-that made Camel what it is today.
+What stayed the same: `from("jms:queue:test.queue").to("file://test")`, the 
routing idea that made Camel.
 
-### Help and contributions
+## Build it step by step
 
-If you hit any problem using Camel or have some feedback, then please
-[let us know](https://camel.apache.org/community/support/).
+Ask your assistant, or type it yourself, one step at a time, and run after 
each, with the broker running:
 
-We also love contributors, so
-[get involved](https://camel.apache.org/community/contributing/) :-)
+1. A route from a timer, ten times, that logs "Test Message" with the timer 
counter.
+2. Declare the Artemis connection factory in `application.properties` and send 
the message to the `jms`
+   queue `test.queue` instead of logging it.
+3. A second route from the same queue that logs what it receives.
+4. Write each received message to a file in `outbox`.
 
-The Camel riders!
+## Try changing
+
+- Open the broker's console at http://localhost:8161 (user `artemis`, password 
`artemis`) and watch the queue's
+  message counts while the example runs.
+- `fileName: "message-${header.CamelTimerCounter}.txt"` on the `file` 
endpoint; the header survives the queue
+  because the JMS component carries headers as message properties.
+- Stop the `jms-to-file` route with `camel cmd stop-route camel-1-tribute 
--id=jms-to-file` from another
+  terminal, and the messages queue up in the broker until you start it again.
 
-### Integration testing
+## Integration testing
 
 The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
-`test/camel-1-tribute.citrus.it.yaml`, which the Camel CLI runs. The test 
starts the broker itself
-with `camel infra`, so nothing must be running beforehand:
+`test/camel-1-tribute.citrus.it.yaml`, which the Camel CLI runs. The test 
starts the broker itself with
+`camel infra`, so nothing must be running beforehand:
 
-```sh
-$ camel test run test/camel-1-tribute.citrus.it.yaml
+```shell
+camel test run test/camel-1-tribute.citrus.it.yaml
 ```
+
+The test verifies the tenth message is sent and received.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/connect-service/ftp/README.md b/connect-service/ftp/README.md
index 0bdc1d8..c6ce383 100644
--- a/connect-service/ftp/README.md
+++ b/connect-service/ftp/README.md
@@ -13,7 +13,8 @@ INFO ... ftp.camel.yaml:42 : Shipment ORD-1003 uploaded to 
the courier as courie
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect-service/kafka-orders/README.md 
b/connect-service/kafka-orders/README.md
index 63d1a68..0a28501 100644
--- a/connect-service/kafka-orders/README.md
+++ b/connect-service/kafka-orders/README.md
@@ -20,7 +20,8 @@ INFO ... kafka-orders.camel.yaml:103 : Notification: email to 
customer C-482 abo
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect-service/mqtt/README.md b/connect-service/mqtt/README.md
index 5aef730..1faf8e4 100644
--- a/connect-service/mqtt/README.md
+++ b/connect-service/mqtt/README.md
@@ -14,7 +14,8 @@ WARN ... mqtt.camel.yaml:39 : cold-room-1: 9 °C, too warm, 
alert the warehouse
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect-service/sql/README.md b/connect-service/sql/README.md
index bc6ee2c..e9509df 100644
--- a/connect-service/sql/README.md
+++ b/connect-service/sql/README.md
@@ -18,7 +18,8 @@ INFO ... sql.camel.yaml:61 :   C-482 (DK): 1 order(s)
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect/README.md b/connect/README.md
index d45b787..e6cfdff 100644
--- a/connect/README.md
+++ b/connect/README.md
@@ -11,5 +11,5 @@ Files, an HTTP client and a REST server; everything runs 
inside the example.
 
 Start with [File processing](file-processing/); the examples read best in the 
order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/connect/file-processing/README.md 
b/connect/file-processing/README.md
index a2d8717..3444ea6 100644
--- a/connect/file-processing/README.md
+++ b/connect/file-processing/README.md
@@ -17,7 +17,8 @@ INFO ... file-processing.camel.yaml:47 : Invoice INV-2004 for 
ORD-1003: 53.45 EU
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect/http-client/README.md b/connect/http-client/README.md
index c24e51d..f035653 100644
--- a/connect/http-client/README.md
+++ b/connect/http-client/README.md
@@ -17,7 +17,8 @@ INFO ... http-client.camel.yaml:112 : ORD-1003: CAMEL-MUG x 
2, 42 in stock, ok
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/connect/stock-api/README.md b/connect/stock-api/README.md
index eeb0e75..10cbd83 100644
--- a/connect/stock-api/README.md
+++ b/connect/stock-api/README.md
@@ -23,7 +23,8 @@ $ curl localhost:8080/stock
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/contracts/README.md b/contracts/README.md
index 827949a..4758ad6 100644
--- a/contracts/README.md
+++ b/contracts/README.md
@@ -11,5 +11,5 @@ An OpenAPI contract served and called, and an API protected 
by Keycloak.
 
 Start with [OpenAPI server](openapi-server/); the examples read best in the 
order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing; the ones with a `test/` 
directory also say how to run their test with `camel test run`.
 <!-- group:end -->
diff --git a/contracts/keycloak-security-rest/README.md 
b/contracts/keycloak-security-rest/README.md
index 739ed4b..e5ebabc 100644
--- a/contracts/keycloak-security-rest/README.md
+++ b/contracts/keycloak-security-rest/README.md
@@ -1,348 +1,118 @@
-# Keycloak Security REST API
+# Keycloak security
 
-This example demonstrates how to secure REST APIs using Apache Camel with 
Keycloak authentication and authorization.
-It shows how to use the `platform-http` component to create REST endpoints 
protected by Keycloak security policies.
+An API protected by Keycloak: two HTTP endpoints on port 8081, a public one 
that answers everyone and a
+protected one that requires a bearer token from a Keycloak started with `camel 
infra`, issued to a user with
+the `admin` role; anyone else gets 403.
 
-## Features
+## What you will see
 
-* Public endpoint accessible without authentication
-* Protected endpoint requiring admin role
-* Integration with Keycloak using OAuth2/OpenID Connect
-* JWT token validation
-* Role-based access control (RBAC)
+```text
+$ curl localhost:8081/api/public
+{"message": "This is a public endpoint, no authentication required", 
"timestamp": "2026-09-20T10:30:00"}
 
-## Prerequisites
+$ curl -i -H "Authorization: Bearer $USER_TOKEN" localhost:8081/api/protected
+HTTP/1.1 403 Forbidden
+{"error": "Forbidden", "message": "Access denied. ...", "timestamp": 
"2026-09-20T10:30:05", "status": 403}
 
-* JBang installed (https://www.jbang.dev)
-* Docker installed for running Keycloak
-* Basic understanding of OAuth2/OpenID Connect
-
-## Dependencies
-
-This example requires the `camel-keycloak` component.
-
-## Install JBang
-
-First install JBang according to https://www.jbang.dev
-
-When JBang is installed then you should be able to run from a shell:
-
-```sh
-$ jbang --version
-```
-
-This will output the version of JBang.
-
-To run this example you can either install Camel on JBang via:
-
-```sh
-$ jbang app install camel@apache/camel
-```
-
-Which allows to run Camel CLI with `camel` as shown below.
-
-## Running Keycloak
-
-The Camel CLI starts Keycloak for you in a container (Docker or Podman must be 
running):
-
-```sh
-$ camel infra run keycloak
-```
-
-It prints the admin user (`admin`, password `admin`) and the URL, 
http://localhost:8080. Wait for the
-container to finish starting before the configuration below. Stop it later 
with `camel infra stop keycloak`.
-
-## Keycloak Configuration
-
-After Keycloak starts, you need to configure it:
-
-### 1. Access Keycloak Admin Console
-
-Open your browser and navigate to:
-* http://localhost:8080
-
-Login with:
-* Username: `admin`
-* Password: `admin`
-
-### 2. Create a Realm
-
-1. Click on the dropdown in the top left (says "master")
-2. Click "Create Realm"
-3. Enter realm name: `camel`
-4. Click "Create"
-
-### 3. Create a Client
-
-1. In the left menu, click "Clients"
-2. Click "Create client"
-3. Enter Client ID: `camel-client`
-4. Click "Next"
-5. Enable "Client authentication"
-6. Enable "Service accounts roles"
-7. Click "Next"
-8. Add Valid Redirect URIs: `http://localhost:8080/*`
-9. Click "Save"
-10. Go to the "Credentials" tab
-11. Copy the "Client Secret" value
-12. Update the `application.properties` file with this secret:
-
-```properties
-keycloak.client.secret=<your-client-secret>
-```
-
-### 4. Create an Admin Role
-
-1. In the left menu, click "Realm roles"
-2. Click "Create role"
-3. Enter role name: `admin`
-4. Click "Save"
-
-### 5. Create Users
-
-#### Create Regular User (without admin role)
-
-1. In the left menu, click "Users"
-2. Click "Add user"
-3. Enter username: `testuser`
-4. Enter email: `[email protected]`
-5. Enter first name: `Test`
-6. Enter last name: `User`
-7. Click "Create"
-8. Go to "Credentials" tab
-9. Click "Set password"
-10. Enter password: `password`
-11. Disable "Temporary" toggle
-12. Click "Save"
-
-#### Create Admin User (with admin role)
-
-1. In the left menu, click "Users"
-2. Click "Add user"
-3. Enter username: `admin-user`
-4. Enter email: `[email protected]`
-5. Enter first name: `Admin`
-6. Enter last name: `User`
-7. Click "Create"
-8. Go to "Credentials" tab
-9. Click "Set password"
-10. Enter password: `password`
-11. Disable "Temporary" toggle
-12. Click "Save"
-13. Go to "Role mapping" tab
-14. Click "Assign role"
-15. Select the `admin` role
-16. Click "Assign"
-
-## Running the Example
-
-After Keycloak is configured, start the Camel application:
-
-```sh
-$ camel run *
-```
-
-The application will start on port 8081 (Keycloak has 8080) with the following 
endpoints:
-
-* `http://localhost:8081/api/public` - Public endpoint (no auth required)
-* `http://localhost:8081/api/protected` - Protected endpoint (admin role 
required)
-
-## Testing the Endpoints
-
-### Test Public Endpoint (No Authentication)
-
-```sh
-$ curl http://localhost:8081/api/public
-```
-
-Expected response:
-```json
-{
-  "message": "This is a public endpoint, no authentication required",
-  "timestamp": "2024-10-06T10:30:00"
-}
-```
-
-### Test Protected Endpoint with Regular User (Should Fail)
-
-First, try to access the protected endpoint with a regular user who doesn't 
have the admin role:
-
-```sh
-
-$ export ACCESS_TOKEN=$(curl -X POST 
http://localhost:8080/realms/camel/protocol/openid-connect/token \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "username=testuser" \
-  -d "password=password" \
-  -d "grant_type=password" \
-  -d "client_id=camel-client" \
-  -d "client_secret=<your-client-secret>" \
-  | jq -r '.access_token')
-
-$ curl -H "Authorization: Bearer $ACCESS_TOKEN" \
-  http://localhost:8081/api/protected
+$ curl -H "Authorization: Bearer $ADMIN_TOKEN" localhost:8081/api/protected
+{"message": "This is a protected endpoint, admin role required", "timestamp": 
"2026-09-20T10:30:10"}
 ```
 
-This will return a **403 Forbidden** error because `testuser` does not have 
the `admin` role.
-
-### Test Protected Endpoint with Admin User (Should Succeed)
-
-Now, obtain a token for the admin user and access the protected endpoint:
-
-```sh
-
-$ export ADMIN_TOKEN=$(curl -X POST 
http://localhost:8080/realms/camel/protocol/openid-connect/token \
-  -H "Content-Type: application/x-www-form-urlencoded" \
-  -d "username=admin-user" \
-  -d "password=password" \
-  -d "grant_type=password" \
-  -d "client_id=camel-client" \
-  -d "client_secret=<your-client-secret>" \
-  | jq -r '.access_token')
-
-$ curl -H "Authorization: Bearer $ADMIN_TOKEN" \
-  http://localhost:8081/api/protected
-```
+and in the log:
 
-Expected response:
-```json
-{
-  "message": "This is a protected endpoint, admin role required",
-  "timestamp": "2024-10-06T10:30:00"
-}
+```text
+INFO ... rest-api.camel.yaml:80 : Public API called
+INFO ... rest-api.camel.yaml:50 : Authorization failed: ...
+INFO ... rest-api.camel.yaml:104 : Protected API called
 ```
 
-Replace `<your-client-secret>` with the actual client secret from Keycloak.
-
-## How It Works
-
-### Security Policies
-
-The example uses a Keycloak security policy to validate JWT tokens and enforce 
role-based access control.
+## Install Camel CLI
 
-The policy is defined as a bean in the `rest-api.camel.yaml` file and requires 
the `admin` role:
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-```yaml
-- beans:
-  - name: keycloakPolicy
-    type: org.apache.camel.component.keycloak.security.KeycloakSecurityPolicy
-    properties:
-      serverUrl: "{{keycloak.server.url}}"
-      realm: "{{keycloak.realm}}"
-      clientId: "{{keycloak.client.id}}"
-      clientSecret: "{{keycloak.client.secret}}"
-      requiredRoles:
-      - "admin"
-```
-
-The bean references configuration properties from `application.properties`:
+## Run it
 
-```properties
-keycloak.server.url=http://localhost:8080
-keycloak.realm=camel
-keycloak.client.id=camel-client
-keycloak.client.secret=<your-client-secret>
-```
+The example needs a running Keycloak, which the Camel CLI starts for you in a 
container (Docker or Podman must
+be running). In one terminal:
 
-### Route Protection
-
-Routes are protected by adding a policy reference. The policy will validate 
the JWT token and check that the user has the required `admin` role:
-
-```yaml
-- route:
-    id: protected-api
-    from:
-      uri: "platform-http:/api/protected"
-      steps:
-        - policy:
-            ref: keycloakPolicy
-        - setBody:
-            expression:
-              simple:
-                expression: |
-                  {
-                    "message": "This is a protected endpoint, admin role 
required",
-                    "timestamp": "${date:now:yyyy-MM-dd'T'HH:mm:ss}"
-                  }
-        - setHeader:
-            name: Content-Type
-            expression:
-              constant:
-                expression: application/json
-        - log:
-            message: "Protected API called"
+```shell
+camel infra run keycloak
 ```
 
-If a user without the `admin` role tries to access this endpoint, they will 
receive a 403 Forbidden response.
+It prints the URL, http://localhost:8080, and the admin user (`admin`, 
password `admin`). Keycloak knows
+nothing about the shop yet, so the realm, client, role and users are created 
once in its console, in the
+browser at http://localhost:8080:
 
-## Developer Console
+1. **Realm**: the dropdown top left says `master`; *Create realm*, name 
`camel`.
+2. **Client**: *Clients*, *Create client*, client ID `camel-client`; on the 
next page enable *Client
+   authentication* and *Service accounts roles*; save. On the *Credentials* 
tab copy the *Client Secret* into
+   `application.properties` as `keycloak.client.secret`.
+3. **Role**: *Realm roles*, *Create role*, name `admin`.
+4. **Users**: *Users*, *Add user*, username `testuser`; on the *Credentials* 
tab set the password `password`
+   with *Temporary* off. The same for `admin-user`, and on its *Role mapping* 
tab assign the `admin` role.
 
-You can enable the developer console via `--console` flag:
+Then, in another terminal:
 
-```sh
-$ camel run * --console
+```shell
+camel run *
 ```
 
-Then you can browse: http://localhost:8081/q/dev to introspect the running 
Camel application.
-
-## Stopping
+The API starts on port 8081, because Keycloak has 8080. Get a token per user 
from Keycloak, with `jq` to pick it
+out of the answer, and call the endpoints as above:
 
-To stop the Camel application, press `Ctrl+C`.
-
-To stop Keycloak:
-
-If you used Camel CLI infra:
-```sh
-$ camel infra stop keycloak
-```
-
-If you used Docker manually:
-```sh
-$ docker stop keycloak
-$ docker rm keycloak
+```shell
+export USER_TOKEN=$(curl -s -X POST 
http://localhost:8080/realms/camel/protocol/openid-connect/token \
+  -d "grant_type=password" -d "client_id=camel-client" -d 
"client_secret=<your-client-secret>" \
+  -d "username=testuser" -d "password=password" | jq -r '.access_token')
+export ADMIN_TOKEN=$(curl -s -X POST 
http://localhost:8080/realms/camel/protocol/openid-connect/token \
+  -d "grant_type=password" -d "client_id=camel-client" -d 
"client_secret=<your-client-secret>" \
+  -d "username=admin-user" -d "password=password" | jq -r '.access_token')
 ```
 
-## Troubleshooting
-
-### 401 Unauthorized
-
-* Verify the access token is valid and not expired
-* Check that the Authorization header is properly formatted: `Bearer <token>`
-* Ensure the client secret in `application.properties` matches Keycloak
-
-### 403 Forbidden
-
-* Verify the user has the required role (e.g., admin role for admin endpoints)
-* Check role assignments in Keycloak Admin Console
+Stop the example with `ctrl` + `c` and the service with `camel infra stop 
keycloak`.
 
-### Connection Refused
+## How it works
 
-* Ensure Keycloak is running on port 8080 (`camel infra ps`) and the API on 
8081
-* Verify the Keycloak server URL in `application.properties` matches your setup
+- `rest-api.camel.yaml` declares the bean `keycloakPolicy`, a 
`KeycloakSecurityPolicy` from the `camel-keycloak`
+  component, with the server, realm, client and `requiredRoles: admin` from 
`application.properties`. The
+  `# camel-k: dependency=camel:keycloak` line at the top makes the CLI 
download the component, which it cannot
+  guess from a bean class.
+- Two routes from `platform-http`, the HTTP server built into the CLI. 
`public-api` just answers. `protected-api`
+  starts with `policy: {ref: keycloakPolicy}`: the policy reads the bearer 
token from the `Authorization`
+  header, validates it against Keycloak, checks the roles in it, and only then 
lets the message through to the
+  steps that build the answer.
+- A token that is missing, invalid or without the role makes the policy throw 
`CamelAuthorizationException`.
+  The `onException` at the top handles it for every route: status 403 in the 
`CamelHttpResponseCode` header, a
+  JSON error body, and a log line.
+- `application.properties` holds the Keycloak details, the client secret you 
copied, and `camel.server.port`.
 
-### Invalid Client Credentials
+## Build it step by step
 
-* Check that the client ID and secret in `application.properties` match the 
Keycloak client configuration
-* Verify the realm name is correct
+Ask your assistant, or type it yourself, one step at a time, and run after 
each, with Keycloak running and
+configured:
 
-## Architecture
+1. A route from `platform-http:/api/public` that answers a JSON message; 
`curl` it.
+2. A second route on `/api/protected` that answers another message.
+3. The `keycloakPolicy` bean with the server, realm, client and secret from 
`application.properties`, and a
+   `policy` step as the first step of the protected route; `curl` it without a 
token and see the error.
+4. The `onException` for `CamelAuthorizationException` that answers 403 with a 
JSON body.
+5. Get a token for `admin-user` and call the protected endpoint with it.
 
-This example demonstrates:
+## Try changing
 
-1. **Platform HTTP Component**: Provides HTTP server capabilities
-2. **Keycloak Security Policy**: Validates OAuth2 JWT tokens
-3. **Role-Based Access Control**: Restricts endpoints based on user roles
-4. **RESTful API Design**: Multiple endpoints with different security levels
+- `requiredRoles: "admin,manager"` on the policy and a `manager` role in 
Keycloak: `allRolesRequired` decides
+  whether a user needs both or one of them.
+- Log `${header.Authorization}` in the protected route to see the raw token, 
and paste it into
+  https://jwt.io to read the roles Keycloak put in it.
+- Protect the public endpoint too, with a second policy that has no 
`requiredRoles`: any valid token passes.
 
-## Next Steps
+## Integration testing
 
-* Add more granular role-based access control
-* Implement refresh token handling
-* Add API documentation with OpenAPI/Swagger
-* Implement request/response logging
-* Add rate limiting
-* Implement CORS configuration for web applications
+The example has no Citrus test: the realm, client and users are created by 
hand in the Keycloak console, so
+there is nothing a test could start from. Verify it with the `curl` calls 
above.
 
-## Help and Contributions
+## Help and contributions
 
 If you hit any problem using Camel or have some feedback, then please
 [let us know](https://camel.apache.org/community/support/).
diff --git a/contracts/openapi-client/README.md 
b/contracts/openapi-client/README.md
index d48c646..bee0624 100644
--- a/contracts/openapi-client/README.md
+++ b/contracts/openapi-client/README.md
@@ -17,7 +17,8 @@ INFO ... openapi-client.camel.yaml:63 : ORD-1003: reserved 2 
x CAMEL-MUG, 42 lef
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/contracts/openapi-server/README.md 
b/contracts/openapi-server/README.md
index 3e19b99..04fbb10 100644
--- a/contracts/openapi-server/README.md
+++ b/contracts/openapi-server/README.md
@@ -25,7 +25,8 @@ INFO ... openapi-server.camel.yaml:123 : Reserved 2 x 
CAMEL-MUG for ORD-1001
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/fail-well/README.md b/fail-well/README.md
index b74f5b2..3612799 100644
--- a/fail-well/README.md
+++ b/fail-well/README.md
@@ -10,5 +10,5 @@ Retries, a dead letter channel, and a circuit breaker in 
front of a flaky servic
 
 Start with [Error handling](error-handling/); the examples read best in the 
order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/fail-well/circuit-breaker/README.md 
b/fail-well/circuit-breaker/README.md
index f2a99dd..c38d159 100644
--- a/fail-well/circuit-breaker/README.md
+++ b/fail-well/circuit-breaker/README.md
@@ -19,7 +19,8 @@ INFO ... circuit-breaker.camel.yaml:30 : Stock check 15 
(breaker CLOSED): CAMEL-
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/fail-well/error-handling/README.md 
b/fail-well/error-handling/README.md
index 2a584e0..00b24b2 100644
--- a/fail-well/error-handling/README.md
+++ b/fail-well/error-handling/README.md
@@ -17,7 +17,8 @@ INFO ... error-handling.camel.yaml:75 : Order ORD-1003 parked 
for manual review:
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/generate-catalog.sh b/generate-catalog.sh
index 18da957..da831c5 100755
--- a/generate-catalog.sh
+++ b/generate-catalog.sh
@@ -116,6 +116,8 @@ for dirpath, dirnames, filenames in 
sorted(os.walk(repo_root)):
     }
     if "infraServices" in meta:
         entry["infraServices"] = meta["infraServices"]
+    if "needs" in meta:
+        entry["needs"] = meta["needs"]
     if meta.get("ciSkip", False):
         entry["ciSkip"] = True
     if "order" in meta:
@@ -161,8 +163,8 @@ def needs(e):
     parts = []
     if e.get("infraServices"):
         parts.append("`camel infra run " + " ".join(e["infraServices"]) + "`")
-    if e.get("ciSkip"):
-        parts.append("a local model")
+    if e.get("needs"):
+        parts.append(e["needs"])
     return ", ".join(parts) if parts else "nothing"
 
 lines = []
@@ -194,8 +196,10 @@ for level, title, intro in GROUPS:
         body.append(f"Start with [{first['title']}]({first_short}/); the 
examples read best in the order above, "
                     f"each one building on what the one before it set up.")
     body.append("")
-    body.append("Every example has a README that says what you will see, how 
it works, how to build it step by step, "
-                "what to try changing, and how to run its test with `camel 
test run`.")
+    body.append("Every example has a README that says what you will see, how 
it works, how to build it step by step "
+                "and what to try changing"
+                + (", and how to run its test with `camel test run`." if 
all(e["hasCitrusTests"] for e in entries)
+                   else "; the ones with a `test/` directory also say how to 
run their test with `camel test run`."))
     if os.path.exists(group_readme):
         g = open(group_readme).read()
         if gstart in g and gend in g:
diff --git a/install.adoc b/install.adoc
deleted file mode 100644
index 826317e..0000000
--- a/install.adoc
+++ /dev/null
@@ -1,24 +0,0 @@
-First install JBang according to the https://www.jbang.dev/download/[JBang 
installation guide]
-
-When JBang is installed you should be able to run from a shell:
-
-[source,shell]
-----
-jbang --version
-----
-
-This will output the version of JBang.
-
-To run this example you can install Camel on JBang via:
-
-[source,shell]
-----
-jbang app install camel@apache/camel
-----
-
-Which allows to run Camel with `camel` as shown below.
-
-[source,shell]
-----
-camel --version
-----
diff --git a/quick-start/README.md b/quick-start/README.md
index e8cbdca..2da983f 100644
--- a/quick-start/README.md
+++ b/quick-start/README.md
@@ -12,5 +12,5 @@ The first ten minutes: generic examples with no story and no 
service, each runni
 
 Start with [Timer Log](timer-log/); the others stand on their own, in any 
order.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/quick-start/rest-api/README.md b/quick-start/rest-api/README.md
index db3dac3..2fc82ee 100644
--- a/quick-start/rest-api/README.md
+++ b/quick-start/rest-api/README.md
@@ -1,12 +1,73 @@
-## REST API
+# REST API
 
-This example shows a REST API with hello endpoints.
+A REST API on port 8080, served by the HTTP server built into the Camel CLI: 
`GET /api/hello` answers the
+greeting from `application.properties` and `GET /api/hello/{name}` answers a 
greeting with the name.
 
-### How to run
+## What you will see
 
-    camel run rest-api.camel.yaml
+```text
+$ curl localhost:8080/api/hello
+Hello from Camel REST API!
 
-### Try it
+$ curl localhost:8080/api/hello/World
+Hello World from Camel REST API!
+```
 
-    curl http://localhost:8080/api/hello
-    curl http://localhost:8080/api/hello/World
+## Install Camel CLI
+
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
+
+## Run it
+
+```shell
+camel run *
+```
+
+Then, in another terminal, call it with `curl` as above. Stop it with `ctrl` + 
`c`.
+
+## How it works
+
+- `rest-api.camel.yaml` declares the API with the REST DSL: a `rest` with 
`path: /api` and two `get`
+  operations, `/hello` and `/hello/{name}`. Each operation hands over to a 
`direct` route with `to`.
+- The two `direct` routes set the body that becomes the HTTP response: a 
constant with the greeting from
+  `application.properties`, and a simple expression in which the `{name}` path 
parameter arrives as the
+  header `name`.
+- The CLI starts the HTTP server because the file uses the REST DSL; 
`camel.server.port` in
+  `application.properties` sets the port.
+
+## Build it step by step
+
+Ask your assistant, or type it yourself, one step at a time, and run after 
each:
+
+1. A `rest` with `path: /api` and one `get` on `/hello` that goes to a direct 
route answering "Hello";
+   run it and `curl localhost:8080/api/hello`.
+2. Add the `/hello/{name}` operation and a second direct route that answers 
with `${header.name}`.
+3. Move the greeting and the port to `application.properties`.
+
+## Try changing
+
+- Add `POST /api/hello` that answers with the request body: `curl -d 'Camel' 
localhost:8080/api/hello`.
+- Set the header `Content-Type` to `application/json` and answer `{"greeting": 
"${body}"}`.
+- Run with `--console` and open http://localhost:8080/q/dev to see the routes 
and their statistics.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/rest-api.citrus.it.yaml`, which the Camel CLI runs:
+
+```shell
+camel test run test/rest-api.citrus.it.yaml
+```
+
+The test starts the route and calls both operations over HTTP.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/quick-start/rest-api/application.properties 
b/quick-start/rest-api/application.properties
index f3ee407..4abd98e 100644
--- a/quick-start/rest-api/application.properties
+++ b/quick-start/rest-api/application.properties
@@ -1,3 +1,20 @@
+# 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.
+
 # HTTP server port
 camel.server.port=8080
 # Greeting message for the hello endpoint
diff --git a/quick-start/rest-api/test/rest-api.citrus.it.yaml 
b/quick-start/rest-api/test/rest-api.citrus.it.yaml
new file mode 100644
index 0000000..160d16f
--- /dev/null
+++ b/quick-start/rest-api/test/rest-api.citrus.it.yaml
@@ -0,0 +1,40 @@
+name: rest-api-test
+description: The REST API answers the greeting, with and without a name
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "rest-api"
+            file: "../rest-api.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+  - camel:
+      jbang:
+        verify:
+          integration: "rest-api"
+          logMessage: "(rest-api) started"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        GET:
+          path: "/api/hello"
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "200"
+          body:
+            data: "Hello from Camel REST API!"
+  - http:
+      client: "http://localhost:8080";
+      sendRequest:
+        GET:
+          path: "/api/hello/World"
+  - http:
+      client: "http://localhost:8080";
+      receiveResponse:
+        response:
+          status: "200"
+          body:
+            data: "Hello World from Camel REST API!"
diff --git a/quick-start/routes/Greeter.java b/quick-start/routes/Greeter.java
index bdb9a45..6053562 100644
--- a/quick-start/routes/Greeter.java
+++ b/quick-start/routes/Greeter.java
@@ -1,20 +1,34 @@
+/*
+ * 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.
+ */
 package camel.example;
 
-import org.apache.camel.Exchange;
-import org.apache.camel.Processor;
+/**
+ * Builds the greeting. A plain Java class next to the route, with no Camel 
API in it: beans.yaml declares it as the
+ * bean greeter and sets its greeting from a property, and the route calls its 
greet method with the message body.
+ */
+public class Greeter {
 
-public class Greeter implements Processor {
+    private String greeting;
 
-    private String message;
-
-    public void setMessage(String message) {
-        this.message = message;
+    public void setGreeting(String greeting) {
+        this.greeting = greeting;
     }
 
-    @Override
-    public void process(Exchange exchange) throws Exception {
-        String body = exchange.getIn().getBody(String.class);
-        exchange.getIn().setBody(message + " " + body);
+    public String greet(String name) {
+        return greeting + ", " + name + "!";
     }
-
-}
\ No newline at end of file
+}
diff --git a/quick-start/routes/README.md b/quick-start/routes/README.md
index 8157bcf..c8e1d74 100644
--- a/quick-start/routes/README.md
+++ b/quick-start/routes/README.md
@@ -1,67 +1,68 @@
-## Routes
+# Routes
 
-This example shows how routes are defined in Yaml.
+The first step from YAML into your own code: a timer route in YAML calls a 
Java bean, `Greeter`, that builds
+the message, and logs what the bean returned.
 
-### Install JBang
+## What you will see
 
-First install JBang according to https://www.jbang.dev
-
-When JBang is installed then you should be able to run from a shell:
-
-```sh
-$ jbang --version
-```
-
-This will output the version of JBang.
-
-To run this example you can either install Camel on JBang via:
-
-```sh
-$ jbang app install camel@apache/camel
+```text
+INFO ... routes.camel.yaml:16 : Hello, Camel!
+INFO ... routes.camel.yaml:16 : Hello, Camel!
 ```
 
-Which allows to run Camel CLI with `camel` as shown below.
+## Install Camel CLI
 
-### How to run
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-You can run this example using:
+## Run it
 
-```sh
-$ camel run *
+```shell
+camel run *
 ```
 
-Camel will start a route that periodically provides a greeting message.
+Stop it with `ctrl` + `c`, or from another terminal with `camel stop routes`.
 
-### Live reload
+## How it works
 
-You can run the example in dev mode which allows you to edit the example,
-and hot-reload when the file is saved.
+- `routes.camel.yaml` is the route: a `timer` fires every second, a `setBody` 
puts the name `Camel` in the
+  message, a `bean` step calls the `greet` method of the bean `greeter` with 
the body, and a `log` prints
+  what the method returned, which is now the body.
+- `Greeter.java` is a plain Java class next to the route, with no Camel API in 
it: a `greeting` property and a
+  `greet(String name)` method. The CLI compiles it when the route starts.
+- `beans.yaml` declares the class as the bean `greeter` and sets its 
`greeting` from a property.
+- `application.properties` holds the greeting and the timer period.
 
-```sh
-$ camel run * --dev
-```
+## Build it step by step
 
-### Run directly from GitHub
+Ask your assistant, or type it yourself, one step at a time, and run after 
each:
 
-The example can also be run directly by referring to the GitHub URL as shown:
+1. A route from a timer that sets the body to "Camel" and logs it.
+2. A Java class `Greeter` in the package `camel.example` with a method 
`greet(String name)` that returns
+   "Hello, " and the name, declared as the bean `greeter` in `beans.yaml`; 
call it from the route with a
+   `bean` step before the log.
+3. Give the class a `greeting` property, set it in `beans.yaml`, and move its 
value to
+   `application.properties`.
 
-```sh
-$ camel run https://github.com/apache/camel-jbang-examples/tree/main/routes
-```
+## Try changing
 
-### Developer Web Console
+- `greeter.greeting=Hej` in `application.properties`; the Java class and the 
route do not change.
+- Add a second method `shout(String name)` that returns the greeting in upper 
case and switch the `method` in
+  the route.
+- Leave out `method: greet` and see that Camel finds the single public method 
by itself.
 
-You can enable the developer console via `--console` flag as show:
+## Integration testing
 
-```sh
-$ camel run * --console
-```
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/routes.citrus.it.yaml`, which the Camel CLI runs:
 
-Then you can browse: http://localhost:8080/q/dev to introspect the running 
Camel Application.
-Under "beans" Camel should display bean `greeter`.
+```shell
+camel test run test/routes.citrus.it.yaml
+```
 
+The test starts the route, with the bean and the Java class, and verifies the 
logged greeting.
 
-### Help and contributions
+## Help and contributions
 
 If you hit any problem using Camel or have some feedback, then please
 [let us know](https://camel.apache.org/community/support/).
diff --git a/quick-start/routes/application.properties 
b/quick-start/routes/application.properties
index 9049d38..a6616c4 100644
--- a/quick-start/routes/application.properties
+++ b/quick-start/routes/application.properties
@@ -1,2 +1,21 @@
-# Greeting message used by the Greeter bean
-greeter.message=Hello!
+# 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.
+
+# The greeting the Greeter bean starts its message with
+greeter.greeting=Hello
+# How often the timer fires, in milliseconds
+greeter.period=1000
diff --git a/quick-start/routes/beans.yaml b/quick-start/routes/beans.yaml
index a984e77..ec44970 100644
--- a/quick-start/routes/beans.yaml
+++ b/quick-start/routes/beans.yaml
@@ -1,5 +1,5 @@
 - beans:
-  - name: "greeter"
-    type: "camel.example.Greeter"
-    properties:
-      message: '{{greeter.message}}'
+    - name: greeter
+      type: "camel.example.Greeter"
+      properties:
+        greeting: "{{greeter.greeting}}"
diff --git a/quick-start/routes/routes.camel.yaml 
b/quick-start/routes/routes.camel.yaml
index a15415f..76ae528 100644
--- a/quick-start/routes/routes.camel.yaml
+++ b/quick-start/routes/routes.camel.yaml
@@ -1,17 +1,17 @@
 - route:
-    id: greeting-route
+    id: greeting
     from:
       uri: timer
       parameters:
-        timerName: start
-        period: 1000
+        timerName: greet
+        period: "{{greeter.period}}"
       steps:
         - setBody:
             expression:
-              simple:
-                expression: "I'm ${routeId}"
+              constant:
+                expression: "Camel"
         - bean:
             ref: greeter
+            method: greet
         - log:
             message: "${body}"
-
diff --git a/quick-start/routes/test/routes.citrus.it.yaml 
b/quick-start/routes/test/routes.citrus.it.yaml
new file mode 100644
index 0000000..b2f129e
--- /dev/null
+++ b/quick-start/routes/test/routes.citrus.it.yaml
@@ -0,0 +1,19 @@
+name: routes-test
+description: The route logs the greeting the Greeter bean built
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "routes"
+            file: "../routes.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+          resources:
+            - "beans.yaml"
+            - "Greeter.java"
+  - camel:
+      jbang:
+        verify:
+          integration: "routes"
+          logMessage: "Hello, Camel!"
diff --git a/quick-start/splitter/README.md b/quick-start/splitter/README.md
index ea673cc..a07be02 100644
--- a/quick-start/splitter/README.md
+++ b/quick-start/splitter/README.md
@@ -1,42 +1,72 @@
-## Splitter
+# Splitter
 
-This example demonstrates the Splitter EIP.
+A timer creates a comma-separated batch of items, the splitter turns it into 
one message per item, and each item
+is logged on its own line.
 
-A batch of comma-separated product names is split into individual messages.
-Each item is logged with its split index.
+## What you will see
 
-The splitter processes each part of the message independently, which is useful
-for breaking down bulk data into individual records for downstream processing.
+```text
+INFO ... splitter.camel.yaml:14 : Received batch: 
Laptop,Phone,Tablet,Monitor,Keyboard
+INFO ... splitter.camel.yaml:21 : Processing item 0: Laptop
+INFO ... splitter.camel.yaml:21 : Processing item 1: Phone
+INFO ... splitter.camel.yaml:21 : Processing item 2: Tablet
+INFO ... splitter.camel.yaml:21 : Processing item 3: Monitor
+INFO ... splitter.camel.yaml:21 : Processing item 4: Keyboard
+```
+
+The batch is sent three times, five seconds apart, and then the timer stops.
 
-### Install JBang
+## Install Camel CLI
 
-First install JBang according to https://www.jbang.dev
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
-When JBang is installed then you should be able to run from a shell:
+## Run it
 
-```sh
-$ jbang --version
+```shell
+camel run *
 ```
 
-This will output the version of JBang.
+Stop it with `ctrl` + `c`, or from another terminal with `camel stop splitter`.
 
-To run this example you can either install Camel on JBang via:
+## How it works
 
-```sh
-$ jbang app install camel@apache/camel
-```
+- `splitter.camel.yaml` is the route: a `timer` with `repeatCount: 3` fires 
three times, a `setBody` puts the
+  batch in the message as one string, and a `log` prints it.
+- `split` with a `tokenize` expression on `,` turns the one message into five, 
one per item. The steps under
+  the `split` run once for each of them: here a `log` with the item.
+- `CamelSplitIndex` is a header the splitter sets on each part, counting from 
0; `CamelSplitSize` is the
+  total and `CamelSplitComplete` is true on the last part.
+- After the last part the route continues after the `split` with the original 
batch as the body; there is
+  nothing after it here.
+
+## Build it step by step
 
-Which allows to run Camel CLI with `camel` as shown below.
+Ask your assistant, or type it yourself, one step at a time, and run after 
each:
 
-### How to run
+1. A route from a timer that sets the body to "Laptop,Phone,Tablet" and logs 
it.
+2. Split the body on the comma and log each part.
+3. Add the split index to the log line, and `repeatCount: 3` to the timer.
 
-You can run this example using:
+## Try changing
 
-```sh
-$ camel run *
+- Log `${header.CamelSplitIndex} of ${header.CamelSplitSize}` on each part.
+- Add a `log` after the `split` and see the original batch come back as the 
body.
+- Split a JSON array instead: set the body to `["Laptop","Phone"]` and use 
`jsonpath: {expression: "$[*]"}`
+  as the split expression.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/splitter.citrus.it.yaml`, which the Camel CLI runs:
+
+```shell
+camel test run test/splitter.citrus.it.yaml
 ```
 
-### Help and contributions
+The test starts the route and verifies the batch and the last item are logged.
+
+## Help and contributions
 
 If you hit any problem using Camel or have some feedback, then please
 [let us know](https://camel.apache.org/community/support/).
diff --git a/quick-start/splitter/test/splitter.citrus.it.yaml 
b/quick-start/splitter/test/splitter.citrus.it.yaml
new file mode 100644
index 0000000..d3ebde9
--- /dev/null
+++ b/quick-start/splitter/test/splitter.citrus.it.yaml
@@ -0,0 +1,19 @@
+name: splitter-test
+description: The splitter logs the batch and then one line per item
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "splitter"
+            file: "../splitter.camel.yaml"
+  - camel:
+      jbang:
+        verify:
+          integration: "splitter"
+          logMessage: "Received batch: Laptop,Phone,Tablet,Monitor,Keyboard"
+  - camel:
+      jbang:
+        verify:
+          integration: "splitter"
+          logMessage: "Processing item 4: Keyboard"
diff --git a/quick-start/timer-log/README.md b/quick-start/timer-log/README.md
index f773ce1..5b44f20 100644
--- a/quick-start/timer-log/README.md
+++ b/quick-start/timer-log/README.md
@@ -1,7 +1,69 @@
-## Timer Log
+# Timer Log
 
-This example shows a simple timer that logs a hello message every second.
+The hello of Camel in one file: a timer fires every second and a log line 
prints the greeting from
+`application.properties`.
 
-### How to run
+## What you will see
 
-    camel run timer-log.camel.yaml
+```text
+INFO ... timer-log.camel.yaml:13 : Hello Camel!
+INFO ... timer-log.camel.yaml:13 : Hello Camel!
+INFO ... timer-log.camel.yaml:13 : Hello Camel!
+```
+
+## Install Camel CLI
+
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
+
+## Run it
+
+```shell
+camel run *
+```
+
+Stop it with `ctrl` + `c`, or from another terminal with `camel stop 
timer-log`.
+
+## How it works
+
+- `timer-log.camel.yaml` is the route: `from` a `timer` that fires every 
`timer.period` milliseconds, a
+  `setBody` puts the greeting in the message, and a `log` prints the body.
+- `application.properties` holds the period and the greeting. 
`{{timer.period}}` and `{{greeting.message}}`
+  in the route are property placeholders, resolved when the route starts.
+- The Camel CLI reads every file in the directory: the route because it ends 
in `.camel.yaml`, the properties
+  because of their name.
+
+## Build it step by step
+
+Ask your assistant, or type it yourself, one step at a time, and run after 
each:
+
+1. A route from a timer that logs "Hello Camel!" every second.
+2. Move the greeting to `application.properties` and set the body from the 
property.
+3. Move the period to a property too.
+
+## Try changing
+
+- `timer.period=5000` for a greeting every five seconds; the route file does 
not change.
+- Add `repeatCount: 3` to the timer parameters and the timer stops after three 
greetings.
+- Log `${date:now:HH:mm:ss} ${body}` to see when each line was written.
+
+## Integration testing
+
+The example comes with a test in the [Citrus](https://citrusframework.org/) 
YAML DSL,
+`test/timer-log.citrus.it.yaml`, which the Camel CLI runs:
+
+```shell
+camel test run test/timer-log.citrus.it.yaml
+```
+
+The test starts the route and verifies the logged greeting.
+
+## Help and contributions
+
+If you hit any problem using Camel or have some feedback, then please
+[let us know](https://camel.apache.org/community/support/).
+
+We also love contributors, so
+[get involved](https://camel.apache.org/community/contributing/) :-)
+
+The Camel riders!
diff --git a/quick-start/timer-log/application.properties 
b/quick-start/timer-log/application.properties
index 370577a..5cc0a54 100644
--- a/quick-start/timer-log/application.properties
+++ b/quick-start/timer-log/application.properties
@@ -1,3 +1,20 @@
+# 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.
+
 # Timer period in milliseconds
 timer.period=1000
 # Greeting message to log
diff --git a/quick-start/timer-log/test/timer-log.citrus.it.yaml 
b/quick-start/timer-log/test/timer-log.citrus.it.yaml
new file mode 100644
index 0000000..d2b2ebe
--- /dev/null
+++ b/quick-start/timer-log/test/timer-log.citrus.it.yaml
@@ -0,0 +1,16 @@
+name: timer-log-test
+description: The timer route logs the greeting from application.properties
+actions:
+  - camel:
+      jbang:
+        run:
+          integration:
+            name: "timer-log"
+            file: "../timer-log.camel.yaml"
+            systemProperties:
+              file: "../application.properties"
+  - camel:
+      jbang:
+        verify:
+          integration: "timer-log"
+          logMessage: "Hello Camel!"
diff --git a/route/README.md b/route/README.md
index ae08b32..d881b2e 100644
--- a/route/README.md
+++ b/route/README.md
@@ -12,5 +12,5 @@ The routing patterns: content-based router, splitter, 
aggregator, filter and mul
 
 Start with [Content-based router](content-based-router/); the examples read 
best in the order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/route/aggregator/README.md b/route/aggregator/README.md
index d67c6fb..56789ff 100644
--- a/route/aggregator/README.md
+++ b/route/aggregator/README.md
@@ -17,7 +17,8 @@ INFO ... aggregator.camel.yaml:51 : Shipment for ORD-1002 
complete: [{"sku":"CAM
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/route/content-based-router/README.md 
b/route/content-based-router/README.md
index ca66bc3..4bbb639 100644
--- a/route/content-based-router/README.md
+++ b/route/content-based-router/README.md
@@ -13,7 +13,8 @@ INFO ... content-based-router.camel.yaml:32 : Order ORD-1003 
from US: export, cu
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/route/filter-and-multicast/README.md 
b/route/filter-and-multicast/README.md
index 8418ed4..fd45f53 100644
--- a/route/filter-and-multicast/README.md
+++ b/route/filter-and-multicast/README.md
@@ -16,7 +16,8 @@ INFO ... filter-and-multicast.camel.yaml:16 : Order ORD-1003 
received, status pe
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/route/order-lines/README.md b/route/order-lines/README.md
index 154e401..2659d8d 100644
--- a/route/order-lines/README.md
+++ b/route/order-lines/README.md
@@ -16,7 +16,8 @@ INFO ... order-lines.camel.yaml:20 : Order ORD-1002 with 1 
line(s)
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/run/README.md b/run/README.md
index 3f9e7a8..58e80cc 100644
--- a/run/README.md
+++ b/run/README.md
@@ -11,5 +11,5 @@ Running Camel: timers and cron schedules, a bean in a route, 
properties and prof
 
 Start with [Order generator](order-generator/); the examples read best in the 
order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/run/nightly-report/README.md b/run/nightly-report/README.md
index ac608cd..5b02665 100644
--- a/run/nightly-report/README.md
+++ b/run/nightly-report/README.md
@@ -12,7 +12,8 @@ INFO ... nightly-report.camel.yaml:15 : Inventory report 
2026-09-18 15:04:20: 12
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/run/order-generator/README.md b/run/order-generator/README.md
index e644321..18fc09f 100644
--- a/run/order-generator/README.md
+++ b/run/order-generator/README.md
@@ -13,7 +13,8 @@ INFO ... order-generator.camel.yaml:23 : New order ORD-1002: 
{"orderId": "ORD-10
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/run/properties-and-profiles/README.md 
b/run/properties-and-profiles/README.md
index e749ff1..a546167 100644
--- a/run/properties-and-profiles/README.md
+++ b/run/properties-and-profiles/README.md
@@ -15,7 +15,8 @@ INFO ... properties-and-profiles.camel.yaml:15 : Welcome to 
Camel Shop, prices i
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/showcase/README.md b/showcase/README.md
index 2c5580e..9bc3925 100644
--- a/showcase/README.md
+++ b/showcase/README.md
@@ -12,5 +12,5 @@ Tooling demos outside the ladder: the TUI, a memory leak, 
message sizes, log ana
 
 Start with [TUI Hello World](tui-hello-world/); the others stand on their own, 
in any order.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing; the ones with a `test/` 
directory also say how to run their test with `camel test run`.
 <!-- group:end -->
diff --git a/transform/README.md b/transform/README.md
index 3d8c69b..f87b719 100644
--- a/transform/README.md
+++ b/transform/README.md
@@ -14,5 +14,5 @@ JSON, XML and CSV in and out, field-by-field mapping, Groovy 
and XSLT.
 
 Start with [JSON transform](json-transform/); the examples read best in the 
order above, each one building on what the one before it set up.
 
-Every example has a README that says what you will see, how it works, how to 
build it step by step, what to try changing, and how to run its test with 
`camel test run`.
+Every example has a README that says what you will see, how it works, how to 
build it step by step and what to try changing, and how to run its test with 
`camel test run`.
 <!-- group:end -->
diff --git a/transform/csv-to-json/README.md b/transform/csv-to-json/README.md
index 6069d92..8ed95b6 100644
--- a/transform/csv-to-json/README.md
+++ b/transform/csv-to-json/README.md
@@ -16,7 +16,8 @@ INV-2001.json INV-2002.json INV-2003.json
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/transform/data-mapping/README.md b/transform/data-mapping/README.md
index ce49606..7ed0376 100644
--- a/transform/data-mapping/README.md
+++ b/transform/data-mapping/README.md
@@ -11,7 +11,8 @@ INFO ... data-mapping.camel.yaml:27 : Shipment for the 
courier: {"shipmentRef":"
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/transform/groovy/README.md b/transform/groovy/README.md
index 35ba363..5a49097 100644
--- a/transform/groovy/README.md
+++ b/transform/groovy/README.md
@@ -13,7 +13,8 @@ INFO ... groovy.camel.yaml:32 : Order ORD-1002 rejected: 
not-an-address is not a
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/transform/json-transform/README.md 
b/transform/json-transform/README.md
index 9b79df3..f7e3d2c 100644
--- a/transform/json-transform/README.md
+++ b/transform/json-transform/README.md
@@ -16,7 +16,8 @@ INFO ... json-transform.camel.yaml:32 : Pick list for the 
warehouse: {
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/transform/xml-to-json/README.md b/transform/xml-to-json/README.md
index 4784dcc..b7e7b72 100644
--- a/transform/xml-to-json/README.md
+++ b/transform/xml-to-json/README.md
@@ -12,7 +12,8 @@ INFO ... xml-to-json.camel.yaml:20 : The same order as JSON: 
{"id":"ORD-1001","c
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 
diff --git a/transform/xslt/README.md b/transform/xslt/README.md
index 47df8a3..4d79939 100644
--- a/transform/xslt/README.md
+++ b/transform/xslt/README.md
@@ -16,7 +16,8 @@ INFO ... xslt.camel.yaml:16 : Packing slip:
 
 ## Install Camel CLI
 
-<!-- see installation instructions in ../../install.adoc -->
+Install [JBang](https://www.jbang.dev/download/) and the Camel CLI as 
described in the
+[root README](../../README.md#install-the-camel-cli); `camel --version` 
confirms the install.
 
 ## Run it
 

Reply via email to