areebithink Claude Opus 4.8 commited on
Commit
38091a2
·
1 Parent(s): 1441c1f

Add /tools suite page cross-linking Macro Intelligence

Browse files

New data-driven /tools page presenting the maker's tools as one suite:
Sentiments Analyzer (this) + Macro Intelligence (macro.areebalikhan.com),
so users discover the other tools. Card grid with tags, "You are here"
badge, ItemList structured data. Adds "Tools" to the site navbar, landing
nav, footer and the terminal topbar; robots.txt + sitemap include it.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

content/site_content.py CHANGED
@@ -55,6 +55,37 @@ AUTHOR = {
55
  "site": "https://areebalikhan.com/",
56
  }
57
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
58
  # ---------------------------------------------------------------------------
59
  # ARTICLES (long-tail, educational, each internally links back to the product)
60
  # body is a list of ("h2", text) / ("p", html) / ("ul", [items]) / ("cta", None)
@@ -493,6 +524,7 @@ def _nav(path: str) -> str:
493
  <span class="n">SENTIMENTS <b>ANALYZER</b></span>
494
  </a>
495
  <span class="navcta">
 
496
  <a class="link"{cls('/articles')} href="/articles">Articles</a>
497
  <a class="link"{cls('/faq')} href="/faq">FAQ</a>
498
  <a class="link"{cls('/about')} href="/about">About</a>
@@ -508,6 +540,7 @@ def _footer() -> str:
508
  return f"""<footer>
509
  &copy; {year} {SITE_NAME}
510
  &nbsp;&middot;&nbsp; <a href="/">Home</a>
 
511
  &nbsp;&middot;&nbsp; <a href="/articles">Articles</a>
512
  &nbsp;&middot;&nbsp; <a href="/faq">FAQ</a>
513
  &nbsp;&middot;&nbsp; <a href="/about">About</a>
@@ -561,6 +594,26 @@ nav .btn:hover{background:var(--accent2)}
561
  .page-head h1{font-size:32px;font-weight:800;letter-spacing:-0.5px}
562
  .page-head h1 .g{color:var(--accent)}
563
  .page-head p{color:var(--dim);font-size:15px;margin-top:12px;max-width:600px;margin-left:auto;margin-right:auto}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
564
  .eyebrow{color:var(--accent);font-size:12px;letter-spacing:1.6px;font-weight:800;text-transform:uppercase}
565
  /* article list cards */
566
  .alist{display:grid;gap:14px;margin-top:30px}
@@ -928,5 +981,51 @@ def render_about(base: str) -> str:
928
  body, head_extra=_jsonld(ld))
929
 
930
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
931
  def article_slugs() -> list[str]:
932
  return [a["slug"] for a in ARTICLES]
 
55
  "site": "https://areebalikhan.com/",
56
  }
57
 
58
+ # ---------------------------------------------------------------------------
59
+ # TOOLS (the maker's suite — cross-links related products for discovery + SEO)
60
+ # Set "current": True on the tool that IS this site.
61
+ # ---------------------------------------------------------------------------
62
+ TOOLS = [
63
+ {
64
+ "name": "Sentiments Analyzer",
65
+ "kind": "Crypto sentiment & narratives",
66
+ "tagline": "Read the crypto market's mood in one number.",
67
+ "description": "Reads hundreds of crypto headlines and posts a day, scores "
68
+ "sentiment 0-100, tracks trending narratives, flags manufactured "
69
+ "hype and shows sentiment vs price, with an AI analyst and a "
70
+ "transparent, publicly-scored track record.",
71
+ "tags": ["Sentiment", "Narratives", "AI analyst", "Public API"],
72
+ "url": "/terminal",
73
+ "current": True,
74
+ },
75
+ {
76
+ "name": "Macro Intelligence",
77
+ "kind": "Global macro regime & risk",
78
+ "tagline": "Live global macro regime & risk score.",
79
+ "description": "Synthesizes the dollar, interest rates, inflation, growth and "
80
+ "central-bank policy into one explainable 0-100 macro score, with "
81
+ "live regime classification, indicator z-scores, signal "
82
+ "contributions and email alerts on regime shifts.",
83
+ "tags": ["Macro", "Risk score", "Regime", "Alerts"],
84
+ "url": "https://macro.areebalikhan.com/",
85
+ "current": False,
86
+ },
87
+ ]
88
+
89
  # ---------------------------------------------------------------------------
90
  # ARTICLES (long-tail, educational, each internally links back to the product)
91
  # body is a list of ("h2", text) / ("p", html) / ("ul", [items]) / ("cta", None)
 
524
  <span class="n">SENTIMENTS <b>ANALYZER</b></span>
525
  </a>
526
  <span class="navcta">
527
+ <a class="link"{cls('/tools')} href="/tools">Tools</a>
528
  <a class="link"{cls('/articles')} href="/articles">Articles</a>
529
  <a class="link"{cls('/faq')} href="/faq">FAQ</a>
530
  <a class="link"{cls('/about')} href="/about">About</a>
 
540
  return f"""<footer>
541
  &copy; {year} {SITE_NAME}
542
  &nbsp;&middot;&nbsp; <a href="/">Home</a>
543
+ &nbsp;&middot;&nbsp; <a href="/tools">Tools</a>
544
  &nbsp;&middot;&nbsp; <a href="/articles">Articles</a>
545
  &nbsp;&middot;&nbsp; <a href="/faq">FAQ</a>
546
  &nbsp;&middot;&nbsp; <a href="/about">About</a>
 
594
  .page-head h1{font-size:32px;font-weight:800;letter-spacing:-0.5px}
595
  .page-head h1 .g{color:var(--accent)}
596
  .page-head p{color:var(--dim);font-size:15px;margin-top:12px;max-width:600px;margin-left:auto;margin-right:auto}
597
+ /* tools suite */
598
+ .tools{display:grid;gap:16px;margin-top:30px}
599
+ .tool{display:block;background:var(--panel);backdrop-filter:blur(10px);border:1px solid var(--border);
600
+ border-radius:16px;padding:24px;transition:.15s;position:relative}
601
+ .tool:hover{border-color:rgba(232,163,61,0.45);transform:translateY(-2px)}
602
+ .tool .kind{color:var(--accent);font-size:11px;letter-spacing:1.4px;font-weight:800;text-transform:uppercase}
603
+ .tool h2{color:var(--white);font-size:21px;font-weight:800;margin:6px 0 4px;display:flex;align-items:center;gap:10px;flex-wrap:wrap}
604
+ .tool .badge{font-size:10px;font-weight:700;letter-spacing:.5px;padding:2px 9px;border-radius:20px;
605
+ border:1px solid var(--border);color:var(--dim)}
606
+ .tool .badge.here{color:var(--accent);border-color:rgba(232,163,61,0.4);background:rgba(232,163,61,0.08)}
607
+ .tool .badge.live{color:var(--green);border-color:rgba(43,214,123,0.4);background:rgba(43,214,123,0.08)}
608
+ .tool .tl2{color:#c8ccd6;font-size:14.5px;font-weight:600;margin-bottom:8px}
609
+ .tool .desc{color:var(--dim);font-size:14px;line-height:1.7}
610
+ .tool .tags{display:flex;gap:7px;flex-wrap:wrap;margin-top:14px}
611
+ .tool .tags span{font-size:11.5px;color:var(--dim);background:rgba(255,255,255,0.04);
612
+ border:1px solid var(--border);border-radius:7px;padding:4px 10px;font-family:var(--mono)}
613
+ .tool .go{display:inline-block;margin-top:16px;color:var(--accent);font-weight:700;font-size:13.5px}
614
+ .tool .go:hover{color:var(--accent2)}
615
+ :root[data-theme="light"] .tool .tl2{color:#333a45}
616
+ :root[data-theme="light"] .tool .tags span{background:rgba(0,0,0,0.03)}
617
  .eyebrow{color:var(--accent);font-size:12px;letter-spacing:1.6px;font-weight:800;text-transform:uppercase}
618
  /* article list cards */
619
  .alist{display:grid;gap:14px;margin-top:30px}
 
981
  body, head_extra=_jsonld(ld))
982
 
983
 
984
+ def render_tools(base: str) -> str:
985
+ import json
986
+ cards = []
987
+ for t in TOOLS:
988
+ ext = t["url"].startswith("http")
989
+ attrs = ' target="_blank" rel="noopener"' if ext else ""
990
+ badge = ('<span class="badge here">You are here</span>' if t.get("current")
991
+ else '<span class="badge live">Live</span>')
992
+ tags = "".join(f"<span>{escape(x)}</span>" for x in t["tags"])
993
+ go = ("Explore this tool &rarr;" if not t.get("current")
994
+ else "Open the terminal &rarr;")
995
+ go_href = "/terminal" if t.get("current") else t["url"]
996
+ cards.append(
997
+ f'<a class="tool" href="{escape(t["url"])}"{attrs}>'
998
+ f'<div class="kind">{escape(t["kind"])}</div>'
999
+ f'<h2>{escape(t["name"])} {badge}</h2>'
1000
+ f'<div class="tl2">{escape(t["tagline"])}</div>'
1001
+ f'<div class="desc">{escape(t["description"])}</div>'
1002
+ f'<div class="tags">{tags}</div>'
1003
+ f'<span class="go">{go}</span></a>'
1004
+ )
1005
+ body = (
1006
+ '<div class="page-head">'
1007
+ '<span class="eyebrow">The toolkit</span>'
1008
+ '<h1>More <span class="g">market intelligence</span> tools</h1>'
1009
+ '<p>A small suite of tools built by the same maker, each turns a complex '
1010
+ 'market signal into one clear, explainable number. Explore the others below.</p>'
1011
+ '</div>'
1012
+ f'<div class="tools">{"".join(cards)}</div>'
1013
+ )
1014
+ ld = json.dumps({
1015
+ "@context": "https://schema.org",
1016
+ "@type": "ItemList",
1017
+ "itemListElement": [
1018
+ {"@type": "ListItem", "position": i + 1, "name": t["name"],
1019
+ "url": (t["url"] if t["url"].startswith("http") else f"{base}{t['url']}")}
1020
+ for i, t in enumerate(TOOLS)
1021
+ ],
1022
+ })
1023
+ return _shell(base, "/tools", f"Tools · {SITE_NAME}",
1024
+ "A suite of market-intelligence tools by Areeb Ali: Sentiments "
1025
+ "Analyzer for crypto sentiment & narratives, and Macro Intelligence "
1026
+ "for a live global macro regime & risk score.",
1027
+ body, head_extra=_jsonld(ld))
1028
+
1029
+
1030
  def article_slugs() -> list[str]:
1031
  return [a["slug"] for a in ARTICLES]
server.py CHANGED
@@ -734,6 +734,11 @@ async def about_page(request: Request):
734
  return HTMLResponse(site_content.render_about(_public_base(request)))
735
 
736
 
 
 
 
 
 
737
  # ---------------------------------------------------------------------------
738
  # Auth pages + API (accounts foundation; terminal stays preview-gated for now)
739
  # ---------------------------------------------------------------------------
@@ -1005,6 +1010,7 @@ async def robots(request: Request):
1005
  body = (
1006
  "User-agent: *\n"
1007
  "Allow: /$\n"
 
1008
  "Allow: /articles\n"
1009
  "Allow: /faq\n"
1010
  "Allow: /about\n"
@@ -1028,6 +1034,8 @@ async def sitemap(request: Request):
1028
  '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
1029
  f" <url><loc>{base}/</loc><lastmod>{today}</lastmod>"
1030
  "<changefreq>daily</changefreq><priority>1.0</priority></url>\n"
 
 
1031
  f" <url><loc>{base}/articles</loc><lastmod>{today}</lastmod>"
1032
  "<changefreq>weekly</changefreq><priority>0.8</priority></url>\n"
1033
  f" <url><loc>{base}/faq</loc><lastmod>{today}</lastmod>"
 
734
  return HTMLResponse(site_content.render_about(_public_base(request)))
735
 
736
 
737
+ @app.api_route("/tools", methods=["GET", "HEAD"], response_class=HTMLResponse)
738
+ async def tools_page(request: Request):
739
+ return HTMLResponse(site_content.render_tools(_public_base(request)))
740
+
741
+
742
  # ---------------------------------------------------------------------------
743
  # Auth pages + API (accounts foundation; terminal stays preview-gated for now)
744
  # ---------------------------------------------------------------------------
 
1010
  body = (
1011
  "User-agent: *\n"
1012
  "Allow: /$\n"
1013
+ "Allow: /tools\n"
1014
  "Allow: /articles\n"
1015
  "Allow: /faq\n"
1016
  "Allow: /about\n"
 
1034
  '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n'
1035
  f" <url><loc>{base}/</loc><lastmod>{today}</lastmod>"
1036
  "<changefreq>daily</changefreq><priority>1.0</priority></url>\n"
1037
+ f" <url><loc>{base}/tools</loc><lastmod>{today}</lastmod>"
1038
+ "<changefreq>monthly</changefreq><priority>0.7</priority></url>\n"
1039
  f" <url><loc>{base}/articles</loc><lastmod>{today}</lastmod>"
1040
  "<changefreq>weekly</changefreq><priority>0.8</priority></url>\n"
1041
  f" <url><loc>{base}/faq</loc><lastmod>{today}</lastmod>"
templates/index.html CHANGED
@@ -975,6 +975,7 @@ body.hint-dismissed #beginner-hint { display: none !important; }
975
  </span>
976
  <a class="tb-link" id="tb-brief" href="/signup" style="display:none;background:var(--accent);color:#0a0b0e;border-color:var(--accent);font-weight:700">&#128233; Get daily brief</a>
977
  <a class="tb-link" id="tb-account" href="/account" style="display:none">&#128100; Account</a>
 
978
  <a class="tb-link" href="https://areeb.instatus.com" target="_blank" title="Service status">&#9679; STATUS</a>
979
  <a class="tb-link" href="/terms" target="_blank">TERMS</a>
980
  <button class="theme-toggle" id="theme-toggle" onclick="toggleTheme()" title="Toggle light/dark" aria-label="Toggle theme">&#9789;</button>
 
975
  </span>
976
  <a class="tb-link" id="tb-brief" href="/signup" style="display:none;background:var(--accent);color:#0a0b0e;border-color:var(--accent);font-weight:700">&#128233; Get daily brief</a>
977
  <a class="tb-link" id="tb-account" href="/account" style="display:none">&#128100; Account</a>
978
+ <a class="tb-link" href="/tools" title="More tools">TOOLS</a>
979
  <a class="tb-link" href="https://areeb.instatus.com" target="_blank" title="Service status">&#9679; STATUS</a>
980
  <a class="tb-link" href="/terms" target="_blank">TERMS</a>
981
  <button class="theme-toggle" id="theme-toggle" onclick="toggleTheme()" title="Toggle light/dark" aria-label="Toggle theme">&#9789;</button>
templates/join.html CHANGED
@@ -147,6 +147,7 @@ footer a{color:var(--dim)}
147
  </a>
148
  <span class="navcta">
149
  <a class="link" href="#how">How it works</a>
 
150
  <a class="link" href="/articles">Articles</a>
151
  <a class="link" href="/faq">FAQ</a>
152
  <a class="link" href="/about">About</a>
 
147
  </a>
148
  <span class="navcta">
149
  <a class="link" href="#how">How it works</a>
150
+ <a class="link" href="/tools">Tools</a>
151
  <a class="link" href="/articles">Articles</a>
152
  <a class="link" href="/faq">FAQ</a>
153
  <a class="link" href="/about">About</a>