SPB Git

spb/airiskindex Public

The most methodologically rigorous, fully transparent AI job-exposure index.

TypeScript 88% Python 6.1% SQL 2.7% CSS 1.2% JavaScript 0.9% Shell 0.8%

feat(web): SVG brand logo (ranked score bars) + favicon via app/icon.svg

LogoMark wired into header, footer and mobile drawer; full logo with
CI-whisker signature in public/logo.svg.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
simon-pierre boucher committed 6 days ago (Aug 5, 2026) parent dd2c367

Showing 5 changed files with +53 and −12

added apps/web/app/icon.svg +11 −0
@@ -0,0 +1,11 @@
1 +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
2 + <!--
3 + AI Risk Index favicon — ranked score bars, sharp cut.
4 + Author: Simon-Pierre Boucher · contact@spboucher.ai
5 + Copyright © 2026 Simon-Pierre Boucher. All rights reserved.
6 + -->
7 + <rect width="64" height="64" rx="12" fill="#2a78d6"/>
8 + <rect x="13" y="14" width="38" height="9" rx="2" fill="#ffffff"/>
9 + <rect x="13" y="28" width="27" height="9" rx="2" fill="#ffffff" opacity="0.82"/>
10 + <rect x="13" y="42" width="16" height="9" rx="2" fill="#ffffff" opacity="0.62"/>
11 +</svg>
modified apps/web/app/layout.tsx +5 −10
@@ -12,6 +12,7 @@ import Link from "next/link";
12 12 import type { ReactNode } from "react";
13 13 import { prisma } from "@airiskindex/db";
14 14 import { INDEX_VERSION } from "@airiskindex/scoring";
15 +import { LogoMark } from "@/components/logo";
15 16 import { MobileMenu } from "@/components/mobile-menu";
16 17 import "./globals.css";
17 18
@@ -77,11 +78,8 @@ export default async function RootLayout({
77 78 )}
78 79 <header className="sticky top-0 z-40 border-b border-[var(--border)] backdrop-blur-md [background:var(--header)]">
79 80 <nav className="relative mx-auto flex max-w-5xl items-center justify-between gap-3 px-4 py-3 sm:px-6">
80 <Link href="/" className="flex shrink-0 items-center gap-2 font-semibold tracking-tight">
81 <span
82 aria-hidden="true"
83 className="inline-block h-2.5 w-2.5 rounded-full bg-[var(--seq)]"
84 />
81 + <Link href="/" className="flex shrink-0 items-center gap-2.5 font-semibold tracking-tight">
82 + <LogoMark size={24} />
85 83 AI Risk Index
86 84 </Link>
87 85 <div className="hidden items-center gap-6 text-sm text-[var(--ink-2)] sm:flex">
@@ -102,11 +100,8 @@ export default async function RootLayout({
102 100 <footer className="mt-20 border-t border-[var(--border)] bg-[var(--surface-1)]">
103 101 <div className="mx-auto grid max-w-5xl gap-8 px-4 py-10 sm:grid-cols-3 sm:px-6">
104 102 <div>
105 <p className="flex items-center gap-2 font-semibold tracking-tight">
106 <span
107 aria-hidden="true"
108 className="inline-block h-2 w-2 rounded-full bg-[var(--seq)]"
109 />
103 + <p className="flex items-center gap-2.5 font-semibold tracking-tight">
104 + <LogoMark size={20} />
110 105 AI Risk Index
111 106 </p>
112 107 <p className="mt-2 text-xs leading-relaxed text-[var(--muted)]">
added apps/web/components/logo.tsx +19 −0
@@ -0,0 +1,19 @@
1 +// File: logo.tsx
2 +// Path: apps/web/components/logo.tsx
3 +// Project: AI Risk Index — airiskindex.io
4 +// Author: Simon-Pierre Boucher
5 +// Contact: contact@spboucher.ai
6 +// Copyright © 2026 Simon-Pierre Boucher. All rights reserved.
7 +//
8 +// Description: Brand mark — ranked score bars, sharp cut, on the index blue.
9 +
10 +export function LogoMark({ size = 22 }: { size?: number }): JSX.Element {
11 + return (
12 + <svg width={size} height={size} viewBox="0 0 64 64" aria-hidden="true" className="shrink-0">
13 + <rect width="64" height="64" rx="12" fill="var(--seq)" />
14 + <rect x="13" y="14" width="38" height="9" rx="2" fill="#ffffff" />
15 + <rect x="13" y="28" width="27" height="9" rx="2" fill="#ffffff" opacity="0.82" />
16 + <rect x="13" y="42" width="16" height="9" rx="2" fill="#ffffff" opacity="0.62" />
17 + </svg>
18 + );
19 +}
modified apps/web/components/mobile-menu.tsx +3 −2
@@ -13,6 +13,7 @@
13 13 import Link from "next/link";
14 14 import { useEffect, useState } from "react";
15 15 import { createPortal } from "react-dom";
16 +import { LogoMark } from "./logo";
16 17
17 18 export function MobileMenu({ items }: { items: ReadonlyArray<readonly [string, string]> }): JSX.Element {
18 19 const [open, setOpen] = useState(false);
@@ -65,8 +66,8 @@ export function MobileMenu({ items }: { items: ReadonlyArray<readonly [string, s
65 66 {/* Drawer sliding in from the right */}
66 67 <nav className="fixed right-0 top-0 z-50 flex h-dvh w-72 max-w-[85vw] animate-[drawer-in_180ms_ease-out] flex-col border-l border-[var(--border)] bg-[var(--surface-1)] shadow-2xl">
67 68 <div className="flex items-center justify-between border-b border-[var(--grid)] px-5 py-3.5">
68 <span className="flex items-center gap-2 font-semibold tracking-tight">
69 <span aria-hidden="true" className="h-2 w-2 rounded-full bg-[var(--seq)]" />
69 + <span className="flex items-center gap-2.5 font-semibold tracking-tight">
70 + <LogoMark size={20} />
70 71 AI Risk Index
71 72 </span>
72 73 <button
added apps/web/public/logo.svg +15 −0
@@ -0,0 +1,15 @@
1 +<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 360 64" role="img" aria-label="AI Risk Index">
2 + <!--
3 + AI Risk Index logo — mark (score bars + confidence whisker) + wordmark.
4 + Author: Simon-Pierre Boucher · contact@spboucher.ai
5 + Copyright © 2026 Simon-Pierre Boucher. All rights reserved.
6 + -->
7 + <rect width="64" height="64" rx="12" fill="#2a78d6"/>
8 + <rect x="13" y="14" width="38" height="9" rx="2" fill="#ffffff"/>
9 + <rect x="13" y="28" width="27" height="9" rx="2" fill="#ffffff" opacity="0.82"/>
10 + <rect x="13" y="42" width="16" height="9" rx="2" fill="#ffffff" opacity="0.62"/>
11 + <!-- confidence whisker on the top bar -->
12 + <line x1="45" y1="18.5" x2="56" y2="18.5" stroke="#cde2fb" stroke-width="2"/>
13 + <line x1="56" y1="14.5" x2="56" y2="22.5" stroke="#cde2fb" stroke-width="2"/>
14 + <text x="80" y="43" font-family="system-ui, -apple-system, 'Segoe UI', sans-serif" font-size="30" font-weight="700" letter-spacing="-0.5" fill="#0b0b0b">AI Risk Index</text>
15 +</svg>
16