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()