diff --git a/src/webui/blueprints/pages.py b/src/webui/blueprints/pages.py
index b16cc9b..b301ca1 100644
--- a/src/webui/blueprints/pages.py
+++ b/src/webui/blueprints/pages.py
@@ -11,7 +11,6 @@ from webui.data import (
get_draft_detail,
get_rating_distributions,
get_timeline_data,
- get_timeline_animation_data,
get_ideas_by_type,
get_top_authors,
get_org_data,
@@ -127,12 +126,6 @@ def ratings():
)
-@pages_bp.route("/timeline")
-def timeline_animation():
- data = get_timeline_animation_data(db())
- return render_template("timeline.html", animation=data)
-
-
@pages_bp.route("/idea-clusters")
def idea_clusters():
data = get_idea_clusters(db())
diff --git a/src/webui/data/__init__.py b/src/webui/data/__init__.py
index 6ac956e..338c79d 100644
--- a/src/webui/data/__init__.py
+++ b/src/webui/data/__init__.py
@@ -69,7 +69,6 @@ from webui.data.analysis import ( # noqa: F401
get_timeline_data,
get_similarity_graph,
get_idea_clusters,
- get_timeline_animation_data,
get_monitor_status,
get_citation_graph,
get_landscape_tsne,
diff --git a/src/webui/data/analysis.py b/src/webui/data/analysis.py
index 0a6af66..48559e6 100644
--- a/src/webui/data/analysis.py
+++ b/src/webui/data/analysis.py
@@ -502,81 +502,6 @@ def _compute_idea_clusters(db: Database) -> dict:
"empty": False,
}
-def get_timeline_animation_data(db: Database) -> dict:
- """Timeline animation (cached for 5 min)."""
- return _cached("timeline_animation", lambda: _compute_timeline_animation_data(db))
-
-def _compute_timeline_animation_data(db: Database) -> dict:
- """Compute t-SNE on all drafts, return points with month info + category_monthly.
-
- t-SNE is computed once on ALL drafts so coordinates are stable across
- animation frames. Each point carries a ``month`` field (YYYY-MM) so the
- front-end can build cumulative animation frames.
- """
-
-
- embeddings = db.all_embeddings()
- if len(embeddings) < 5:
- return {"points": [], "months": [], "category_monthly": {}}
-
- pairs = db.drafts_with_ratings(limit=1000)
- rating_map = {d.name: r for d, r in pairs}
- draft_map = {d.name: d for d, _ in pairs}
-
- # Filter to drafts that have both embeddings and ratings
- names = [n for n in embeddings if n in rating_map]
- if len(names) < 5:
- return {"points": [], "months": [], "category_monthly": {}}
-
- matrix = np.array([embeddings[n] for n in names])
-
- try:
- tsne = TSNE(n_components=2, perplexity=min(30, len(names) - 1),
- random_state=42, max_iter=500)
- coords = tsne.fit_transform(matrix)
- except Exception:
- return {"points": [], "months": [], "category_monthly": {}}
-
- # Build points with month
- points = []
- month_set: set[str] = set()
- category_monthly: dict[str, dict[str, int]] = defaultdict(lambda: defaultdict(int))
-
- for i, name in enumerate(names):
- r = rating_map[name]
- d = draft_map.get(name)
- month = _extract_month(d.time if d else None)
- if month == "unknown":
- continue # Undated docs (e.g. ISO/ETSI) can't be placed on a temporal animation
- cat = r.categories[0] if r.categories else "Other"
- month_set.add(month)
- category_monthly[month][cat] += 1
- points.append({
- "name": name,
- "title": d.title if d else name,
- "x": round(float(coords[i, 0]), 3),
- "y": round(float(coords[i, 1]), 3),
- "category": cat,
- "score": round(r.composite_score, 2),
- "month": month,
- })
-
- # Deliver points in chronological order so the front-end's cumulative
- # filter (p.month <= frame) is append-only. Otherwise new points get
- # inserted mid-array and Plotly's index-based frame transition animates
- # existing markers flying to other drafts' coordinates ("jumping points").
- points.sort(key=lambda p: (p["month"], p["name"]))
-
- months = sorted(month_set)
- # Convert defaultdict to plain dict for JSON
- cat_monthly_plain = {m: dict(cats) for m, cats in category_monthly.items()}
-
- return {
- "points": points,
- "months": months,
- "category_monthly": cat_monthly_plain,
- }
-
def get_monitor_status(db: Database) -> MonitorStatus:
"""Return monitoring status data for dashboard."""
runs = db.get_monitor_runs(limit=20)
diff --git a/src/webui/templates/base.html b/src/webui/templates/base.html
index 75f1144..a02e7e1 100644
--- a/src/webui/templates/base.html
+++ b/src/webui/templates/base.html
@@ -156,10 +156,6 @@
Blog Drafts
{% endif %}
-
{% if is_admin %}