Python 49.6%
TypeScript 25.5%
CSS 24.1%
1// Author: Simon-Pierre Boucher — contact@spboucher.ai2// ka-ui/react/KaFooter.tsx — shared Groupe KA footer (ink background),3// vendored in each Vite/React app under frontend/src/ka/. Consumes4// ecosystem.json for the site list; copy localized in US English for Home-Ka.5import eco from "./ecosystem.json";67type LocalLink = { label: string; href: string };89const TAGLINE_EN =10 "A holding of fully automated product and service aggregators.";11const DISCLAIMER_EN =12 "Groupe KA is a content aggregator: we sell nothing, rent nothing and are party to no transaction.";1314// English labels for the hub legal pages (hrefs unchanged)15const LEGAL_LABELS_EN: Record<string, string> = {16 "https://www.groupe-ka.com/conditions": "Terms of Use (Groupe KA)",17 "https://www.groupe-ka.com/confidentialite": "Privacy Policy (Groupe KA)",18 "https://www.groupe-ka.com/loi-25": "Personal information protection",19 "https://www.groupe-ka.com/bots": "Crawler transparency",20};2122export default function KaFooter({23 siteId,24 localLegal = [],25}: {26 /** id of the current site in ecosystem.json (e.g. "home-ka") */27 siteId: string;28 /** legal pages OWNED by the site (e.g. /terms), shown before the hub's */29 localLegal?: LocalLink[];30}) {31 const year = new Date().getFullYear();32 // graceful fallback if the siteId is not (yet) in ecosystem.json33 const site = eco.sites.find((s) => s.id === siteId) ?? null;34 const others = eco.sites.filter((s) => s.id !== siteId);35 return (36 <footer className="ka-footer" id="contact">37 <div className="container">38 <a39 className="wordmark"40 href={eco.hub.url}41 target={siteId === "groupe-ka" ? undefined : "_blank"}42 rel="noopener noreferrer"43 aria-label="Groupe KA — the ecosystem portal"44 >45 Groupe <span className="ka">KA</span>46 </a>47 <p className="desc">48 {TAGLINE_EN} Hundreds of connectors read the sites at the source,49 normalize the data and resynchronize on their own.{" "}50 {site ? (51 <>52 <b style={{ color: "var(--paper)" }}>{site.wordmark}</b> —{" "}53 {site.tagline} — is a Groupe KA service.54 </>55 ) : null}56 </p>57 <p className="notice">58 <b>{DISCLAIMER_EN}</b>59 </p>60 <ul className="sites">61 {others.map((s) => (62 <li key={s.id}>63 <a href={`https://${s.domain}`} target="_blank" rel="noopener noreferrer">64 {s.wordmark}65 </a>66 </li>67 ))}68 {eco.extraFooterLinks.map((l) => (69 <li key={l.href}>70 <a href={l.href} target="_blank" rel="noopener noreferrer">71 {l.label}72 </a>73 </li>74 ))}75 </ul>76 <div className="contacts">77 <p style={{ margin: 0 }}>78 <a href="mailto:contact@spboucher.ai">contact@spboucher.ai</a>79 <span>All Home-Ka inquiries — data, partnerships, legal & press</span>80 </p>81 </div>82 <p className="legal">83 © {year} {eco.org.copyrightHolder}84 {localLegal.map((l) => (85 <span key={l.href}>86 {" · "}87 <a href={l.href}>{l.label}</a>88 </span>89 ))}90 {eco.legal.map((l) => (91 <span key={l.href}>92 {" · "}93 <a href={l.href} target="_blank" rel="noopener noreferrer">94 {LEGAL_LABELS_EN[l.href] ?? l.label}95 </a>96 </span>97 ))}98 </p>99 </div>100 </footer>101 );102}103