OOKNET                             [ /  search the index  ]  
──────────────────────────────────────────────────────────────────────────────────────
══════════════════════════════════════════════════════════════════════════════════════
OOKNET   [ /  search  ]  
────────────────────────────────────────────────
════════════════════════════════════════════════
 
HASH      263406739880
DATE      2025-08-14
SUBJECT   challenge-mode: minify json
FILES     2 CHANGED
HASH      263406739880
DATE      2025-08-14
SUBJECT   challenge-mode: minify json
FILES     2 CHANGED
 

diff --git a/nix/apps/challenge-mode-parser.nix b/nix/apps/challenge-mode-parser.n
ix
index b2b8764..1a5a1f1 100644
--- a/nix/apps/challenge-mode-parser.nix
+++ b/nix/apps/challenge-mode-parser.nix
@@ -15,13 +15,13 @@
       from pathlib import Path
       import sys
 
-      # The root directory where the fetcher script saves its data.
+      # the root directory where the fetcher script saves its data.
       INPUT_ROOT = "./web/public/data/challenge-mode"
-      # A new directory to store the processed and ranked leaderboards.
+      # a new directory to store the processed and ranked leaderboards.
       OUTPUT_ROOT = "./web/public/data/leaderboards"
-      # The number of top runs to collect from each realm's file.
+      # the number of top runs to collect from each realm's file.
       TOP_N_PER_REALM = 50
-      # The number of top runs to keep in final aggregated leaderboards.
+      # the number of top runs to keep in final aggregated leaderboards.
       TOP_N_FINAL = 50
 
       def parse_and_aggregate_data():
@@ -59,8 +59,12 @@
                   continue
 
               if dungeon_slug not in dungeon_data:
+                  # extract only the English name from the multilingual data
+                  map_name = data.get("map", {}).get("name", {})
+                  dungeon_name = map_name.get("en_US", dungeon_slug) if isinstanc
e(map_name, dict) else map_name
+
                   dungeon_data[dungeon_slug] = {
-                      "dungeon_name": data.get("map", {}).get("name", {}).get("en
_US", dungeon_slug),
+                      "dungeon_name": dungeon_name,
                       "runs": {"us": [], "eu": [], "kr": []}
                   }
 
@@ -76,13 +80,18 @@
 
 
       def deduplicate_runs(runs):
-          # Remove duplicate runs caused by cross-realm groups appearing on multi
ple realm leaderboards
+          # remove duplicate runs caused by cross-realm groups appearing on multi
ple realm leaderboards
           seen = set()
           deduplicated = []
 
           for run in runs:
-              # Create a unique identifier for each run using timestamp, duration
, and sorted player IDs
-              player_ids = sorted([member["profile"]["id"] for member in run["mem
bers"]])
+              # create a unique identifier for each run using timestamp, duration
, and sorted player IDs
+              # support both old format (member["profile"]["id"]) and optimized f
ormat (member["id"])
+              player_ids = []
+              for member in run["members"]:
+                  member_id = member.get("id") or member.get("profile", {}).get("
id", 0)
+                  player_ids.append(member_id)
+              player_ids = sorted(player_ids)
               unique_key = (run["completed_timestamp"], run["duration"], tuple(pl
ayer_ids))
 
               if unique_key not in seen:
@@ -93,6 +102,40 @@
 
           return deduplicated
 
+      def optimize_run_data(run):
+          # optimize individual run data to remove redundant information
+          optimized_run = {
+              "ranking": run["ranking"],
+              "duration": run["duration"],
+              "completed_timestamp": run["completed_timestamp"],
+              "keystone_level": run.get("keystone_level", 1),
+              "members": []
+          }
+
+          # add realm and region info if present
+          if "realm_slug" in run:
+              optimized_run["realm_slug"] = run["realm_slug"]
+          if "region" in run:
+              optimized_run["region"] = run["region"]
+
+          # optimize member data - handle both old format and already optimized f
ormat
+          for member in run.get("members", []):
+              if "profile" in member:
+                  # old format with nested profile data
+                  optimized_member = {
+                      "name": member["profile"]["name"],
+                      "id": member["profile"]["id"],
+                      "realm_slug": member["profile"]["realm"]["slug"],
+                      "faction": member["faction"]["type"],
+                      "spec_id": member["specialization"]["id"]
+                  }
+              else:
+                  # already optimized format - just copy it
+                  optimized_member = member.copy()
+              optimized_run["members"].append(optimized_member)
+
+          return optimized_run
+
       def rank_and_save_leaderboards(dungeon_data):
           # sorts the aggregated data to create regional and global leaderboards,
           # then saves them to new JSON files
@@ -108,27 +151,30 @@
               print(f"  Processing dungeon: {data['dungeon_name']}")
               all_regional_runs = []
 
-              # 1. Generate and save REGIONAL leaderboards
+              # generate and save REGIONAL leaderboards
               regional_path = os.path.join(OUTPUT_ROOT, "regional")
               for region, runs in data["runs"].items():
                   if not runs:
                       continue
 
-                  # Deduplicate and sort regional runs
+                  # deduplicate and sort regional runs
                   print(f"    Deduplicating {region.upper()} runs ({len(runs)} ->
 ", end="")
                   deduplicated_runs = deduplicate_runs(runs)
                   print(f"{len(deduplicated_runs)} -> ", end="")
                   deduplicated_runs.sort(key=sort_key)
 
-                  # Limit to top N runs for regional leaderboard
+                  # limit to top N runs for regional leaderboard
                   final_runs = deduplicated_runs[:TOP_N_FINAL]
                   print(f"{len(final_runs)})")
 
-                  # Re-rank runs for regional leaderboard
+                  # re-rank and optimize runs for regional leaderboard
+                  optimized_runs = []
                   for i, run in enumerate(final_runs):
                       run["ranking"] = i + 1
+                      optimized_run = optimize_run_data(run)
+                      optimized_runs.append(optimized_run)
 
-                  all_regional_runs.extend(final_runs)
+                  all_regional_runs.extend(optimized_runs)
                   output_dir = os.path.join(regional_path, region, dungeon_slug)
                   os.makedirs(output_dir, exist_ok=True)
                   output_file = os.path.join(output_dir, "leaderboard.json")
@@ -138,26 +184,28 @@
                           "dungeon_name": data["dungeon_name"],
                           "dungeon_slug": dungeon_slug,
                           "region": region,
-                          "leaderboard": final_runs,
-                      }, f, indent=2)
+                          "leaderboard": optimized_runs,
+                      }, f, separators=(',', ':'))
 
-              # 2. Generate and save GLOBAL leaderboard
               if not all_regional_runs:
                   continue
 
-              # Deduplicate global runs (cross-region duplicates)
+              # deduplicate global runs (cross-region duplicates)
               print(f"    Deduplicating global runs ({len(all_regional_runs)} -> 
", end="")
               deduplicated_global = deduplicate_runs(all_regional_runs)
               print(f"{len(deduplicated_global)} -> ", end="")
               deduplicated_global.sort(key=sort_key)
 
-              # Limit to top N runs for global leaderboard
+              # limit to top N runs for global leaderboard
               final_global = deduplicated_global[:TOP_N_FINAL]
               print(f"{len(final_global)})")
 
-              # Re-rank runs for global leaderboard
+              # re-rank and optimize runs for global leaderboard
+              optimized_global_runs = []
               for i, run in enumerate(final_global):
                   run["ranking"] = i + 1
+                  optimized_run = optimize_run_data(run)
+                  optimized_global_runs.append(optimized_run)
 
               global_path = os.path.join(OUTPUT_ROOT, "global", dungeon_slug)
               os.makedirs(global_path, exist_ok=True)
@@ -167,13 +215,104 @@
                   json.dump({
                       "dungeon_name": data["dungeon_name"],
                       "dungeon_slug": dungeon_slug,
-                      "leaderboard": final_global,
-                  }, f, indent=2)
+                      "leaderboard": optimized_global_runs,
+                  }, f, separators=(',', ':'))
+
+      def optimize_individual_files():
+          print("\nOptimizing individual challenge mode files...")
+
+          search_path = os.path.join(INPUT_ROOT, "**", "*.json")
+          leaderboard_files = glob.glob(search_path, recursive=True)
+
+          if not leaderboard_files:
+              print("No individual files found to optimize.")
+              return
+
+          success_count = 0
+          total_original_size = 0
+          total_optimized_size = 0
+
+          for file_path in leaderboard_files:
+              try:
+                  # get original file size
+                  original_size = os.path.getsize(file_path)
+                  total_original_size += original_size
+
+                  with open(file_path, 'r', encoding='utf-8') as f:
+                      data = json.load(f)
+
+                  # extract and limit leading groups
+                  leading_groups = data.get("leading_groups", [])
+                  original_count = len(leading_groups)
+
+                  if original_count == 0:
+                      continue
+
+                  # limit to TOP_N_PER_REALM records
+                  limited_groups = leading_groups[:TOP_N_PER_REALM]
+
+                  # optimize each run
+                  optimized_groups = []
+                  for i, run in enumerate(limited_groups):
+                      optimized_run = optimize_run_data(run)
+                      optimized_run["ranking"] = i + 1  # Re-rank after limiting
+                      optimized_groups.append(optimized_run)
+
+                  # extract dungeon name
+                  map_name = data.get("map", {}).get("name", {})
+                  dungeon_name = map_name.get("en_US", "Unknown") if isinstance(m
ap_name, dict) else map_name
+
+                  # create optimized data structure
+                  optimized_data = {
+                      "_links": data.get("_links", {}),
+                      "map": {
+                          "name": {"en_US": dungeon_name},
+                          "id": data.get("map", {}).get("id", 0)
+                      },
+                      "period": data.get("period", 0),
+                      "period_start_timestamp": data.get("period_start_timestamp"
, 0),
+                      "period_end_timestamp": data.get("period_end_timestamp", 0)
,
+                      "connected_realm": data.get("connected_realm", {}),
+                      "map_challenge_mode_id": data.get("map_challenge_mode_id", 
0),
+                      "name": {"en_US": dungeon_name},
+                      "leading_groups": optimized_groups
+                  }
+
+                  # write back with minified json
+                  with open(file_path, 'w', encoding='utf-8') as f:
+                      json.dump(optimized_data, f, separators=(',', ':'))
+
+                  # get new file size
+                  optimized_size = os.path.getsize(file_path)
+                  total_optimized_size += optimized_size
+
+                  size_reduction = original_count - len(optimized_groups)
+                  if size_reduction > 0:
+                      print(f"  Optimized {file_path}: {original_count} ? {len(op
timized_groups)} records (-{size_reduction})")
+                  else:
+                      print(f"  Minified {file_path}: {len(optimized_groups)} rec
ords")
+
+                  success_count += 1
+
+              except Exception as e:
+                  print(f"  Error processing {file_path}: {e}")
+
+          print(f"\nIndividual file optimization complete:")
+          print(f"  Files processed: {success_count}/{len(leaderboard_files)}")
+          print(f"  Total size reduction: {total_original_size:,} ? {total_optimi
zed_size:,} bytes")
+
+          if total_original_size > 0:
+              reduction_percent = ((total_original_size - total_optimized_size) /
 total_original_size) * 100
+              print(f"  Size reduction: {reduction_percent:.1f}%")
 
       def main():
+          # first optimize individual files in-place
+          optimize_individual_files()
+
+          # then create aggregated leaderboards
           aggregated_data = parse_and_aggregate_data()
           rank_and_save_leaderboards(aggregated_data)
-          print(f"\nDone. Ranked leaderboards are available in: {os.path.abspath(
OUTPUT_ROOT)}")
+          print(f"\nDone. Individual files optimized and ranked leaderboards avai
lable in: {os.path.abspath(OUTPUT_ROOT)}")
 
 
       if __name__ == "__main__":

diff --git a/nix/apps/challenge-mode-parser.
nix b/nix/apps/challenge-mode-parser.nix
index b2b8764..1a5a1f1 100644
--- a/nix/apps/challenge-mode-parser.nix
+++ b/nix/apps/challenge-mode-parser.nix
@@ -15,13 +15,13 @@
       from pathlib import Path
       import sys
 
-      # The root directory where the fetche
r script saves its data.
+      # the root directory where the fetche
r script saves its data.
       INPUT_ROOT = "./web/public/data/chall
enge-mode"
-      # A new directory to store the proces
sed and ranked leaderboards.
+      # a new directory to store the proces
sed and ranked leaderboards.
       OUTPUT_ROOT = "./web/public/data/lead
erboards"
-      # The number of top runs to collect f
rom each realm's file.
+      # the number of top runs to collect f
rom each realm's file.
       TOP_N_PER_REALM = 50
-      # The number of top runs to keep in f
inal aggregated leaderboards.
+      # the number of top runs to keep in f
inal aggregated leaderboards.
       TOP_N_FINAL = 50
 
       def parse_and_aggregate_data():
@@ -59,8 +59,12 @@
                   continue
 
               if dungeon_slug not in dungeo
n_data:
+                  # extract only the Englis
h name from the multilingual data
+                  map_name = data.get("map"
, {}).get("name", {})
+                  dungeon_name = map_name.g
et("en_US", dungeon_slug) if isinstance(map_
name, dict) else map_name
+
                   dungeon_data[dungeon_slug
] = {
-                      "dungeon_name": data.
get("map", {}).get("name", {}).get("en_US", 
dungeon_slug),
+                      "dungeon_name": dunge
on_name,
                       "runs": {"us": [], "e
u": [], "kr": []}
                   }
 
@@ -76,13 +80,18 @@
 
 
       def deduplicate_runs(runs):
-          # Remove duplicate runs caused by
 cross-realm groups appearing on multiple re
alm leaderboards
+          # remove duplicate runs caused by
 cross-realm groups appearing on multiple re
alm leaderboards
           seen = set()
           deduplicated = []
 
           for run in runs:
-              # Create a unique identifier 
for each run using timestamp, duration, and 
sorted player IDs
-              player_ids = sorted([member["
profile"]["id"] for member in run["members"]
])
+              # create a unique identifier 
for each run using timestamp, duration, and 
sorted player IDs
+              # support both old format (me
mber["profile"]["id"]) and optimized format 
(member["id"])
+              player_ids = []
+              for member in run["members"]:
+                  member_id = member.get("i
d") or member.get("profile", {}).get("id", 0
)
+                  player_ids.append(member_
id)
+              player_ids = sorted(player_id
s)
               unique_key = (run["completed_
timestamp"], run["duration"], tuple(player_i
ds))
 
               if unique_key not in seen:
@@ -93,6 +102,40 @@
 
           return deduplicated
 
+      def optimize_run_data(run):
+          # optimize individual run data to
 remove redundant information
+          optimized_run = {
+              "ranking": run["ranking"],
+              "duration": run["duration"],
+              "completed_timestamp": run["c
ompleted_timestamp"],
+              "keystone_level": run.get("ke
ystone_level", 1),
+              "members": []
+          }
+
+          # add realm and region info if pr
esent
+          if "realm_slug" in run:
+              optimized_run["realm_slug"] =
 run["realm_slug"]
+          if "region" in run:
+              optimized_run["region"] = run
["region"]
+
+          # optimize member data - handle b
oth old format and already optimized format
+          for member in run.get("members", 
[]):
+              if "profile" in member:
+                  # old format with nested 
profile data
+                  optimized_member = {
+                      "name": member["profi
le"]["name"],
+                      "id": member["profile
"]["id"],
+                      "realm_slug": member[
"profile"]["realm"]["slug"],
+                      "faction": member["fa
ction"]["type"],
+                      "spec_id": member["sp
ecialization"]["id"]
+                  }
+              else:
+                  # already optimized forma
t - just copy it
+                  optimized_member = member
.copy()
+              optimized_run["members"].appe
nd(optimized_member)
+
+          return optimized_run
+
       def rank_and_save_leaderboards(dungeo
n_data):
           # sorts the aggregated data to cr
eate regional and global leaderboards,
           # then saves them to new JSON fil
es
@@ -108,27 +151,30 @@
               print(f"  Processing dungeon:
 {data['dungeon_name']}")
               all_regional_runs = []
 
-              # 1. Generate and save REGION
AL leaderboards
+              # generate and save REGIONAL 
leaderboards
               regional_path = os.path.join(
OUTPUT_ROOT, "regional")
               for region, runs in data["run
s"].items():
                   if not runs:
                       continue
 
-                  # Deduplicate and sort re
gional runs
+                  # deduplicate and sort re
gional runs
                   print(f"    Deduplicating
 {region.upper()} runs ({len(runs)} -> ", en
d="")
                   deduplicated_runs = dedup
licate_runs(runs)
                   print(f"{len(deduplicated
_runs)} -> ", end="")
                   deduplicated_runs.sort(ke
y=sort_key)
 
-                  # Limit to top N runs for
 regional leaderboard
+                  # limit to top N runs for
 regional leaderboard
                   final_runs = deduplicated
_runs[:TOP_N_FINAL]
                   print(f"{len(final_runs)}
)")
 
-                  # Re-rank runs for region
al leaderboard
+                  # re-rank and optimize ru
ns for regional leaderboard
+                  optimized_runs = []
                   for i, run in enumerate(f
inal_runs):
                       run["ranking"] = i + 
1
+                      optimized_run = optim
ize_run_data(run)
+                      optimized_runs.append
(optimized_run)
 
-                  all_regional_runs.extend(
final_runs)
+                  all_regional_runs.extend(
optimized_runs)
                   output_dir = os.path.join
(regional_path, region, dungeon_slug)
                   os.makedirs(output_dir, e
xist_ok=True)
                   output_file = os.path.joi
n(output_dir, "leaderboard.json")
@@ -138,26 +184,28 @@
                           "dungeon_name": d
ata["dungeon_name"],
                           "dungeon_slug": d
ungeon_slug,
                           "region": region,
-                          "leaderboard": fi
nal_runs,
-                      }, f, indent=2)
+                          "leaderboard": op
timized_runs,
+                      }, f, separators=(','
, ':'))
 
-              # 2. Generate and save GLOBAL
 leaderboard
               if not all_regional_runs:
                   continue
 
-              # Deduplicate global runs (cr
oss-region duplicates)
+              # deduplicate global runs (cr
oss-region duplicates)
               print(f"    Deduplicating glo
bal runs ({len(all_regional_runs)} -> ", end
="")
               deduplicated_global = dedupli
cate_runs(all_regional_runs)
               print(f"{len(deduplicated_glo
bal)} -> ", end="")
               deduplicated_global.sort(key=
sort_key)
 
-              # Limit to top N runs for glo
bal leaderboard
+              # limit to top N runs for glo
bal leaderboard
               final_global = deduplicated_g
lobal[:TOP_N_FINAL]
               print(f"{len(final_global)})"
)
 
-              # Re-rank runs for global lea
derboard
+              # re-rank and optimize runs f
or global leaderboard
+              optimized_global_runs = []
               for i, run in enumerate(final
_global):
                   run["ranking"] = i + 1
+                  optimized_run = optimize_
run_data(run)
+                  optimized_global_runs.app
end(optimized_run)
 
               global_path = os.path.join(OU
TPUT_ROOT, "global", dungeon_slug)
               os.makedirs(global_path, exis
t_ok=True)
@@ -167,13 +215,104 @@
                   json.dump({
                       "dungeon_name": data[
"dungeon_name"],
                       "dungeon_slug": dunge
on_slug,
-                      "leaderboard": final_
global,
-                  }, f, indent=2)
+                      "leaderboard": optimi
zed_global_runs,
+                  }, f, separators=(',', ':
'))
+
+      def optimize_individual_files():
+          print("\nOptimizing individual ch
allenge mode files...")
+
+          search_path = os.path.join(INPUT_
ROOT, "**", "*.json")
+          leaderboard_files = glob.glob(sea
rch_path, recursive=True)
+
+          if not leaderboard_files:
+              print("No individual files fo
und to optimize.")
+              return
+
+          success_count = 0
+          total_original_size = 0
+          total_optimized_size = 0
+
+          for file_path in leaderboard_file
s:
+              try:
+                  # get original file size
+                  original_size = os.path.g
etsize(file_path)
+                  total_original_size += or
iginal_size
+
+                  with open(file_path, 'r',
 encoding='utf-8') as f:
+                      data = json.load(f)
+
+                  # extract and limit leadi
ng groups
+                  leading_groups = data.get
("leading_groups", [])
+                  original_count = len(lead
ing_groups)
+
+                  if original_count == 0:
+                      continue
+
+                  # limit to TOP_N_PER_REAL
M records
+                  limited_groups = leading_
groups[:TOP_N_PER_REALM]
+
+                  # optimize each run
+                  optimized_groups = []
+                  for i, run in enumerate(l
imited_groups):
+                      optimized_run = optim
ize_run_data(run)
+                      optimized_run["rankin
g"] = i + 1  # Re-rank after limiting
+                      optimized_groups.appe
nd(optimized_run)
+
+                  # extract dungeon name
+                  map_name = data.get("map"
, {}).get("name", {})
+                  dungeon_name = map_name.g
et("en_US", "Unknown") if isinstance(map_nam
e, dict) else map_name
+
+                  # create optimized data s
tructure
+                  optimized_data = {
+                      "_links": data.get("_
links", {}),
+                      "map": {
+                          "name": {"en_US":
 dungeon_name},
+                          "id": data.get("m
ap", {}).get("id", 0)
+                      },
+                      "period": data.get("p
eriod", 0),
+                      "period_start_timesta
mp": data.get("period_start_timestamp", 0),
+                      "period_end_timestamp
": data.get("period_end_timestamp", 0),
+                      "connected_realm": da
ta.get("connected_realm", {}),
+                      "map_challenge_mode_i
d": data.get("map_challenge_mode_id", 0),
+                      "name": {"en_US": dun
geon_name},
+                      "leading_groups": opt
imized_groups
+                  }
+
+                  # write back with minifie
d json
+                  with open(file_path, 'w',
 encoding='utf-8') as f:
+                      json.dump(optimized_d
ata, f, separators=(',', ':'))
+
+                  # get new file size
+                  optimized_size = os.path.
getsize(file_path)
+                  total_optimized_size += o
ptimized_size
+
+                  size_reduction = original
_count - len(optimized_groups)
+                  if size_reduction > 0:
+                      print(f"  Optimized {
file_path}: {original_count} ? {len(optimize
d_groups)} records (-{size_reduction})")
+                  else:
+                      print(f"  Minified {f
ile_path}: {len(optimized_groups)} records")
+
+                  success_count += 1
+
+              except Exception as e:
+                  print(f"  Error processin
g {file_path}: {e}")
+
+          print(f"\nIndividual file optimiz
ation complete:")
+          print(f"  Files processed: {succe
ss_count}/{len(leaderboard_files)}")
+          print(f"  Total size reduction: {
total_original_size:,} ? {total_optimized_si
ze:,} bytes")
+
+          if total_original_size > 0:
+              reduction_percent = ((total_o
riginal_size - total_optimized_size) / total
_original_size) * 100
+              print(f"  Size reduction: {re
duction_percent:.1f}%")
 
       def main():
+          # first optimize individual files
 in-place
+          optimize_individual_files()
+
+          # then create aggregated leaderbo
ards
           aggregated_data = parse_and_aggre
gate_data()
           rank_and_save_leaderboards(aggreg
ated_data)
-          print(f"\nDone. Ranked leaderboar
ds are available in: {os.path.abspath(OUTPUT
_ROOT)}")
+          print(f"\nDone. Individual files 
optimized and ranked leaderboards available 
in: {os.path.abspath(OUTPUT_ROOT)}")
 
 
       if __name__ == "__main__":
 

diff --git a/web/src/layouts/ChallengeModeLayout.astro b/web/src/layouts/Challenge
ModeLayout.astro
index 80ebc94..2b499ba 100644
--- a/web/src/layouts/ChallengeModeLayout.astro
+++ b/web/src/layouts/ChallengeModeLayout.astro
@@ -456,8 +456,8 @@ const baseUrl = import.meta.env.BASE_URL;
 
     let teamHtml = "";
     group.members.forEach((member) => {
-      // Handle missing specialization data (deleted/transferred characters)
-      const specId = member.specialization?.id;
+      // Handle both old format (member.specialization.id) and optimized format (
member.spec_id)
+      const specId = member.spec_id || member.specialization?.id;
       const spec = specId
         ? window.WoW.getSpecInfo(specId)
         : {
@@ -476,12 +476,15 @@ const baseUrl = import.meta.env.BASE_URL;
           '" style="width: 16px; height: 16px; border-radius: 2px; margin-right: 
4px; vertical-align: middle; flex-shrink: 0;">'
         : "";
 
+      // Handle both old format (member.profile.name) and optimized format (membe
r.name)
+      let playerName = member.name || member.profile?.name;
+      
       // Check if player is from a different realm (for individual realm views on
ly)
-      let playerName = member.profile.name;
+      const memberRealmSlug = member.realm_slug || member.profile?.realm?.slug;
       if (
         isIndividualRealmView &&
-        member.profile.realm?.slug &&
-        member.profile.realm.slug !== currentRealm
+        memberRealmSlug &&
+        memberRealmSlug !== currentRealm
       ) {
         playerName +=
           '<span style="color: #ff6b6b; font-weight: bold; margin-left: 2px;">*</
span>';

diff --git a/web/src/layouts/ChallengeModeLa
yout.astro b/web/src/layouts/ChallengeModeLa
yout.astro
index 80ebc94..2b499ba 100644
--- a/web/src/layouts/ChallengeModeLayout.as
tro
+++ b/web/src/layouts/ChallengeModeLayout.as
tro
@@ -456,8 +456,8 @@ const baseUrl = import.m
eta.env.BASE_URL;
 
     let teamHtml = "";
     group.members.forEach((member) => {
-      // Handle missing specialization data
 (deleted/transferred characters)
-      const specId = member.specialization?
.id;
+      // Handle both old format (member.spe
cialization.id) and optimized format (member
.spec_id)
+      const specId = member.spec_id || memb
er.specialization?.id;
       const spec = specId
         ? window.WoW.getSpecInfo(specId)
         : {
@@ -476,12 +476,15 @@ const baseUrl = import
.meta.env.BASE_URL;
           '" style="width: 16px; height: 16
px; border-radius: 2px; margin-right: 4px; v
ertical-align: middle; flex-shrink: 0;">'
         : "";
 
+      // Handle both old format (member.pro
file.name) and optimized format (member.name
)
+      let playerName = member.name || membe
r.profile?.name;
+      
       // Check if player is from a differen
t realm (for individual realm views only)
-      let playerName = member.profile.name;
+      const memberRealmSlug = member.realm_
slug || member.profile?.realm?.slug;
       if (
         isIndividualRealmView &&
-        member.profile.realm?.slug &&
-        member.profile.realm.slug !== curre
ntRealm
+        memberRealmSlug &&
+        memberRealmSlug !== currentRealm
       ) {
         playerName +=
           '<span style="color: #ff6b6b; fon
t-weight: bold; margin-left: 2px;">*</span>'
;
 
[ BACK TO LOG ]
──────────────────────────────────────────────────────────────────────────────────────
OOKNET
────────────────────────────────────────────────
OOKNET