This is an automated email from the ASF dual-hosted git repository.

rzo1 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/storm-site.git


The following commit(s) were added to refs/heads/main by this push:
     new 2a5444b60c Add team page sourced from ASF roster and trim hero tagline
2a5444b60c is described below

commit 2a5444b60c8e59ed84cfda175d958784265b2f4a
Author: Richard Zowalla <[email protected]>
AuthorDate: Thu May 7 11:53:18 2026 +0200

    Add team page sourced from ASF roster and trim hero tagline
    
    Build-time Jekyll plugin pulls Storm's PMC and committer roster from
    Whimsy and projects.apache.org, then overlays the active set defined
    in _data/team.yml. Anyone in LDAP not flagged active is shown as
    emeritus. Header "People" link is replaced with "Team" pointing at
    /team/; the old contribute/People.md becomes a stub redirect.
    
    Hero tagline no longer repeats the H2 title above it.
---
 _data/team.yml        |  20 +++++++
 _includes/header.html |   2 +-
 _plugins/team.rb      | 145 ++++++++++++++++++++++++++++++++++++++++++++++++++
 contribute/People.md  |   2 +-
 css/style.css         | 124 +++++++++++++++++++++++++++++++++++++++++-
 index.html            |   2 +-
 team.md               |  87 ++++++++++++++++++++++++++++++
 7 files changed, 378 insertions(+), 4 deletions(-)

diff --git a/_data/team.yml b/_data/team.yml
new file mode 100644
index 0000000000..c108cdf45c
--- /dev/null
+++ b/_data/team.yml
@@ -0,0 +1,20 @@
+# Apache Storm team โ€” active members.
+#
+# Anyone listed under `active` is shown in the "Active" section of /team/.
+# Anyone in the ASF LDAP roster but NOT listed here is shown as "Emeritus".
+# `chair` overrides whatever LDAP reports (use this to fix lag in Whimsy).
+#
+# Names + GitHub usernames are resolved at build time by _plugins/team.rb
+# from Whimsy / projects.apache.org. No need to duplicate them here.
+
+chair: rzo1
+
+active:
+  - rzo1            # Richard Zowalla
+  - rabreu          # Rui Abreu
+  - bipinprasad     # Bipin Prasad
+  - jnioche         # Julien Nioche
+  - avermeerbergen  # Alexandre Vermeerbergen
+  - puru            # Purshotam Shah
+  - agresch         # Aaron Gresch
+  - roshannaik      # Roshan Naik
diff --git a/_includes/header.html b/_includes/header.html
index 89dbe7c85e..bcd0df4a97 100644
--- a/_includes/header.html
+++ b/_includes/header.html
@@ -61,7 +61,7 @@
                     <ul class="dropdown-menu">
                         <li><a href="/getting-help.html">Getting Help</a></li>
                         <li><a 
href="/contribute/Contributing-to-Storm.html">Contributing</a></li>
-                        <li><a href="/contribute/People.html">People</a></li>
+                        <li><a href="/team/">Team</a></li>
                         <li><a href="/contribute/BYLAWS.html">ByLaws</a></li>
                         <li role="separator" class="divider"></li>
                         <li><a href="/talksAndVideos.html">Talks and 
Slideshows</a></li>
diff --git a/_plugins/team.rb b/_plugins/team.rb
new file mode 100644
index 0000000000..2e8ffbf29d
--- /dev/null
+++ b/_plugins/team.rb
@@ -0,0 +1,145 @@
+require 'jekyll'
+require 'net/http'
+require 'json'
+require 'yaml'
+require 'uri'
+
+# Storm team data generator.
+#
+# Pulls the Storm PMC + committer roster from public ASF sources at build
+# time and exposes it to Liquid templates as:
+#
+#   site.data.team_active     # active members (chair, then PMC, then 
committers)
+#   site.data.team_emeritus   # everyone else in the LDAP roster
+#
+# Active membership is driven by _data/team.yml (`active:` list of availids
+# plus an optional `chair:` override). Anyone in LDAP not listed in the
+# YAML is shown as emeritus.
+#
+# Network sources (no auth required):
+#   * https://whimsy.apache.org/public/public_ldap_projects.json โ€” committee
+#   * https://projects.apache.org/json/foundation/people.json    โ€” names + GH
+#
+# Successful fetches are cached to tmp/asf_roster.yml; the cache is consulted
+# only when the live fetch fails, so the build degrades gracefully if Whimsy
+# or projects.apache.org is unreachable.
+module StormTeam
+  WHIMSY_PROJECTS_URL = 
'https://whimsy.apache.org/public/public_ldap_projects.json'.freeze
+  PEOPLE_JSON_URL     = 
'https://projects.apache.org/json/foundation/people.json'.freeze
+  CACHE_RELATIVE_PATH = 'tmp/asf_roster.yml'.freeze
+  PROJECT_NAME        = 'storm'.freeze
+  HTTP_TIMEOUT        = 8
+
+  class Generator < Jekyll::Generator
+    def generate(site)
+      cache_path = File.join(site.source, CACHE_RELATIVE_PATH)
+
+      committee = fetch_committee
+      people    = fetch_people
+
+      if committee.nil? || people.nil?
+        cached    = load_cache(cache_path)
+        committee ||= cached && cached['committee']
+        people    ||= cached && cached['people']
+      end
+
+      save_cache(cache_path, committee, people) if committee && people
+
+      yaml_team  = site.data['team'] || {}
+      active_set = (yaml_team['active'] || []).map(&:to_s)
+      chair_id   = (yaml_team['chair'] || (committee && 
committee['chair'])).to_s
+
+      pmc_ids       = (committee && committee['owners'])  || []
+      committer_ids = (committee && committee['members']) || []
+      all_ids       = (pmc_ids + committer_ids + active_set + [chair_id])
+                      .uniq.reject { |s| s.nil? || s.empty? }
+
+      records = all_ids.map do |aid|
+        person = people ? (people[aid] || {}) : {}
+        role =
+          if    aid == chair_id            then 'chair'
+          elsif pmc_ids.include?(aid)      then 'pmc'
+          elsif committer_ids.include?(aid) then 'committer'
+          else                                  'committer'
+          end
+        {
+          'apache_id' => aid,
+          'name'      => person['name']   || aid,
+          'github'    => person['github'] || aid,
+          'role'      => role,
+          'active'    => (aid == chair_id) || active_set.include?(aid),
+        }
+      end
+
+      site.data['team_active']   = records.select { |r| r['active'] }.sort_by 
{ |r| active_sort_key(r) }
+      site.data['team_emeritus'] = records.reject { |r| r['active'] }.sort_by 
{ |r| r['name'].to_s.downcase }
+
+      Jekyll.logger.info 'StormTeam:',
+        "active=#{site.data['team_active'].size} 
emeritus=#{site.data['team_emeritus'].size}"
+    end
+
+    private
+
+    def active_sort_key(record)
+      rank = { 'chair' => 0, 'pmc' => 1, 'committer' => 2 }[record['role']] || 
3
+      [rank, record['name'].to_s.downcase]
+    end
+
+    def fetch_committee
+      data = fetch_json(WHIMSY_PROJECTS_URL)
+      data && data.dig('projects', PROJECT_NAME)
+    rescue StandardError => e
+      Jekyll.logger.warn 'StormTeam:', "Whimsy fetch failed: #{e.message}"
+      nil
+    end
+
+    def fetch_people
+      data = fetch_json(PEOPLE_JSON_URL)
+      return nil unless data.is_a?(Hash)
+
+      data.each_with_object({}) do |(aid, rec), out|
+        next unless rec.is_a?(Hash)
+        out[aid] = { 'name' => rec['name'] || aid, 'github' => 
extract_github(rec) }
+      end
+    rescue StandardError => e
+      Jekyll.logger.warn 'StormTeam:', "people.json fetch failed: #{e.message}"
+      nil
+    end
+
+    def extract_github(rec)
+      urls = rec['urls']
+      return nil unless urls.is_a?(Hash)
+      raw = urls['github'] || urls['GitHub'] || urls['github.com']
+      return nil unless raw.is_a?(String) && !raw.empty?
+      handle = raw.sub(%r{\Ahttps?://github\.com/}, '').sub(%r{/.*\z}, 
'').strip
+      handle.empty? ? nil : handle
+    end
+
+    def fetch_json(url)
+      uri = URI.parse(url)
+      http = Net::HTTP.new(uri.host, uri.port)
+      http.use_ssl     = (uri.scheme == 'https')
+      http.open_timeout = HTTP_TIMEOUT
+      http.read_timeout = HTTP_TIMEOUT
+      req = Net::HTTP::Get.new(uri.request_uri, 'User-Agent' => 
'storm-site-team/1.0')
+      res = http.request(req)
+      return nil unless res.is_a?(Net::HTTPSuccess)
+      JSON.parse(res.body)
+    end
+
+    def load_cache(path)
+      return nil unless File.exist?(path)
+      YAML.safe_load(File.read(path))
+    rescue StandardError => e
+      Jekyll.logger.warn 'StormTeam:', "cache read failed: #{e.message}"
+      nil
+    end
+
+    def save_cache(path, committee, people)
+      FileUtils.mkdir_p(File.dirname(path))
+      File.write(path, { 'committee' => committee, 'people' => people 
}.to_yaml)
+    rescue StandardError => e
+      Jekyll.logger.warn 'StormTeam:', "cache write failed: #{e.message}"
+    end
+  end
+end
diff --git a/contribute/People.md b/contribute/People.md
index b5be3cb47b..98d22e02f7 100644
--- a/contribute/People.md
+++ b/contribute/People.md
@@ -4,4 +4,4 @@ layout: documentation
 documentation: true
 ---
 
-Current list of committers and PMC members is 
[here](https://projects.apache.org/committee.html?storm) 
+The Apache Storm team page has moved to [/team/](/team/).
diff --git a/css/style.css b/css/style.css
index 511ae34032..b0ddd60087 100644
--- a/css/style.css
+++ b/css/style.css
@@ -830,9 +830,131 @@ footer hr {
        .github-fork-ribbon { display: none; }
 }
 
+/* /team/ page */
+.team-page { margin: 0 0 40px; }
+.team-intro {
+       font-size: 16px;
+       line-height: 1.6;
+       max-width: 780px;
+       color: #444;
+       margin: 0 0 30px;
+}
+.team-section { margin: 36px 0; }
+.team-section h2 {
+       font-size: 24px;
+       margin: 0 0 18px;
+       padding-bottom: 8px;
+       border-bottom: 2px solid #e6e6e6;
+       color: #235693;
+}
+.team-grid {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+       display: grid;
+       grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
+       gap: 16px;
+}
+.team-card {
+       display: flex;
+       align-items: center;
+       gap: 14px;
+       padding: 14px 16px;
+       background: #fff;
+       border: 1px solid #e2e6ea;
+       border-radius: 6px;
+       transition: box-shadow 0.15s ease, border-color 0.15s ease;
+}
+.team-card:hover {
+       box-shadow: 0 4px 14px rgba(35, 86, 147, 0.10);
+       border-color: #c8d3df;
+}
+.team-avatar {
+       flex: 0 0 48px;
+       width: 48px;
+       height: 48px;
+       border-radius: 50%;
+       background: linear-gradient(135deg, #328fbf, #235693);
+       color: #fff;
+       font-weight: 700;
+       font-size: 20px;
+       display: flex;
+       align-items: center;
+       justify-content: center;
+       text-transform: uppercase;
+}
+.team-card--active .team-avatar { background: linear-gradient(135deg, #32bf61, 
#235693); }
+.team-meta { min-width: 0; flex: 1; }
+.team-name {
+       margin: 0 0 4px;
+       font-weight: 700;
+       font-size: 15px;
+       color: #222;
+       white-space: nowrap;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+.team-roles { margin: 0 0 4px; line-height: 1; }
+.role-badge {
+       display: inline-block;
+       padding: 2px 7px;
+       margin-right: 4px;
+       font-size: 11px;
+       font-weight: 700;
+       letter-spacing: 0.4px;
+       text-transform: uppercase;
+       border-radius: 3px;
+       color: #fff;
+       vertical-align: middle;
+}
+.role-chair     { background: #c75a26; }
+.role-pmc       { background: #235693; }
+.role-committer { background: #4a90a4; }
+.role-badge--sm { padding: 1px 5px; font-size: 10px; }
+.team-links {
+       margin: 0;
+       font-size: 13px;
+       color: #666;
+       white-space: nowrap;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+.team-links a { color: #235693; font-weight: 600; }
+.team-links a:hover { color: #328fbf; }
+.team-availid { color: #999; font-size: 12px; }
 
+.team-emeritus-intro {
+       color: #555;
+       max-width: 780px;
+       margin: 0 0 16px;
+}
+.team-emeritus-list {
+       list-style: none;
+       margin: 0;
+       padding: 0;
+       display: grid;
+       grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
+       gap: 6px 18px;
+       font-size: 14px;
+}
+.team-emeritus-list li {
+       padding: 4px 0;
+       color: #444;
+       white-space: nowrap;
+       overflow: hidden;
+       text-overflow: ellipsis;
+}
+.team-emeritus-list a { color: #235693; }
+.team-emeritus-list a:hover { color: #328fbf; }
 
-
+.team-thanks {
+       padding: 14px 18px;
+       background: #f6f9fc;
+       border-left: 4px solid #32bf61;
+       border-radius: 3px;
+       margin: 16px 0;
+}
+.team-empty { color: #888; font-style: italic; }
 
 
 
diff --git a/index.html b/index.html
index 4853b41dcc..002a12ea07 100644
--- a/index.html
+++ b/index.html
@@ -8,7 +8,7 @@ title: Apache Storm
         <div class="row">
             <div class="col-md-7 hero-text">
                 <h2 class="hero-title">Distributed real-time computation</h2>
-                <p class="hero-tagline">Distributed real-time computation. 
Free and open source. Process unbounded streams of data &mdash; fast, 
fault-tolerant, and reliable.</p>
+                <p class="hero-tagline">Free and open source. Process 
unbounded streams of data &mdash; fast, fault-tolerant, and reliable.</p>
                 <p class="hero-cta">
                     <a href="/downloads.html" class="btn-hero 
btn-hero-primary">Download {{ current.name }}</a>
                     <a href="/releases/current/Tutorial.html" class="btn-hero 
btn-hero-secondary">Get Started</a>
diff --git a/team.md b/team.md
new file mode 100644
index 0000000000..9c4c082e06
--- /dev/null
+++ b/team.md
@@ -0,0 +1,87 @@
+---
+title: Team
+layout: default
+permalink: /team/
+description: The PMC, committers, and contributors behind Apache Storm.
+---
+
+<div class="team-page">
+
+<p class="team-intro">
+  Apache Storm is developed and maintained by a community of volunteers from
+  around the world. Below are the project's active and emeritus PMC members
+  and committers, sourced from
+  <a href="https://whimsy.apache.org/roster/committee/storm";>the official ASF 
roster</a>
+  and overlaid with the project's currently active set.
+</p>
+
+<section class="team-section">
+  <h2 id="active">Active team</h2>
+  {% if site.data.team_active and site.data.team_active.size > 0 %}
+  <ul class="team-grid">
+    {% for m in site.data.team_active %}
+    <li class="team-card team-card--active">
+      <div class="team-avatar" aria-hidden="true">{{ m.name | slice: 0, 1 | 
upcase }}</div>
+      <div class="team-meta">
+        <p class="team-name">{{ m.name }}</p>
+        <p class="team-roles">
+          {% if m.role == 'chair' %}<span class="role-badge role-chair" 
title="PMC Chair">Chair</span>{% endif %}
+          {% if m.role == 'pmc' or m.role == 'chair' %}<span class="role-badge 
role-pmc" title="PMC member">PMC</span>{% endif %}
+          <span class="role-badge role-committer" 
title="Committer">Committer</span>
+        </p>
+        <p class="team-links">
+          <a href="https://github.com/{{ m.github }}" rel="noopener" 
target="_blank">@{{ m.github }}</a>
+          <span class="team-availid">ยท&nbsp;{{ m.apache_id }}@apache.org</span>
+        </p>
+      </div>
+    </li>
+    {% endfor %}
+  </ul>
+  {% else %}
+  <p class="team-empty">Active team list is currently unavailable.</p>
+  {% endif %}
+</section>
+
+{% if site.data.team_emeritus and site.data.team_emeritus.size > 0 %}
+<section class="team-section">
+  <h2 id="emeritus">Emeritus</h2>
+  <p class="team-emeritus-intro">
+    Past contributors who served as Storm PMC members or committers and are
+    no longer actively maintaining the project. Many of them shaped Storm
+    into what it is today &mdash; thank you.
+  </p>
+  <ul class="team-emeritus-list">
+    {% for m in site.data.team_emeritus %}
+    <li>
+      <a href="https://github.com/{{ m.github }}" rel="noopener" 
target="_blank">{{ m.name }}</a>
+      {% if m.role == 'pmc' %}<span class="role-badge role-pmc 
role-badge--sm">PMC</span>{% endif %}
+      <span class="team-availid">({{ m.apache_id }})</span>
+    </li>
+    {% endfor %}
+  </ul>
+</section>
+{% endif %}
+
+<section class="team-section">
+  <h2 id="contributors">Wall of fame</h2>
+  <p>
+    Apache Storm exists because of the many people who have contributed code,
+    reviews, documentation, and bug reports across the project's repositories
+    on GitHub. The full list is far too long to render here &mdash; please
+    have a look at the
+    <a href="https://github.com/apache/storm/graphs/contributors"; 
rel="noopener" target="_blank">contributors graph on GitHub</a>
+    to see them all.
+  </p>
+  <p class="team-thanks">
+    <strong>Thank you to every contributor</strong> &mdash; your patches,
+    reports, and reviews are what keep Storm moving.
+  </p>
+  <p>
+    If you would like to contribute, see the
+    <a href="/contribute/Contributing-to-Storm.html">contributing guide</a>
+    and join the conversation on the
+    <a href="/getting-help.html">developer mailing list</a>.
+  </p>
+</section>
+
+</div>

Reply via email to