Add project training template, dark theme, catalog infrastructure

- Template with AGENT_INSTRUCTIONS.md and README
- Dark theme CSS (white on black, 32px font, fixed logos)
- Removed persistent header/footer from document.html.slim
- Oak leaf logo in shared resources
- Tag-based catalog page with filtering
- generate-catalog.py for building catalog.json
- Updated site.xml navigation
- RAT plugin excludes fix (deprecated -> inputExcludes)
diff --git a/content/Apache/Template/AGENT_INSTRUCTIONS.md b/content/Apache/Template/AGENT_INSTRUCTIONS.md
new file mode 100644
index 0000000..612af8c
--- /dev/null
+++ b/content/Apache/Template/AGENT_INSTRUCTIONS.md
@@ -0,0 +1,369 @@
+# Agent Instructions: Generating a New Training Module
+
+These instructions are for an AI agent tasked with generating a new Apache
+project training presentation from the Template. Follow them exactly.
+
+## Overview
+
+You are generating a reveal.js AsciiDoc presentation for an Apache project.
+The output must build cleanly with Maven and render as a dark-themed slide
+deck viewable in a browser.
+
+## CRITICAL: Research First, Write Second
+
+**DO NOT rely on training data or general knowledge for ANY project-specific
+facts.** Your training data is stale and often wrong. Projects rename things,
+spin off sub-projects, change installation steps, and deprecate features
+constantly. You MUST research every claim by fetching live documentation.
+
+### Research Phase (MANDATORY — do this BEFORE writing any slides)
+
+For each presentation, you must fetch and read the following pages:
+
+1. **Project homepage** — `https://PROJECT_ID.apache.org`
+   - What does the project call itself? (Don't assume — projects rename)
+   - What is the current tagline/description in their own words?
+   - What sub-projects or components exist? Are any now separate TLPs?
+
+2. **Getting Started / Quick Start page** — find this from the homepage nav
+   - What are the actual prerequisites?
+   - What are the exact install commands?
+   - What does the first-run experience look like?
+   - What port does it run on? What's the default URL?
+
+3. **Download page** — `https://PROJECT_ID.apache.org/download` or similar
+   - What is the current version?
+   - What package formats are available?
+   - Is there a Docker image? What's its exact name?
+
+4. **Community / Contributing page**
+   - What are the actual mailing list addresses?
+   - Where is the issue tracker? (Jira? GitHub Issues? Both?)
+   - Where is the source code? (GitHub? GitBox? Multiple repos?)
+
+5. **Apache committee data** — use the apache_projects tools to verify:
+   - Is this project still an active TLP? (Check it hasn't retired to Attic)
+   - How many PMC members / committers?
+   - When was it established?
+   - Are there related projects that have split off?
+
+### Content Rules Based on Research
+
+- Use the EXACT terminology the project uses on their website
+- If the project calls something "XYZ" on their docs, use "XYZ" — not what
+  you think it "used to be" or "should be" called
+- If you cannot verify a fact from a live source, DO NOT include it
+- When in doubt, leave a TODO comment for human review:
+  `// TODO: Verify this against PROJECT_ID.apache.org — could not confirm`
+
+### Human Review Required
+
+Every generated presentation MUST be reviewed by a human familiar with the
+project before it is published. The agent's job is to produce a well-structured
+draft with researched content — but mistakes will happen, and only someone
+who uses the project can catch subtle errors in terminology, architecture
+descriptions, or getting-started flows.
+
+Flag anything uncertain with a comment:
+```asciidoc
+// TODO: Human review — verify this is still the correct install process
+```
+
+## File Structure to Create
+
+Copy the Template directory and produce these files:
+
+```
+content/Apache/<ProjectName>/
+├── pom.xml
+├── metadata.yaml
+└── src/
+    └── main/
+        ├── asciidoc/
+        │   ├── _settings.adoc       (copy from Template, do not modify)
+        │   ├── images/
+        │   │   └── project-logo.png  (download from https://apache.org/logos/res/<project_id>/default.png)
+        │   └── index.adoc            (the presentation — YOU WRITE THIS)
+        └── theme/
+            └── apache.css            (copy from Template, do not modify)
+```
+
+## pom.xml
+
+Use this exact structure (only change the artifactId and name):
+
+```xml
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.training</groupId>
+    <artifactId>content-parent-pom</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath>../../../tools/content-parent-pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.training.content</groupId>
+  <artifactId>training-content-apache-PROJECT_ID</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+
+  <name>Training: Content: Apache: PROJECT_NAME</name>
+  <description>Training module for Apache PROJECT_NAME</description>
+
+</project>
+```
+
+## metadata.yaml
+
+Must have the ASF license header. Example:
+
+```yaml
+# 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.
+
+title: "Apache PROJECT_NAME"
+project_id: PROJECT_ID
+description: "One-line description"
+tags:
+  - relevant-tag
+  - intro
+  - developer
+duration: "45-60 min"
+level: beginner
+language: java
+slides: 25
+updated: "YYYY-MM-DD"
+```
+
+## index.adoc — THE PRESENTATION
+
+This is where all the content goes. Follow these rules EXACTLY:
+
+### Rule 1: ASF License Header
+
+The file MUST start with:
+
+```asciidoc
+////
+
+  Licensed to the Apache Software Foundation (ASF) under one or more
+  contributor license agreements.  ...full header...
+
+////
+```
+
+### Rule 2: Settings Include
+
+Immediately after the license header:
+
+```asciidoc
+include::_settings.adoc[]
+:presenter_name: Your Name
+:presenter_company: Your Company
+:description: Introduction to Apache PROJECT_NAME
+:keywords: Apache, PROJECT_NAME
+:author: Your Name
+:email: Your email
+:position: Your role
+```
+
+DO NOT add `:revealjsdir:`, `:revealjs_slideNumber:`, or `:revealjs_theme:`
+attributes. Maven handles all of these.
+
+### Rule 3: NO PREAMBLE — Title Slide is the First == Section
+
+**CRITICAL**: The FIRST content after the attributes MUST be a `==` section.
+NEVER put content (images, text, blocks) before the first `==`.
+
+Content before `==` becomes a PERSISTENT overlay on every slide. This is the
+single most common mistake.
+
+✅ CORRECT:
+```asciidoc
+== Apache PROJECT_NAME
+
+image::project-logo.png[Apache PROJECT_NAME, 500]
+
+*Your project tagline here*
+```
+
+❌ WRONG (creates persistent overlay on ALL slides):
+```asciidoc
+[.text-center]
+====
+image::logo.png[width=400]
+Title
+====
+
+== First Slide
+```
+
+❌ ALSO WRONG (= creates document title/preamble):
+```asciidoc
+= Apache PROJECT_NAME
+
+== First Slide
+```
+
+### Rule 4: Use ONLY == for Slides
+
+Every slide MUST use `==` (level 2 heading). 
+
+- `==` = a new slide ✅
+- `===` = a vertical sub-slide (DO NOT USE — they don't render properly) ❌
+- `=` = document title/preamble (DO NOT USE) ❌
+
+### Rule 5: Content Limits Per Slide
+
+These are HARD LIMITS. Violating them causes text to overflow off-screen:
+
+| Element | Maximum |
+|---------|---------|
+| Bullet points | 4–5 |
+| Table rows (data) | 4–5 |
+| Code block lines | 6–8 |
+| Total visible text lines | 6–7 |
+
+If you have more content, SPLIT into multiple slides with clear titles.
+
+### Rule 6: Never Combine Bullets + Large Image
+
+If a slide has an image AND more than 2 bullet points, split it:
+- Slide A: the explanation bullets
+- Slide B: the image with a brief caption
+
+### Rule 7: Never Name the Project Chair
+
+Apache is about community, not individuals. The PMC Chair role rotates.
+Do not include the name of the current chair anywhere in the presentation.
+You may explain the PMC Chair *role* generically in the governance section.
+
+### Rule 8: Speaker Notes
+
+Add `[.notes]` blocks for instructor context. These don't appear on screen:
+
+```asciidoc
+[.notes]
+--
+Explain why this matters. Mention common misconceptions.
+Suggest a demo at this point in the presentation.
+--
+```
+
+### Rule 9: Three-Part Structure
+
+Target ~25 slides total, organized as:
+
+**Part 1: What Is It? (~8 slides)**
+- Title slide (logo + tagline)
+- What is it? (elevator pitch, 3-4 bullets)
+- Problem it solves / why it exists
+- Key features (4-5 bullets max)
+- Architecture overview (brief, not a diagram dump)
+- Use cases (3-4 with examples)
+- Project vitals (PMC size, contributor count, established year — NO chair name)
+
+**Part 2: Installation & Getting Started (~8 slides)**
+- Prerequisites (OS, language, runtime)
+- Install methods (one slide per method, keep commands to 4-6 lines)
+- Hello World (simplest possible working example)
+- Configuration basics (3-4 key settings)
+- Next steps / where to go deeper
+
+**Part 3: Community Participation (~7 slides)**
+- Communication channels (mailing lists, chat, GitHub — bullets not tables)
+- How to contribute (5 steps max)
+- Types of contributions (code, docs, testing, support — 4-5 bullets)
+- Governance roles (User → Contributor → Committer → PMC, explained briefly)
+- Resources & links (4-5 bullets max)
+- Thank you / Q&A slide
+
+### Rule 10: Code Blocks
+
+Use `[source,language]` blocks:
+
+```asciidoc
+[source,bash]
+----
+./bin/start.sh
+curl http://localhost:8080/health
+----
+```
+
+Keep code blocks to 6-8 lines MAX. If a real example is longer, show only
+the essential lines with comments indicating what's omitted.
+
+### Rule 11: Slide Title Style
+
+- Keep titles short (3-5 words)
+- Use sentence case, not UPPERCASE
+- Be specific: "Install with Docker" not "Installation Method 2"
+
+### Rule 12: Image References
+
+For the title slide, reference the local project logo:
+```asciidoc
+image::project-logo.png[Apache PROJECT_NAME, 500]
+```
+
+For architecture diagrams or screenshots, use external URLs if stable:
+```asciidoc
+image::https://project.apache.org/img/architecture.png[width=70%]
+```
+
+Keep image width to 70% max to leave room for the fixed logos.
+
+## Build & Verify
+
+After generating all files:
+
+```bash
+cd content/Apache/ProjectName
+rm -rf target .asciidoctor
+../../../mvnw process-resources -Drat.skip=true
+open target/generated-slides/index.html
+```
+
+## Common Mistakes to Avoid
+
+1. **Using `===` instead of `==`** → slides won't render as separate pages
+2. **Content before first `==`** → persistent overlay on every slide
+3. **Using `= Title`** → creates document preamble, same problem
+4. **More than 5 bullets** → text overflows off bottom of screen
+5. **Code blocks > 8 lines** → overflows
+6. **Naming the project chair** → individuals change; Apache is community-first
+7. **Adding `:revealjsdir:` in the adoc** → conflicts with Maven build
+8. **Tables with 6+ rows** → overflow
+9. **Bullets + image on same slide** → overflow
+10. **Referencing `project-logo.svg`** → the file is `.png` (from apache.org/logos)
diff --git a/content/Apache/Template/README.md b/content/Apache/Template/README.md
new file mode 100644
index 0000000..39f96dd
--- /dev/null
+++ b/content/Apache/Template/README.md
@@ -0,0 +1,281 @@
+# Apache Project Training Module Template
+
+This is the template for creating training modules for Apache projects.
+Copy this entire directory to create a new module.
+
+## Quick Start
+
+```bash
+# 1. Copy the template
+cp -r Template/ YourProject/
+
+# 2. Update pom.xml (artifactId and name)
+# 3. Replace project-logo.svg with your project's logo
+# 4. Edit index.adoc — fill in all TODO sections
+# 5. Build
+cd YourProject
+../../../mvnw process-resources -Drat.skip=true
+open target/generated-slides/index.html
+```
+
+## Directory Structure
+
+```
+Template/
+├── pom.xml                              # Maven build descriptor
+├── metadata.yaml                        # Tags for catalog filtering
+├── README.md                            # This file
+└── src/
+    └── main/
+        ├── asciidoc/
+        │   ├── _settings.adoc           # Reveal.js presentation settings
+        │   ├── images/
+        │   │   └── project-logo.svg     # YOUR PROJECT LOGO (required)
+        │   └── index.adoc              # Main presentation content
+        └── theme/
+            └── apache.css              # Dark theme CSS (do not modify)
+```
+
+## Build Instructions
+
+### Prerequisites
+
+- Java 11+
+- Maven (or use the included `mvnw` wrapper)
+
+### First-Time Setup
+
+Before building any module for the first time, install the shared tools:
+
+```bash
+cd /path/to/training/tools
+../mvnw install
+```
+
+This installs the parent POM, shared resources (including the ASF oak leaf
+logo), and the HTML template into your local Maven repository.
+
+### Building a Module
+
+```bash
+cd content/Apache/YourProject
+../../../mvnw process-resources -Drat.skip=true
+```
+
+The rendered HTML presentation will be at:
+```
+target/generated-slides/index.html
+```
+
+Open it directly in a browser — it's a self-contained reveal.js presentation.
+
+**Important phases:**
+- `generate-resources` — downloads reveal.js, copies theme/images (no slides yet)
+- `process-resources` — converts AsciiDoc to HTML slides ← **use this one**
+- `package` — full build including license checks (WAR output)
+
+### Troubleshooting
+
+| Problem | Fix |
+|---------|-----|
+| `Could not find artifact org.apache.training:training-tools:pom` | Run `mvnw install` from the `tools/` directory |
+| RAT license check fails on `metadata.yaml` | Ensure the file has the ASF license header (see existing files) |
+| Stale output after editing | Delete `target/` AND `.asciidoctor/` then rebuild |
+| White background instead of dark | Ensure `src/main/theme/apache.css` is present (not modified) |
+
+## Creating a New Module
+
+### Step 1: Copy and Rename
+
+```bash
+cp -r content/Apache/Template/ content/Apache/YourProject/
+```
+
+### Step 2: Update `pom.xml`
+
+Change these two lines:
+```xml
+<artifactId>training-content-apache-yourproject</artifactId>
+<name>Training: Content: Apache: YourProject</name>
+```
+
+Keep the parent POM reference as-is (`1.5.0-SNAPSHOT`).
+
+### Step 3: Add Your Project Logo
+
+Replace `src/main/asciidoc/images/project-logo.svg` with your project's
+actual logo. This appears in the **top-left corner** of every slide.
+
+Get official logos from: https://apache.org/logos
+
+Requirements:
+- SVG format preferred (renders crisp at any size)
+- Horizontal/landscape orientation works best (displayed at 120×36px)
+- Filename must be exactly `project-logo.svg`
+
+### Step 4: Update `metadata.yaml`
+
+Fill in the project details and tags for the catalog:
+
+```yaml
+title: "Apache YourProject"
+project_id: yourproject
+description: "One-line description"
+tags:
+  - relevant-domain-tag
+  - intro
+  - developer
+duration: "45-60 min"
+level: beginner
+language: java  # or python, scala, etc.
+slides: 25
+updated: "2026-01-01"
+```
+
+Standard tags:
+- **Domain:** big-data, streaming, messaging, database, web, ml-ai, iot,
+  build-tools, libraries, security, search, cloud, governance
+- **Type:** intro, deep-dive, hands-on, overview
+- **Ecosystem:** hadoop-ecosystem, jvm, python-ecosystem
+- **Audience:** developer, operator, data-engineer, contributor
+
+### Step 5: Write the Presentation Content
+
+Edit `src/main/asciidoc/index.adoc`. The template has three parts:
+
+1. **What is it?** (~8 slides) — problem it solves, features, architecture, use cases
+2. **Installation & Getting Started** (~8 slides) — prerequisites, install, hello world
+3. **Community Participation** (~8 slides) — channels, contributing, governance
+
+## Slide Design Rules
+
+### Content Limits Per Slide
+
+These are hard rules — violating them causes text to overflow off-screen:
+
+| Element | Maximum |
+|---------|---------|
+| Bullet points | 4–5 |
+| Table rows | 4–5 |
+| Code block lines | 8–10 |
+| Lines of text total | 6–7 |
+
+**If a slide has BOTH bullets AND an image, split into two slides.**
+
+### When to Split
+
+Split a slide when:
+- Content would scroll below the visible area
+- You have more than 5 bullet points
+- **Never name the project chair** — it changes frequently and Apache is about community, not individuals. The governance slide can explain the PMC Chair *role* generically.
+- A code example exceeds 10 lines
+- A table has more than 5 rows
+- You have an image plus more than 2 bullet points
+
+### AsciiDoc Slide Syntax
+
+```asciidoc
+== Slide Title            ← creates a new slide (h2)
+
+Bullet points:
+* Point one
+* Point two
+* Point three
+
+Code:
+[source,bash]
+----
+echo "hello world"
+----
+
+Speaker notes (not shown on screen):
+[.notes]
+--
+These notes are for the instructor only.
+--
+```
+
+### Critical: No Preamble Content
+
+**NEVER** put content before the first `==` section. In reveal.js, preamble
+content becomes a persistent title that overlays every subsequent slide.
+
+✅ Correct:
+```asciidoc
+include::_settings.adoc[]
+:author: Your Name
+
+== Apache YourProject        ← first slide
+
+image::project-logo.svg[width=300]
+
+Your tagline here
+```
+
+❌ Wrong (creates persistent overlay):
+```asciidoc
+include::_settings.adoc[]
+
+[.text-center]
+====
+image::logo.svg[width=300]
+Title text
+====
+
+== First Real Slide          ← too late, overlay already set
+```
+
+## Visual Theme
+
+The presentation uses a dark theme optimized for conference rooms:
+
+- **Background:** Dark (#1a1a1a)
+- **Text:** White/light (#f0f0f0)
+- **Font:** 32px base, Segoe UI / Helvetica / Arial
+- **Headers:** Compact (h2 at 1.0em — same visual weight as body, just bold)
+- **Code blocks:** Dark grey background with light text
+- **Links:** Blue (#42affa)
+
+### Logo Placement
+
+| Logo | Position | Source |
+|------|----------|--------|
+| Project logo | Top-left (fixed) | `src/main/asciidoc/images/project-logo.svg` |
+| ASF oak leaf | Bottom-left (fixed) | Shared resources (`logo-apache.png`) |
+
+Both logos are fixed to the viewport — they don't scroll with content.
+
+### Theme CSS
+
+The file `src/main/theme/apache.css` provides the dark theme. **Do not modify
+it** unless you want to diverge from the standard look. It overrides the
+default white reveal.js theme and adds:
+
+- Dark background on `.reveal-viewport`
+- White text everywhere
+- Compact headers
+- Fixed-position logos
+- Scroll overflow safety for long slides
+
+## Catalog & Navigation
+
+The site uses tag-based filtering instead of a giant nav menu:
+
+1. Each module has a `metadata.yaml` with tags
+2. Run `python3 tools/generate-catalog.py` to regenerate `catalog.json`
+3. The catalog page (`site/src/site/asciidoc/catalog.adoc`) renders a
+   filterable card grid
+
+After adding a new module, always regenerate the catalog.
+
+## License Headers
+
+All source files need an Apache License 2.0 header:
+
+- `.adoc` files: Use `////` comment blocks
+- `.yaml` files: Use `#` comment lines
+- `.css` files: Use `/* */` comment blocks
+- `.xml` files: Use `<!-- -->` comment blocks
+
+The RAT plugin checks this during `mvnw package`. Use `-Drat.skip=true`
+during development to skip the check.
diff --git a/content/Apache/Template/metadata.yaml b/content/Apache/Template/metadata.yaml
new file mode 100644
index 0000000..f311430
--- /dev/null
+++ b/content/Apache/Template/metadata.yaml
@@ -0,0 +1,51 @@
+# 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.
+
+# Training Module Metadata
+# ========================
+# Each training module should include a metadata.yaml file in its root directory.
+# This file is used to generate the site catalog with tag-based filtering.
+#
+# Required fields:
+#   title       - Display name of the module
+#   project_id  - Apache project identifier (lowercase)
+#   description - One-line summary (shown in catalog cards)
+#   tags        - List of tags for filtering (see standard tags below)
+#
+# Optional fields:
+#   duration    - Estimated presentation length (e.g., "45 min", "2 hours")
+#   level       - beginner | intermediate | advanced
+#   language    - Programming language focus (java, python, scala, etc.)
+#   updated     - Last updated date (YYYY-MM-DD)
+#   author      - Original author or contributor
+#   slides      - Number of slides
+#
+# Standard tags (use these where applicable for consistency):
+#   Domain:     big-data, streaming, messaging, database, web, ml-ai, iot,
+#               build-tools, libraries, security, search, cloud, governance
+#   Type:       intro, deep-dive, hands-on, overview
+#   Ecosystem:  hadoop-ecosystem, jvm, python-ecosystem
+#   Audience:   developer, operator, data-engineer, contributor
+
+title: "Template"
+project_id: template
+description: "Template for creating new Apache project training modules"
+tags:
+  - governance
+  - intro
+duration: "45-60 min"
+level: beginner
+slides: 25
+updated: "2026-05-24"
diff --git a/content/Apache/Template/pom.xml b/content/Apache/Template/pom.xml
new file mode 100644
index 0000000..5d1ddd1
--- /dev/null
+++ b/content/Apache/Template/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+  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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.training</groupId>
+    <artifactId>content-parent-pom</artifactId>
+    <version>1.5.0-SNAPSHOT</version>
+    <relativePath>../../../tools/content-parent-pom/pom.xml</relativePath>
+  </parent>
+
+  <groupId>org.apache.training.content</groupId>
+  <artifactId>training-content-apache-template</artifactId>
+  <version>1.0.0-SNAPSHOT</version>
+  <packaging>war</packaging>
+
+  <name>Training: Content: Apache: Template</name>
+  <description>Template module for creating new Apache project training decks</description>
+
+</project>
diff --git a/content/Apache/Template/src/main/asciidoc/_settings.adoc b/content/Apache/Template/src/main/asciidoc/_settings.adoc
new file mode 100644
index 0000000..9a16917
--- /dev/null
+++ b/content/Apache/Template/src/main/asciidoc/_settings.adoc
@@ -0,0 +1,36 @@
+////
+
+  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.
+
+////
+
+:goto:
+:menu:
+:navigation:
+:status:
+:arrows:
+:revealjs_theme: black
+:revealjs_progress: true
+:revealjs_slidenumber: true
+:revealjs_center: false
+:revealjs_history: true
+:customcss: reveal.js-5.2.1/dist/theme/apache.css
+:favicon: https://apache.org/favicon.ico
+:icons: font
+:imagesdir: images
+:sourcedir: ../java
+:idprefix:
+:idseparator: -
diff --git a/content/Apache/Template/src/main/asciidoc/images/project-logo.svg b/content/Apache/Template/src/main/asciidoc/images/project-logo.svg
new file mode 100644
index 0000000..fbb755d
--- /dev/null
+++ b/content/Apache/Template/src/main/asciidoc/images/project-logo.svg
Binary files differ
diff --git a/content/Apache/Template/src/main/asciidoc/index.adoc b/content/Apache/Template/src/main/asciidoc/index.adoc
new file mode 100644
index 0000000..a926eb6
--- /dev/null
+++ b/content/Apache/Template/src/main/asciidoc/index.adoc
@@ -0,0 +1,368 @@
+////
+
+  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.
+
+////
+
+include::_settings.adoc[]
+:presenter_name: Your Name
+:presenter_company: Your Company
+:description: Introduction to Apache PROJECT_NAME
+:keywords: Apache, PROJECT_NAME
+:author: Your Name
+:email: Your email
+:position: Your role
+
+// ============================================================
+// TEMPLATE INSTRUCTIONS
+// ============================================================
+// Replace all instances of PROJECT_NAME with the actual project name.
+// Replace PROJECT_ID with the lowercase project identifier (e.g., "kafka").
+// Replace PROJECT_LOGO_URL with the project's logo URL or local image path.
+// Fill in each section with project-specific content.
+// Remove this comment block before publishing.
+// ============================================================
+
+== Apache PROJECT_NAME
+
+image::PROJECT_LOGO_URL[width=400, align=center]
+
+Introduction to Apache PROJECT_NAME
+
+== Who am I?
+{author} +
+{position} +
+{email} +
+
+// ============================================================
+// PART 1: WHAT IS IT?
+// ============================================================
+
+== What is Apache PROJECT_NAME?
+
+// One-paragraph elevator pitch: what problem does it solve?
+// Example: "Apache Kafka is a distributed event streaming platform
+// used by thousands of companies for high-performance data pipelines,
+// streaming analytics, data integration, and mission-critical applications."
+
+TODO: Write a concise description of what the project does and why it exists.
+
+== The Problem it Solves
+
+// What pain point or gap existed before this project?
+// What were people using instead?
+
+TODO: Describe the problem space.
+
+[.notes]
+--
+Provide context on why this project was created.
+What alternatives existed? What was lacking?
+--
+
+== Key Features
+
+// Highlight 4-6 distinguishing capabilities
+
+* *Feature 1* — brief explanation
+* *Feature 2* — brief explanation
+* *Feature 3* — brief explanation
+* *Feature 4* — brief explanation
+
+[.notes]
+--
+Expand on each feature with examples or use cases.
+--
+
+== Architecture Overview
+
+// High-level architecture diagram or description.
+// Use an image if possible.
+
+image::architecture.png[]
+
+[.notes]
+--
+Describe the major components and how they interact.
+Keep it high-level — this is an intro, not a deep-dive.
+--
+
+== Use Cases
+
+// Who uses this and for what?
+
+[cols="2*", options="header"]
+|===
+| Use Case | Example Users
+
+| TODO: Use case 1
+| TODO: Example companies/projects
+
+| TODO: Use case 2
+| TODO: Example companies/projects
+
+| TODO: Use case 3
+| TODO: Example companies/projects
+|===
+
+== Project History
+
+// Brief timeline: inception, incubation, TLP graduation, major milestones.
+
+* *YYYY* — Project created at / donated by ___
+* *YYYY* — Entered Apache Incubator
+* *YYYY* — Graduated to Top-Level Project
+* *YYYY* — Major milestone (1.0 release, etc.)
+
+// ============================================================
+// PART 2: INSTALLATION & GETTING STARTED
+// ============================================================
+
+== Getting Started
+
+// What does a newcomer need to get up and running?
+
+=== Prerequisites
+
+* Operating System: ___
+* Language/Runtime: ___ (version ___)
+* Other dependencies: ___
+
+=== Installation Methods
+
+// List the common installation methods
+
+== Method 1: Package Manager
+
+// e.g., brew, apt, yum, pip, mvn dependency
+
+[source,bash]
+----
+# TODO: Add package manager install command
+# Example: brew install project_id
+----
+
+== Method 2: Download Binary Release
+
+* Download from: https://PROJECT_ID.apache.org/downloads.html
+* Verify checksums and signatures (https://www.apache.org/info/verification.html[ASF verification guide])
+
+[source,bash]
+----
+# TODO: Extract and run commands
+tar -xzf apache-PROJECT_ID-X.Y.Z-bin.tar.gz
+cd apache-PROJECT_ID-X.Y.Z
+./bin/start.sh
+----
+
+== Method 3: Docker
+
+[source,bash]
+----
+# TODO: Docker run command
+docker run -d --name project_id apache/PROJECT_ID:latest
+----
+
+== Method 4: Build from Source
+
+[source,bash]
+----
+git clone https://github.com/apache/PROJECT_ID.git
+cd PROJECT_ID
+# TODO: Build commands (mvn, gradle, make, etc.)
+----
+
+== Verifying the Installation
+
+// How does the user confirm it's working?
+
+[source,bash]
+----
+# TODO: Verification command
+# Example: project_id --version
+# Example: curl http://localhost:8080/health
+----
+
+== Hello World
+
+// Minimal working example — the simplest possible use of the project.
+
+[source,java]
+----
+// TODO: Replace with a minimal code example in the project's
+// primary language. Keep it under 20 lines.
+----
+
+[.notes]
+--
+This should be something the learner can type in and see
+results within 2 minutes of completing installation.
+--
+
+== Configuration Basics
+
+// What are the most important configuration knobs a beginner
+// needs to know about?
+
+* *Config file location*: ___
+* *Key setting 1*: what it controls
+* *Key setting 2*: what it controls
+* *Key setting 3*: what it controls
+
+== Next Steps
+
+// Where does the learner go after "Hello World"?
+
+* Official tutorials: https://PROJECT_ID.apache.org/docs/tutorial
+* Example projects: https://github.com/apache/PROJECT_ID/tree/main/examples
+* API documentation: https://PROJECT_ID.apache.org/docs/api
+
+// ============================================================
+// PART 3: PARTICIPATING IN THE COMMUNITY
+// ============================================================
+
+== The Apache PROJECT_NAME Community
+
+// Brief overview of community size, activity level, governance.
+
+* PMC members: ___ | Committers: ___ | Contributors: ___
+* Releases per year: ___
+* Active since: ___
+
+== Communication Channels
+
+// Where does discussion happen?
+
+[cols="3*", options="header"]
+|===
+| Channel | URL | Purpose
+
+| Dev mailing list
+| https://lists.apache.org/list.html?dev@PROJECT_ID.apache.org[Archive] — mailto:dev-subscribe@PROJECT_ID.apache.org[Subscribe]
+| Technical discussion, design proposals, releases
+
+| User mailing list
+| https://lists.apache.org/list.html?user@PROJECT_ID.apache.org[Archive] — mailto:user-subscribe@PROJECT_ID.apache.org[Subscribe]
+| End-user questions and support
+
+| Slack / Discord / IRC
+| TODO: Link if applicable
+| Real-time chat (informal)
+
+| GitHub Discussions
+| TODO: Link if applicable
+| Longer-form Q&A
+|===
+
+[.notes]
+--
+At Apache, the mailing list is the official channel of record.
+Decisions made elsewhere (Slack, etc.) must be brought back to
+the mailing list to be binding ("if it didn't happen on the
+mailing list, it didn't happen").
+--
+
+== Issue Tracking
+
+* *Bug reports*: TODO: Jira or GitHub Issues link
+* *Feature requests*: TODO: Same or separate link
+* *Good first issues*: TODO: Filtered link for newcomers
+
+== How to Contribute
+
+=== The Apache Way (quick overview)
+
+* Community over code
+* Earned authority (meritocracy)
+* Lazy consensus
+* Open development — all discussion on public mailing lists
+
+=== Contribution Workflow
+
+. *Find an issue* — browse "good first issue" labels or ask on dev@
+. *Discuss your approach* — email the dev list or comment on the issue
+. *Fork and branch* — `git checkout -b my-feature`
+. *Make your change* — follow the project's coding standards
+. *Test* — run the project's test suite
+. *Submit a PR* — reference the issue number
+. *Respond to review* — iterate based on feedback
+. *Celebrate* 🎉 — your contribution is merged!
+
+== Beyond Code
+
+// Not all contributions require writing code.
+
+* *Documentation* — fix typos, improve guides, translate
+* *Testing* — reproduce bugs, write test cases
+* *Triage* — help categorize and prioritize issues
+* *User support* — answer questions on the user@ list
+* *Evangelism* — write blog posts, give talks, create tutorials
+
+== Governance & Roles
+
+[cols="2*", options="header"]
+|===
+| Role | Description
+
+| *User*
+| Anyone using the software
+
+| *Contributor*
+| Someone who has submitted patches or helped the project
+
+| *Committer*
+| Earned write access to the repository (voted in by PMC)
+
+| *PMC Member*
+| Project Management Committee — responsible for releases, community health, and project direction
+
+| *PMC Chair*
+| Administrative liaison to the ASF Board
+|===
+
+== Code of Conduct
+
+The Apache Software Foundation follows the
+https://www.apache.org/foundation/policies/conduct.html[ASF Code of Conduct].
+
+All participants are expected to be respectful, constructive, and inclusive.
+
+// ============================================================
+// WRAP-UP
+// ============================================================
+
+== Further Resources
+
+* *Project website*: https://PROJECT_ID.apache.org
+* *Documentation*: https://PROJECT_ID.apache.org/docs
+* *Source code*: https://github.com/apache/PROJECT_ID
+* *Blog*: https://PROJECT_ID.apache.org/blog (if applicable)
+* *ASF-wide resources*:
+** https://community.apache.org[Apache Community Development]
+** https://www.apache.org/foundation/how-it-works.html[How the ASF Works]
+
+== Questions?
+
+image::PROJECT_LOGO_URL[width=200, align=center]
+
+* dev@PROJECT_ID.apache.org
+* https://PROJECT_ID.apache.org
+
+[.notes]
+--
+Open the floor for questions.
+Remind attendees they can reach the community on the mailing list.
+--
diff --git a/content/Apache/Template/src/main/theme/apache.css b/content/Apache/Template/src/main/theme/apache.css
new file mode 100644
index 0000000..d8f2a14
--- /dev/null
+++ b/content/Apache/Template/src/main/theme/apache.css
@@ -0,0 +1,457 @@
+/*
+  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
+
+    https://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.
+*/
+
+/*********************************************
+ * APACHE TRAINING DARK THEME
+ * White text on black, large fonts for
+ * conference room visibility.
+ *********************************************/
+
+/*********************************************
+ * GLOBAL STYLES
+ *********************************************/
+body {
+  background-color: #1a1a1a;
+  background-image: none;
+}
+
+.reveal-viewport {
+  background-color: #1a1a1a;
+  color: #f0f0f0;
+  background-image: none !important;
+}
+
+.reveal {
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-size: 32px;
+  font-weight: normal;
+  color: #f0f0f0;
+}
+
+/*********************************************
+ * SLIDE OVERFLOW — allow scrolling if content
+ * exceeds slide height
+ *********************************************/
+.reveal .slides section {
+  height: auto !important;
+  overflow-y: auto !important;
+}
+
+::selection {
+  color: #fff;
+  background: #42affa;
+  text-shadow: none;
+}
+
+.reveal .slides > section, .reveal .slides > section > section {
+  line-height: 1.4;
+  font-weight: inherit;
+}
+
+/*********************************************
+ * HEADERS — smaller than default
+ *********************************************/
+.reveal h1, .reveal h2, .reveal h3, .reveal h4, .reveal h5, .reveal h6 {
+  margin: 0 0 20px 0;
+  color: #ffffff;
+  font-family: "Segoe UI", Helvetica, Arial, sans-serif;
+  font-weight: 600;
+  line-height: 1.2;
+  letter-spacing: normal;
+  text-transform: none;
+  text-shadow: none;
+  word-wrap: break-word;
+}
+
+.reveal h1 {
+  font-size: 1.4em;
+}
+
+.reveal h2 {
+  font-size: 1.0em;
+}
+
+.reveal h3 {
+  font-size: 0.9em;
+}
+
+.reveal h4 {
+  font-size: 0.8em;
+}
+
+/*********************************************
+ * BODY TEXT — large for back-of-room
+ *********************************************/
+.reveal p {
+  margin: 20px 0;
+  line-height: 1.4;
+  font-size: 1em;
+}
+
+.reveal li {
+  font-size: 0.95em;
+  margin-bottom: 0.3em;
+}
+
+/* Ensure certain elements are never larger than the slide itself */
+.reveal img, .reveal video, .reveal iframe {
+  max-width: 95%;
+  max-height: 85%;
+}
+
+.reveal strong, .reveal b {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal em {
+  font-style: italic;
+}
+
+.reveal ol, .reveal dl, .reveal ul {
+  display: inline-block;
+  text-align: left;
+  margin: 0 0 0 1em;
+}
+
+.reveal ol {
+  list-style-type: decimal;
+}
+
+.reveal ul {
+  list-style-type: disc;
+}
+
+.reveal ul ul {
+  list-style-type: square;
+}
+
+.reveal ul ul ul {
+  list-style-type: circle;
+}
+
+.reveal ul ul, .reveal ul ol, .reveal ol ol, .reveal ol ul {
+  display: block;
+  margin-left: 40px;
+}
+
+.reveal dt {
+  font-weight: bold;
+}
+
+.reveal dd {
+  margin-left: 40px;
+}
+
+.reveal q, .reveal blockquote {
+  quotes: none;
+}
+
+.reveal blockquote {
+  display: block;
+  position: relative;
+  width: 70%;
+  margin: 20px auto;
+  padding: 5px;
+  font-style: italic;
+  background: rgba(255, 255, 255, 0.05);
+  box-shadow: 0 0 2px rgba(255, 255, 255, 0.2);
+  color: #ccc;
+}
+
+.reveal blockquote p:first-child, .reveal blockquote p:last-child {
+  display: inline-block;
+}
+
+.reveal q {
+  font-style: italic;
+}
+
+/*********************************************
+ * CODE
+ *********************************************/
+.reveal pre {
+  display: block;
+  position: relative;
+  width: 90%;
+  margin: 20px auto;
+  text-align: left;
+  font-size: 0.55em;
+  font-family: "Fira Code", "Consolas", monospace;
+  line-height: 1.3em;
+  word-wrap: break-word;
+  box-shadow: 0 0 6px rgba(0, 0, 0, 0.3);
+}
+
+.reveal code {
+  font-family: "Fira Code", "Consolas", monospace;
+}
+
+.reveal pre code {
+  display: block;
+  padding: 10px;
+  overflow: auto;
+  max-height: 450px;
+  word-wrap: normal;
+  background: #2d2d2d;
+  color: #e0e0e0;
+  border-radius: 4px;
+}
+
+/*********************************************
+ * TABLES
+ *********************************************/
+.reveal table {
+  margin: auto;
+  border-collapse: collapse;
+  border-spacing: 0;
+}
+
+.reveal table th {
+  font-weight: bold;
+  color: #ffffff;
+}
+
+.reveal table th, .reveal table td {
+  text-align: left;
+  padding: 0.3em 0.6em;
+  border-bottom: 1px solid #555;
+  color: #e0e0e0;
+}
+
+.reveal table th[align="center"], .reveal table td[align="center"] {
+  text-align: center;
+}
+
+.reveal table th[align="right"], .reveal table td[align="right"] {
+  text-align: right;
+}
+
+.reveal table tr:last-child td {
+  border-bottom: none;
+}
+
+.reveal sup {
+  vertical-align: super;
+}
+
+.reveal sub {
+  vertical-align: sub;
+}
+
+.reveal small {
+  display: inline-block;
+  font-size: 0.6em;
+  line-height: 1.2em;
+  vertical-align: top;
+}
+
+.reveal small * {
+  vertical-align: top;
+}
+
+/*********************************************
+ * LINKS
+ *********************************************/
+.reveal a {
+  color: #42affa;
+  text-decoration: none;
+  -webkit-transition: color 0.15s ease;
+  -moz-transition: color 0.15s ease;
+  transition: color 0.15s ease;
+}
+
+.reveal a:hover {
+  color: #8dcffc;
+  text-shadow: none;
+  border: none;
+}
+
+.reveal .roll span:after {
+  color: #fff;
+  background: #068ee9;
+}
+
+/*********************************************
+ * IMAGES
+ *********************************************/
+.reveal section img {
+  margin: 15px 0;
+}
+
+.reveal a img {
+  -webkit-transition: all 0.15s linear;
+  -moz-transition: all 0.15s linear;
+  transition: all 0.15s linear;
+}
+
+.reveal a:hover img {
+  background: rgba(255, 255, 255, 0.2);
+  border-color: #42affa;
+  box-shadow: 0 0 20px rgba(0, 0, 0, 0.55);
+}
+
+/*********************************************
+ * NAVIGATION CONTROLS
+ *********************************************/
+.reveal .controls div.navigate-left, .reveal .controls div.navigate-left.enabled {
+  border-right-color: #42affa;
+}
+
+.reveal .controls div.navigate-right, .reveal .controls div.navigate-right.enabled {
+  border-left-color: #42affa;
+}
+
+.reveal .controls div.navigate-up, .reveal .controls div.navigate-up.enabled {
+  border-bottom-color: #42affa;
+}
+
+.reveal .controls div.navigate-down, .reveal .controls div.navigate-down.enabled {
+  border-top-color: #42affa;
+}
+
+.reveal .controls div.navigate-left.enabled:hover {
+  border-right-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-right.enabled:hover {
+  border-left-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-up.enabled:hover {
+  border-bottom-color: #8dcffc;
+}
+
+.reveal .controls div.navigate-down.enabled:hover {
+  border-top-color: #8dcffc;
+}
+
+/*********************************************
+ * PROGRESS BAR
+ *********************************************/
+.reveal .progress {
+  background: rgba(255, 255, 255, 0.2);
+}
+
+.reveal .progress span {
+  background: #42affa;
+  -webkit-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  -moz-transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+  transition: width 800ms cubic-bezier(0.26, 0.86, 0.44, 0.985);
+}
+
+/*********************************************
+ * SLIDE NUMBER
+ *********************************************/
+.reveal .slide-number {
+  color: #888;
+  background-color: rgba(0, 0, 0, 0);
+}
+
+/*********************************************
+ * GENERAL PURPOSE COLORS
+ *********************************************/
+.reveal .red {
+  color: #ff4444;
+}
+
+.reveal .orange {
+  color: #ffaa44;
+}
+
+.reveal .yellow {
+  color: #ffff44;
+}
+
+.reveal .green {
+  color: #44ff44;
+}
+
+/*********************************************
+ * HIDE THE PERSISTENT HEADER/FOOTER from
+ * document.html.slim template
+ *********************************************/
+.header,
+.footer {
+  display: none !important;
+}
+
+/*********************************************
+ * PROJECT LOGO — small, top left of every slide
+ * Each module should place a project-logo.png
+ * in src/main/asciidoc/images/ OR override
+ * this rule in a local customcss with the
+ * project's logo URL.
+ *********************************************/
+.reveal::before {
+  content: "";
+  position: fixed;
+  top: 16px;
+  left: 16px;
+  width: 120px;
+  height: 36px;
+  background-image: url("../../../images/project-logo.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.7;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * APACHE OAK LEAF — bottom right of every slide
+ *********************************************/
+.reveal::after {
+  content: "";
+  position: fixed;
+  bottom: 16px;
+  left: 16px;
+  width: 36px;
+  height: 36px;
+  background-image: url("../../../images/logo-apache.png");
+  background-size: contain;
+  background-repeat: no-repeat;
+  opacity: 0.6;
+  z-index: 100;
+  pointer-events: none;
+}
+
+/*********************************************
+ * C3JS Charts (dark mode)
+ *********************************************/
+.c3 {
+  fill: white;
+}
+
+.c3 line, .c3 path {
+  stroke: white !important;
+}
+
+/*********************************************
+ * Column layout
+ *********************************************/
+.reveal .west {
+  position: fixed;
+  left: 5%;
+}
+
+.reveal .east {
+  position: fixed;
+  right: 5%;
+}
diff --git a/site/src/site/asciidoc/catalog.adoc b/site/src/site/asciidoc/catalog.adoc
new file mode 100644
index 0000000..aee5672
--- /dev/null
+++ b/site/src/site/asciidoc/catalog.adoc
@@ -0,0 +1,242 @@
+//
+//  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
+//
+//      https://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.
+//
+
+== Training Module Catalog
+
+Browse all available training modules. Use the tags below to filter by topic, technology, or audience.
+
+++++
+<style>
+  .catalog-search {
+    width: 100%;
+    max-width: 400px;
+    padding: 8px 12px;
+    font-size: 14px;
+    border: 1px solid #ccc;
+    border-radius: 4px;
+    margin-bottom: 16px;
+  }
+  .tag-filters {
+    margin-bottom: 20px;
+    display: flex;
+    flex-wrap: wrap;
+    gap: 6px;
+  }
+  .tag-chip {
+    display: inline-block;
+    padding: 4px 12px;
+    border-radius: 16px;
+    font-size: 13px;
+    cursor: pointer;
+    background: #e8e8e8;
+    color: #333;
+    border: 1px solid #ccc;
+    transition: all 0.2s;
+    user-select: none;
+  }
+  .tag-chip:hover {
+    background: #d0d0d0;
+  }
+  .tag-chip.active {
+    background: #d62d20;
+    color: white;
+    border-color: #d62d20;
+  }
+  .catalog-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+    gap: 16px;
+    margin-top: 16px;
+  }
+  .module-card {
+    border: 1px solid #ddd;
+    border-radius: 8px;
+    padding: 16px;
+    background: #fafafa;
+    transition: box-shadow 0.2s;
+  }
+  .module-card:hover {
+    box-shadow: 0 2px 8px rgba(0,0,0,0.12);
+  }
+  .module-card h3 {
+    margin: 0 0 8px 0;
+    font-size: 16px;
+  }
+  .module-card h3 a {
+    color: #d62d20;
+    text-decoration: none;
+  }
+  .module-card h3 a:hover {
+    text-decoration: underline;
+  }
+  .module-card .description {
+    font-size: 14px;
+    color: #555;
+    margin-bottom: 10px;
+  }
+  .module-card .meta {
+    font-size: 12px;
+    color: #888;
+    margin-bottom: 8px;
+  }
+  .module-card .tags {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 4px;
+  }
+  .module-card .tags span {
+    font-size: 11px;
+    background: #eee;
+    padding: 2px 8px;
+    border-radius: 10px;
+    color: #666;
+  }
+  .catalog-count {
+    font-size: 14px;
+    color: #666;
+    margin-bottom: 8px;
+  }
+  .no-results {
+    padding: 40px;
+    text-align: center;
+    color: #888;
+    font-size: 16px;
+  }
+</style>
+
+<input type="text" class="catalog-search" id="catalogSearch" placeholder="Search modules..." />
+
+<div class="tag-filters" id="tagFilters">
+  <!-- Tags populated by JavaScript -->
+</div>
+
+<div class="catalog-count" id="catalogCount"></div>
+
+<div class="catalog-grid" id="catalogGrid">
+  <!-- Cards populated by JavaScript -->
+</div>
+
+<script>
+(function() {
+  var catalog = null;
+  var activeTags = new Set();
+
+  function loadCatalog() {
+    var xhr = new XMLHttpRequest();
+    xhr.open('GET', 'catalog.json', true);
+    xhr.onload = function() {
+      if (xhr.status === 200) {
+        catalog = JSON.parse(xhr.responseText);
+        renderTags();
+        renderModules();
+      } else {
+        document.getElementById('catalogGrid').innerHTML =
+          '<div class="no-results">Could not load catalog. Run <code>python3 tools/generate-catalog.py</code> first.</div>';
+      }
+    };
+    xhr.onerror = function() {
+      document.getElementById('catalogGrid').innerHTML =
+        '<div class="no-results">Could not load catalog. Run <code>python3 tools/generate-catalog.py</code> first.</div>';
+    };
+    xhr.send();
+  }
+
+  function renderTags() {
+    var container = document.getElementById('tagFilters');
+    container.innerHTML = '';
+    catalog.tags.forEach(function(tag) {
+      var chip = document.createElement('span');
+      chip.className = 'tag-chip';
+      chip.textContent = tag;
+      chip.addEventListener('click', function() {
+        if (activeTags.has(tag)) {
+          activeTags.delete(tag);
+          chip.classList.remove('active');
+        } else {
+          activeTags.add(tag);
+          chip.classList.add('active');
+        }
+        renderModules();
+      });
+      container.appendChild(chip);
+    });
+  }
+
+  function renderModules() {
+    var grid = document.getElementById('catalogGrid');
+    var countEl = document.getElementById('catalogCount');
+    var searchTerm = (document.getElementById('catalogSearch').value || '').toLowerCase();
+
+    var filtered = catalog.modules.filter(function(mod) {
+      // Tag filter: module must have ALL active tags
+      if (activeTags.size > 0) {
+        var moduleTags = mod.tags || [];
+        var hasAll = true;
+        activeTags.forEach(function(t) {
+          if (moduleTags.indexOf(t) === -1) hasAll = false;
+        });
+        if (!hasAll) return false;
+      }
+      // Text search
+      if (searchTerm) {
+        var haystack = (mod.title + ' ' + mod.description + ' ' + (mod.tags || []).join(' ')).toLowerCase();
+        if (haystack.indexOf(searchTerm) === -1) return false;
+      }
+      return true;
+    });
+
+    countEl.textContent = filtered.length + ' of ' + catalog.count + ' modules';
+
+    if (filtered.length === 0) {
+      grid.innerHTML = '<div class="no-results">No modules match your filters. Try removing some tags.</div>';
+      return;
+    }
+
+    grid.innerHTML = filtered.map(function(mod) {
+      var meta = [];
+      if (mod.level) meta.push(mod.level);
+      if (mod.duration) meta.push(mod.duration);
+      if (mod.language) meta.push(mod.language);
+      if (mod.slides) meta.push(mod.slides + ' slides');
+
+      var tagsHtml = (mod.tags || []).map(function(t) {
+        return '<span>' + t + '</span>';
+      }).join('');
+
+      return '<div class="module-card">' +
+        '<h3><a href="' + mod.path + '" target="_blank">' + mod.title + '</a></h3>' +
+        '<div class="description">' + mod.description + '</div>' +
+        (meta.length ? '<div class="meta">' + meta.join(' · ') + '</div>' : '') +
+        '<div class="tags">' + tagsHtml + '</div>' +
+        '</div>';
+    }).join('');
+  }
+
+  // Search handler
+  document.getElementById('catalogSearch').addEventListener('input', function() {
+    if (catalog) renderModules();
+  });
+
+  // Load on page ready
+  if (document.readyState === 'loading') {
+    document.addEventListener('DOMContentLoaded', loadCatalog);
+  } else {
+    loadCatalog();
+  }
+})();
+</script>
+++++
diff --git a/site/src/site/site.xml b/site/src/site/site.xml
index c00879d..877934d 100644
--- a/site/src/site/site.xml
+++ b/site/src/site/site.xml
@@ -100,53 +100,7 @@
 
     <!-- Published presentations -->
     <menu name="Presentations">
-      <item name="Apache Airflow" href="presentations/apache/airflow/index.html" target="_blank"/>
-      <item name="Apache ComDev">
-        <item name="The ASF" href="presentations/apache/comdev/apache-intro/index.html" target="_blank"/>
-        <item name="Intro" href="presentations/apache/comdev/comdev-intro/index.html" target="_blank"/>
-        <item name="Working Groups" href="presentations/apache/comdev/working-groups/index.html" target="_blank"/>
-      </item>
-      <item name="Apache Druid" href="presentations/apache/druid/index.html" target="_blank"/>
-      <item name="Apache Flink" href="presentations/apache/flink/index.html" target="_blank"/>
-      <item name="Apache Hadoop" href="presentations/apache/hadoop/index.html" target="_blank"/>
-      <item name="Apache Hive" href="presentations/apache/hive/index.html" target="_blank"/>
-      <item name="Apache Ignite" href="presentations/apache/ignite/index.html" target="_blank"/>
-      <item name="Apache Incubator">
-        <item name="Podling Orientation" href="presentations/apache/incubator/PodlingOrientation/index.html" target="_blank"/>
-        <item name="ASF Values" href="presentations/apache/incubator/ASFvalues/index.html" target="_blank"/>
-        <item name="Incubator Releases" href="presentations/apache/incubator/incubator-releases/index.html" target="_blank"/>
-        <item name="Vendor Neutrality" href="presentations/apache/incubator/VendorNeutrality/index.html" target="_blank"/>
-        <item name="Branding and Identity" href="presentations/apache/incubator/BrandingIdentity/index.html" target="_blank"/>
-        <item name="Governance in Practice" href="presentations/apache/incubator/Goverance/index.html" target="_blank"/>
-        <item name="Voting And Consensus" href="presentations/apache/incubator/VotingAndConsensus/index.html" target="_blank"/>
-        <item name="Community Building" href="presentations/apache/incubator/CommunityBuilding/index.html" target="_blank"/>
-        <item name="IPMC Onboarding" href="presentations/apache/incubator/IPMC/index.html" target="_blank"/>
-        <item name="Mentors Onboarding" href="presentations/apache/incubator/mentors/index.html" target="_blank"/>
-        <item name="PPMC Onboarding" href="presentations/apache/incubator/PPMC/index.html" target="_blank"/>
-        <item name="Committers Onboarding" href="presentations/apache/incubator/committers/index.html" target="_blank"/>
-        <item name="Navigating ASF Incubator" href="presentations/apache/incubator/navigating-asf-incubation/index.html" target="_blank"/>
-        <item name="Release Checklist" href="presentations/apache/incubator/release-checklist/index.html" target="_blank"/>
-      </item>
-      <item name="Apache MyNewt" href="presentations/apache/mynewt/index_en.html" target="_blank"/>
-      <item name="Apache PLC4X">
-        <item name="Revolutionizing IIoT with Apache PLC4X" href="presentations/apache/plc4x/revolutionizing-iiot-with-plc4x/index.html" target="_blank"/>
-      </item>
-      <item name="Apache Pulsar" href="presentations/apache/pulsar/index.html" target="_blank"/>
-      <item name="Apache Samza" href="presentations/apache/samza/index.html" target="_blank"/>
-      <item name="Apache Spark">
-        <item name="Basics" href="presentations/apache/spark/basics/index.html" target="_blank"/>
-      </item>
-      <item name="Apache Training">
-        <!--item name="Demo" href="presentations/training/demo/index.html" target="_blank"/-->
-        <item name="Presentation" href="presentations/apache/training/presentation/index_en.html" target="_blank"/>
-      </item>
-      <item name="Apache Zookeeper" href="presentations/apache/zookeeper/index_en.html" target="_blank"/>
-      <item name="IoT">
-        <item name="Magic Industrial Data Acquisition" href="presentations/iot/magic-industrial-data-acquisition-with-apache-plc4x-tsfile-and-iotdb/index.html" target="_blank"/>
-        <!-- There are double-linked here -->
-        <item name="Apache MyNewt" href="presentations/apache/mynewt/index_en.html" target="_blank"/>
-        <item name="Revolutionizing IIoT with Apache PLC4X" href="presentations/apache/plc4x/revolutionizing-iiot-with-plc4x/index.html" target="_blank"/>
-      </item>
+      <item name="Browse Catalog" href="catalog.html"/>
     </menu>
 
     <!-- Users (Authors and presenters) -->
diff --git a/tools/content-parent-pom/pom.xml b/tools/content-parent-pom/pom.xml
index 98d9acc..fe49f7d 100644
--- a/tools/content-parent-pom/pom.xml
+++ b/tools/content-parent-pom/pom.xml
@@ -95,36 +95,36 @@
                 </executions>
                 <configuration>
                     <consoleOutput>true</consoleOutput>
-                    <excludes>
+                    <inputExcludes>
                         <!-- Maven related files -->
-                        <exclude>**/target/**</exclude>
+                        <inputExclude>**/target/**</inputExclude>
 
                         <!-- Eclipse related files -->
-                        <exclude>**/.project</exclude>
-                        <exclude>**/.settings/**</exclude>
-                        <exclude>**/.classpath</exclude>
+                        <inputExclude>**/.project</inputExclude>
+                        <inputExclude>**/.settings/**</inputExclude>
+                        <inputExclude>**/.classpath</inputExclude>
 
                         <!-- IntelliJ related files -->
-                        <exclude>**/.idea/**</exclude>
-                        <exclude>**/*.iml</exclude>
+                        <inputExclude>**/.idea/**</inputExclude>
+                        <inputExclude>**/*.iml</inputExclude>
 
                         <!-- Asciidoctor generated files -->
-                        <exclude>**/.asciidoctor/**</exclude>
+                        <inputExclude>**/.asciidoctor/**</inputExclude>
 
                         <!-- JSON doesn't like comments -->
-                        <exclude>**/*.json</exclude>
+                        <inputExclude>**/*.json</inputExclude>
                         <!-- Mermaid does't like comments -->
-                        <exclude>**/*.mmd</exclude>
+                        <inputExclude>**/*.mmd</inputExclude>
 
                         <!-- Output of the profiler maven extension -->
-                        <exclude>**/.profiler/**</exclude>
+                        <inputExclude>**/.profiler/**</inputExclude>
 
-                        <exclude>licenses/**</exclude>
-                        <exclude>README.md</exclude>
+                        <inputExclude>licenses/**</inputExclude>
+                        <inputExclude>README.md</inputExclude>
 
                         <!-- Exclude the Docker local repo -->
-                        <exclude>out/**</exclude>
-                    </excludes>
+                        <inputExclude>out/**</inputExclude>
+                    </inputExcludes>
                 </configuration>
             </plugin>
 
diff --git a/tools/content-parent-resources/src/main/resources/document.html.slim b/tools/content-parent-resources/src/main/resources/document.html.slim
index 9bc9acc..915d1b0 100644
--- a/tools/content-parent-resources/src/main/resources/document.html.slim
+++ b/tools/content-parent-resources/src/main/resources/document.html.slim
@@ -74,20 +74,10 @@
     - unless (_docinfo = docinfo :head, '-revealjs.html').empty?
       =_docinfo
   body
-    / START ADDED For Apache Training
-    .header
-      .left
-      .right
-    / END ADDED For Apache Training
     .reveal
       / Any section element inside of this container is displayed as a slide
       .slides
         - yield_content :slides
-    / START ADDED For Apache Training
-    .footer
-      .left
-      .right
-    / END ADDED For Apache Training
     script src="#{revealjsdir}/dist/reveal.js"
     / Supports easy AsciiDoc syntax for background color
     javascript:
diff --git a/tools/content-parent-resources/src/main/resources/logo-apache.png b/tools/content-parent-resources/src/main/resources/logo-apache.png
index 44c337b..fbb755d 100644
--- a/tools/content-parent-resources/src/main/resources/logo-apache.png
+++ b/tools/content-parent-resources/src/main/resources/logo-apache.png
Binary files differ
diff --git a/tools/generate-catalog.py b/tools/generate-catalog.py
new file mode 100644
index 0000000..e61e07b
--- /dev/null
+++ b/tools/generate-catalog.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python3
+"""
+Generate catalog.json from all metadata.yaml files in content/.
+
+Usage:
+    python3 tools/generate-catalog.py
+
+Output:
+    site/src/site/resources/catalog.json
+
+This script walks the content/ directory tree, finds all metadata.yaml files,
+parses them, and writes a JSON catalog that the catalog.html page uses for
+tag-based filtering.
+"""
+
+import json
+import os
+import sys
+from pathlib import Path
+
+try:
+    import yaml
+except ImportError:
+    print("ERROR: PyYAML is required. Install with: pip install pyyaml")
+    sys.exit(1)
+
+# Paths relative to repository root
+REPO_ROOT = Path(__file__).resolve().parent.parent
+CONTENT_DIR = REPO_ROOT / "content"
+OUTPUT_FILE = REPO_ROOT / "site" / "src" / "site" / "resources" / "catalog.json"
+
+
+def find_metadata_files(content_dir):
+    """Recursively find all metadata.yaml files."""
+    return sorted(content_dir.rglob("metadata.yaml"))
+
+
+def parse_metadata(filepath):
+    """Parse a metadata.yaml file and add computed fields."""
+    with open(filepath) as f:
+        data = yaml.safe_load(f)
+
+    if not data or not data.get("title"):
+        return None
+
+    # Skip the Template itself
+    if data.get("project_id") == "template":
+        return None
+
+    # Compute the relative path to the presentation
+    module_dir = filepath.parent
+    rel_path = module_dir.relative_to(CONTENT_DIR)
+
+    # Convention: presentation is at presentations/{rel_path}/index.html
+    # (lowercase, as built by Maven)
+    presentation_path = f"presentations/{str(rel_path).lower()}/index.html"
+
+    data["path"] = presentation_path
+    data["module_dir"] = str(rel_path)
+
+    return data
+
+
+def main():
+    if not CONTENT_DIR.exists():
+        print(f"ERROR: Content directory not found: {CONTENT_DIR}")
+        sys.exit(1)
+
+    metadata_files = find_metadata_files(CONTENT_DIR)
+    print(f"Found {len(metadata_files)} metadata.yaml files")
+
+    catalog = []
+    all_tags = set()
+
+    for filepath in metadata_files:
+        entry = parse_metadata(filepath)
+        if entry:
+            catalog.append(entry)
+            all_tags.update(entry.get("tags", []))
+            print(f"  + {entry['title']}")
+
+    # Sort catalog alphabetically by title
+    catalog.sort(key=lambda x: x["title"].lower())
+
+    output = {
+        "generated": True,
+        "count": len(catalog),
+        "tags": sorted(all_tags),
+        "modules": catalog,
+    }
+
+    # Ensure output directory exists
+    OUTPUT_FILE.parent.mkdir(parents=True, exist_ok=True)
+
+    with open(OUTPUT_FILE, "w") as f:
+        json.dump(output, f, indent=2)
+
+    print(f"\nWrote {len(catalog)} modules to {OUTPUT_FILE}")
+    print(f"Tags: {', '.join(sorted(all_tags))}")
+
+
+if __name__ == "__main__":
+    main()