SPB Git

spb/cancerindex

Public

Site identity: author Simon-Pierre Boucher, contact@spboucher.ai, hosted on MacLustr (www.maclustr.io) in footer, About, methodology, metadata and OpenAPI contact

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Sep 11, 2026) parent 15088d0 Browse files

6 changed files +40 −7

modified apps/api/src/app.ts +1 −1
@@ -94,7 +94,7 @@ export async function buildApp(opts: BuildOptions = {}): Promise<FastifyInstance
94 version: '1.0.0', 94 version: '1.0.0',
95 description: 95 description:
96 'Public read-only API of CancerIndex.io — the global index of cancer. Every response is wrapped in `{ data, sources, dataRelease, generatedAt }`; `sources` lists the upstream sources (with license and attribution) behind the returned data. Numbers are never invented: absent data is absent, not zero. Rankings carry scope, formula version and inputs hash. Not medical advice.', 96 'Public read-only API of CancerIndex.io — the global index of cancer. Every response is wrapped in `{ data, sources, dataRelease, generatedAt }`; `sources` lists the upstream sources (with license and attribution) behind the returned data. Numbers are never invented: absent data is absent, not zero. Rankings carry scope, formula version and inputs hash. Not medical advice.',
97− contact: { name: 'CancerIndex', url: 'https://www.cancerindex.io' }, 97+ contact: { name: 'Simon-Pierre Boucher — CancerIndex', url: 'https://www.cancerindex.io/about', email: 'contact@spboucher.ai' },
98 license: { name: 'Data licensed per source; see /v1/sources' }, 98 license: { name: 'Data licensed per source; see /v1/sources' },
99 }, 99 },
100 servers: [{ url: '/', description: 'This host' }], 100 servers: [{ url: '/', description: 'This host' }],
modified apps/web/src/app/about/page.tsx +17 −0
@@ -1,5 +1,6 @@
1 import type { Metadata } from 'next'; 1 import type { Metadata } from 'next';
2 import Link from 'next/link'; 2 import Link from 'next/link';
3+import { CONTACT_EMAIL, AUTHOR_NAME, AUTHOR_URL, HOSTING_NAME, HOSTING_URL } from '@/lib/site';
3 import { PageHeader, Section } from '@/components/ui/section'; 4 import { PageHeader, Section } from '@/components/ui/section';
4 5
5 export const metadata: Metadata = { title: 'About', description: 'What CancerIndex is, who it is for, and what it refuses to do.' }; 6 export const metadata: Metadata = { title: 'About', description: 'What CancerIndex is, who it is for, and what it refuses to do.' };
@@ -23,6 +24,22 @@ export default function AboutPage() {
23 <li>No AI-generated synthesis in this phase; all text is sourced or fixed methodology.</li> 24 <li>No AI-generated synthesis in this phase; all text is sourced or fixed methodology.</li>
24 </ul> 25 </ul>
25 </Section> 26 </Section>
27+ <Section id="team" kicker="Who" title="Who builds and hosts it">
28+ <p>
29+ CancerIndex is designed, built and maintained by{' '}
30+ <a className="ci-link" href={AUTHOR_URL} rel="author">
31+ {AUTHOR_NAME}
32+ </a>
33+ . Questions, corrections, licensing concerns and collaboration requests: <a className="ci-link" href={`mailto:${CONTACT_EMAIL}`}>{CONTACT_EMAIL}</a>.
34+ </p>
35+ <p className="mt-2">
36+ The platform — database, ingestion workers, API and web application — is hosted on{' '}
37+ <a className="ci-link" href={HOSTING_URL} target="_blank" rel="noopener noreferrer">
38+ {HOSTING_NAME}
39+ </a>{' '}
40+ (www.maclustr.io), a private Apple-silicon compute cluster, and published through the MacLustr Tunnel.
41+ </p>
42+ </Section>
26 <Section id="status" kicker="Status" title="Phase 1"> 43 <Section id="status" kicker="Status" title="Phase 1">
27 <p> 44 <p>
28 The taxonomy backbone is live; epidemiology, genomics, trial and literature connectors are being brought online one at a time, each after a license review. Follow progress on the <Link className="ci-link" href="/sources">source registry</Link> and read the <Link className="ci-link" href="/methodology">methodology</Link>. 45 The taxonomy backbone is live; epidemiology, genomics, trial and literature connectors are being brought online one at a time, each after a license review. Follow progress on the <Link className="ci-link" href="/sources">source registry</Link> and read the <Link className="ci-link" href="/methodology">methodology</Link>.
modified apps/web/src/app/layout.tsx +3 −1
@@ -3,7 +3,7 @@ import { Newsreader, Inter, IBM_Plex_Mono } from 'next/font/google';
3 import './globals.css'; 3 import './globals.css';
4 import { SiteHeader } from '@/components/layout/site-header'; 4 import { SiteHeader } from '@/components/layout/site-header';
5 import { SiteFooter } from '@/components/layout/site-footer'; 5 import { SiteFooter } from '@/components/layout/site-footer';
6−import { SITE_URL, SITE_NAME, TAGLINE } from '@/lib/site'; 6+import { SITE_URL, SITE_NAME, TAGLINE, AUTHOR_NAME, AUTHOR_URL } from '@/lib/site';
7 7
8 const display = Newsreader({ variable: '--font-display', subsets: ['latin'], display: 'swap', weight: ['400', '500', '600'], style: ['normal', 'italic'] }); 8 const display = Newsreader({ variable: '--font-display', subsets: ['latin'], display: 'swap', weight: ['400', '500', '600'], style: ['normal', 'italic'] });
9 const ui = Inter({ variable: '--font-ui', subsets: ['latin'], display: 'swap' }); 9 const ui = Inter({ variable: '--font-ui', subsets: ['latin'], display: 'swap' });
@@ -14,6 +14,8 @@ export const metadata: Metadata = {
14 title: { default: `${SITE_NAME} — ${TAGLINE}`, template: `%s · ${SITE_NAME}` }, 14 title: { default: `${SITE_NAME} — ${TAGLINE}`, template: `%s · ${SITE_NAME}` },
15 description: 'A provenance-first index of every recognized cancer entity: taxonomy, epidemiology, genomics, variants, therapies, clinical trials, literature and transparent rankings.', 15 description: 'A provenance-first index of every recognized cancer entity: taxonomy, epidemiology, genomics, variants, therapies, clinical trials, literature and transparent rankings.',
16 applicationName: SITE_NAME, 16 applicationName: SITE_NAME,
17+ authors: [{ name: AUTHOR_NAME, url: AUTHOR_URL }],
18+ creator: AUTHOR_NAME,
17 robots: { index: true, follow: true }, 19 robots: { index: true, follow: true },
18 openGraph: { type: 'website', siteName: SITE_NAME, url: SITE_URL, title: `${SITE_NAME} — ${TAGLINE}`, description: 'Provenance-first oncology intelligence: every number linked to its source.' }, 20 openGraph: { type: 'website', siteName: SITE_NAME, url: SITE_URL, title: `${SITE_NAME} — ${TAGLINE}`, description: 'Provenance-first oncology intelligence: every number linked to its source.' },
19 twitter: { card: 'summary', title: SITE_NAME, description: TAGLINE }, 21 twitter: { card: 'summary', title: SITE_NAME, description: TAGLINE },
modified apps/web/src/app/methodology/page.tsx +1 −1
@@ -297,7 +297,7 @@ export default async function MethodologyPage() {
297 <li>Approval records reflect the jurisdictions ingested; absence of an approval on this site is not evidence of absence.</li> 297 <li>Approval records reflect the jurisdictions ingested; absence of an approval on this site is not evidence of absence.</li>
298 </ul> 298 </ul>
299 <p className="mt-3 text-[13px] text-ink-3"> 299 <p className="mt-3 text-[13px] text-ink-3">
300− Corrections: <a className="ci-link" href="mailto:corrections@cancerindex.io">corrections@cancerindex.io</a>. See also <Link className="ci-link" href="/trust">Trust &amp; policies</Link>. 300+ Corrections: <a className="ci-link" href="mailto:contact@spboucher.ai">contact@spboucher.ai</a>. See also <Link className="ci-link" href="/trust">Trust &amp; policies</Link>.
301 </p> 301 </p>
302 </Section> 302 </Section>
303 </div> 303 </div>
modified apps/web/src/components/layout/site-footer.tsx +13 −3
@@ -1,5 +1,5 @@
1 import Link from 'next/link'; 1 import Link from 'next/link';
2−import { DISCLAIMER, FOOTER_NAV, CONTACT_EMAIL } from '@/lib/site'; 2+import { DISCLAIMER, FOOTER_NAV, CONTACT_EMAIL, AUTHOR_NAME, AUTHOR_URL, HOSTING_NAME, HOSTING_URL } from '@/lib/site';
3 3
4 export function SiteFooter() { 4 export function SiteFooter() {
5 return ( 5 return (
@@ -20,14 +20,24 @@ export function SiteFooter() {
20 </Link> 20 </Link>
21 ))} 21 ))}
22 <a href={`mailto:${CONTACT_EMAIL}`} className="text-ink-2 no-underline hover:text-accent"> 22 <a href={`mailto:${CONTACT_EMAIL}`} className="text-ink-2 no-underline hover:text-accent">
23− Report a correction 23+ Contact · {CONTACT_EMAIL}
24 </a> 24 </a>
25 <Link href="/healthz" className="text-ink-2 no-underline hover:text-accent"> 25 <Link href="/healthz" className="text-ink-2 no-underline hover:text-accent">
26 Status 26 Status
27 </Link> 27 </Link>
28 </nav> 28 </nav>
29 </div> 29 </div>
30− <p className="mt-6 text-[11.5px] text-ink-3">© {new Date().getUTCFullYear()} CancerIndex. Source data remains under the license of each provider — see /sources.</p> 30+ <p className="mt-6 text-[11.5px] text-ink-3">
31+ © {new Date().getUTCFullYear()} CancerIndex · built and maintained by{' '}
32+ <a href={AUTHOR_URL} className="text-ink-2 no-underline hover:text-accent" rel="author">
33+ {AUTHOR_NAME}
34+ </a>{' '}
35+ · contact <a href={`mailto:${CONTACT_EMAIL}`} className="text-ink-2 no-underline hover:text-accent">{CONTACT_EMAIL}</a> · hosted on{' '}
36+ <a href={HOSTING_URL} className="text-ink-2 no-underline hover:text-accent" target="_blank" rel="noopener noreferrer">
37+ {HOSTING_NAME}
38+ </a>{' '}
39+ (www.maclustr.io). Source data remains under the license of each provider — see /sources.
40+ </p>
31 </div> 41 </div>
32 </footer> 42 </footer>
33 ); 43 );
modified apps/web/src/lib/site.ts +5 −1
@@ -3,7 +3,11 @@ export const SITE_NAME = 'CancerIndex';
3 export const TAGLINE = 'The global index of cancer.'; 3 export const TAGLINE = 'The global index of cancer.';
4 export const DISCLAIMER = 4 export const DISCLAIMER =
5 'CancerIndex is a research and information platform. It is not a physician, does not diagnose, and does not recommend treatment. Population statistics do not predict individual outcomes.'; 5 'CancerIndex is a research and information platform. It is not a physician, does not diagnose, and does not recommend treatment. Population statistics do not predict individual outcomes.';
6−export const CONTACT_EMAIL = 'corrections@cancerindex.io'; 6+export const CONTACT_EMAIL = 'contact@spboucher.ai';
7+export const AUTHOR_NAME = 'Simon-Pierre Boucher';
8+export const AUTHOR_URL = 'https://www.spboucher.ai';
9+export const HOSTING_NAME = 'MacLustr';
10+export const HOSTING_URL = 'https://www.maclustr.io';
7 11
8 export const NAV = [ 12 export const NAV = [
9 { href: '/cancers', label: 'Cancers' }, 13 { href: '/cancers', label: 'Cancers' },
10 14
Menu

Theme