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>
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 & 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 & 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 | ||||