diff --git a/next.config.ts b/next.config.ts index b8a5e70..2791a13 100644 --- a/next.config.ts +++ b/next.config.ts @@ -53,6 +53,14 @@ const nextConfig: NextConfig = { destination: '/insights/:path*', permanent: true, }, + // The impact dashboard shipped first as an unlisted, non-indexed preview + // at a cryptic slug (#98). It's now a public, discoverable /impact page, + // so send anyone holding the old preview link to the live route. + { + source: '/impact-preview-eb61fba1b98e/', + destination: '/impact/', + permanent: true, + }, ] }, } diff --git a/src/app/impact-preview-eb61fba1b98e/page.tsx b/src/app/impact-preview-eb61fba1b98e/page.tsx deleted file mode 100644 index e2cb684..0000000 --- a/src/app/impact-preview-eb61fba1b98e/page.tsx +++ /dev/null @@ -1,148 +0,0 @@ -import type { Metadata } from 'next' -import Breadcrumb from '@/components/Breadcrumb' -import ImpactDashboardV2, { type LiveMetric, type LiveOutputs } from '@/components/ImpactDashboardV2' -import MeasuringQuestionsV2 from '@/components/MeasuringQuestionsV2' -import { fetchSimocracyStats } from '@/lib/simocracy' -import { fetchGainforestStats } from '@/lib/gainforest' -import { fetchGlowStats } from '@/lib/glow' -import { resolveAllSignals } from '@/lib/market-signals' -import { FOCUS_AREAS, type FocusAreaKey } from '@/lib/inflection-points' -import { instrumentsForArea, withOpenAlex, type InstrumentRecord } from '@/lib/velocity-instruments' -import { loadAllOpenAlex } from '@/lib/velocity-openalex' - -// The impact page reads field velocity: the interventions we run, the five -// instruments we read a field's rate of change with, and the inflection points -// we track, each with its live signal. -export const revalidate = 60 - -async function fetchLiveOutputs(): Promise { - const compact = (n: number) => - new Intl.NumberFormat('en-US', { notation: 'compact', maximumFractionDigits: 1 }).format(n) - const out: LiveOutputs = {} - - const [sim, gf, glow] = await Promise.allSettled([ - fetchSimocracyStats(), - fetchGainforestStats(), - fetchGlowStats(), - ]) - - // A binding decision at scale — Simocracy (a PL-supported deliberation mechanism). - if (sim.status === 'fulfilled' && !sim.value.degraded) { - const t = sim.value.totals - const metrics: LiveMetric[] = [ - { n: t.uniqueHumans, label: 'participants' }, - { n: t.totalSims, label: 'simulations' }, - { n: t.totalGatherings, label: 'gatherings' }, - ] - .filter((m) => m.n > 0) - .map((m) => ({ value: compact(m.n), label: m.label })) - if (metrics.length) out['A binding decision at scale'] = metrics - } - - // Capital that pays on verified outcomes — GainForest + Glow (PL-backed MRV teams). - const verified: LiveMetric[] = [] - if (gf.status === 'fulfilled' && !gf.value.degraded) { - const g = gf.value - if (g.observations > 0) verified.push({ value: compact(g.observations), label: 'species observations' }) - if (g.certifiedOrgs > 0) verified.push({ value: compact(g.certifiedOrgs), label: 'certified orgs' }) - } - if (glow.status === 'fulfilled' && !glow.value.degraded) { - const gl = glow.value - if (gl.activeFarms > 0) verified.push({ value: compact(gl.activeFarms), label: 'active solar farms' }) - if (gl.carbon > 0) verified.push({ value: compact(gl.carbon), label: 'tCO₂ / wk' }) - } - if (verified.length) out['Capital that pays on verified outcomes'] = verified - - return out -} - -export const metadata: Metadata = { - title: 'Impact', - description: - 'How we judge PL R&D: whether the fields we back are speeding up. We name the interventions we run, then read field velocity through five instruments and the inflection points we track.', - // Unlisted preview: reachable only via the exact cryptic URL. Keep it out of - // search indexes and previews. (Not in nav, not in sitemap.xml, and - // deliberately not listed in robots.txt so the path isn't published there.) - robots: { index: false, follow: false, googleBot: { index: false, follow: false } }, -} - -export default async function ImpactPage() { - const [liveOutputs, marketSignals] = await Promise.all([fetchLiveOutputs(), resolveAllSignals()]) - - // Merge any OpenAlex CSV readings (idea vintage + talent entry) into the static - // instrument records, per focus area. Parsed at build time; absent CSVs are a - // no-op, leaving the documented `unwired` records in place. - const openAlex = loadAllOpenAlex() - const recordsByArea = Object.fromEntries( - FOCUS_AREAS.map((fa) => [fa.key, withOpenAlex(instrumentsForArea(fa.key), openAlex[fa.key])]), - ) as Partial> - - // Example idea-vintage series per field, for the methodology modal that explains - // the instrument (shown as small multiples). - const ideaVintageExamples = FOCUS_AREAS.map((fa) => { - const rec = (recordsByArea[fa.key] ?? []).find( - (r) => r.instrument === 'idea_vintage' && r.state === 'reading' && r.series && r.series.length > 1, - ) - return rec ? { label: fa.label, series: rec.series!, scale: rec.seriesScale ?? 'linear' } : null - }).filter((x): x is { label: string; series: NonNullable; scale: 'linear' | 'log' } => !!x) - return ( -
- {/* Hero */} -
- -
-

- PL R&D’s impact on field velocity -

-

- We back fields we think are ready to move, then check whether they do.{' '} - Field velocity is that rate of change: - how fast talent enters, capital forms, tool costs fall, and output ships.{' '} - Inflection points are one of the markers - we read — dated, falsifiable shifts an accelerating field should produce. -

-

- We measure velocity the same way we do the work: as a research program. Whether field - acceleration works is itself the open question, tested across all four focus areas. -

- - Learn more about our methodology - - - - -
-
- - {/* Field velocity — grey full-bleed section to set it apart from the rest of the site */} -
-
-

Field velocity

-

- Pick a focus area. The summary above reads that field’s velocity across the instruments - that apply to it; the inflection points below are the specific markers we track, each with its - live signal. -

- -
-
- - {/* Methodology */} -
-

Our methodology

-

- The method is the meta-research design of how we do field acceleration. We name the - interventions we run, then read field velocity as the result. Same design, every focus area. -

- -
-
- ) -} diff --git a/src/app/sitemap.ts b/src/app/sitemap.ts index 3c97a3b..a127031 100644 --- a/src/app/sitemap.ts +++ b/src/app/sitemap.ts @@ -29,6 +29,7 @@ export default function sitemap(): MetadataRoute.Sitemap { { url: url(''), changeFrequency: 'weekly', priority: 1 }, { url: url('about'), changeFrequency: 'monthly', priority: 0.7 }, { url: url('areas'), changeFrequency: 'monthly', priority: 0.8 }, + { url: url('impact'), changeFrequency: 'weekly', priority: 0.8 }, { url: url('insights'), changeFrequency: 'weekly', priority: 0.8 }, { url: url('authors'), changeFrequency: 'weekly', priority: 0.7 }, { url: url('publications'), changeFrequency: 'weekly', priority: 0.8 },