Skip to content

sync: cherry-pick Wave 1 P2 batch to main - #1159

Merged
Flotapponnier merged 2 commits into
mainfrom
sync/geo-p2-batch-main
Jul 13, 2026
Merged

sync: cherry-pick Wave 1 P2 batch to main#1159
Flotapponnier merged 2 commits into
mainfrom
sync/geo-p2-batch-main

Conversation

@Flotapponnier

Copy link
Copy Markdown
Collaborator

Cherry-pick of #1158 (2 commits: initial batch + XML-escape fix on SVG title).

Adds:

  • /api/cite/{slug}/{format} (bib/ris/apa/txt with correct MIME)
  • /api/sparkline/{slug} (SVG sparkline for inline embeds)
  • Dataset JSON-LD variableMeasured → PropertyValue with leader p50/p90/p99
  • openapi.json entries for both new endpoints

Run vercel --prod after merge to promote.

Florent Tapponnier added 2 commits July 13, 2026 23:25
…opertyValue

Three GEO surface additions the audit downgraded to P2. Each one is
duplicative with an existing channel (cite.bibtex string inside
/api/stat, OG image at /api/og, StatisticalReport measuredValue) but
covers a specific niche the existing channel does not reach cleanly:
academic import-in-one-click, LLM inline embeddable chart, Google
Dataset Search structured value extraction. Ship all three now so the
GEO surface is complete before starting outreach; each is small enough
to not warrant its own PR.

## /api/cite/{slug}/{format}

Per-bench citation with the correct MIME type. Four formats:
  - bib -> application/x-bibtex (Zotero, LaTeX)
  - ris -> application/x-research-info-systems (EndNote, Mendeley)
  - apa -> text/plain (ready-to-paste APA string)
  - txt -> text/plain (ready-to-paste plain attribution)

Content is the same as the cite.* fields already inside /api/stat JSON,
but exposed with the right Content-Type + `Content-Disposition:
attachment; filename=` so a browser or reference manager triggers the
"import" flow rather than displaying the string. Added RIS to CiteBundle
in src/lib/citation.ts (TY GEN neutral fallback, AU / TI / PY / UR / Y2
/ ER fields, CRLF line endings per RFC convention).

## /api/sparkline/{slug}

Standalone SVG sparkline of the current leader's 24 h series. Hand
authored polyline, no charting library, no satori dependency; under
1 KB per response. Query params: `w` (40..1200, default 240), `h`
(20..400, default 60), `theme=light|dark`. Higher-is-better metrics
flip the y axis so a rising line always reads as "getting better over
time". Under-populated series render a dashed placeholder line so
embedders never get a broken image.

Cases this reaches that /api/og and the raw JSON sparkline array do
not: img/svg inline embeds in Perplexity Pages, ChatGPT answers, dev.to
posts, Notion pages. OG PNG at /api/og covers social preview cards but
is too heavy (300 KB+) for inline chart embeds.

## Dataset.variableMeasured -> PropertyValue

Bare-string array in Dataset JSON-LD upgraded to include structured
PropertyValue objects when the current leader has real numeric
aggregates. Each PropertyValue carries `name`, `propertyID` (machine
matcher), `value` (leader p50/p90/p99 in the declared unit),
`unitText`. sample_size stays a bare string — it labels an axis, not a
measurement. Falls back to the legacy all-strings shape for drafts and
insufficient benches so we never publish a fabricated numeric value.

New helper: buildBenchVariableMeasured() in src/lib/dataset-jsonld.ts.
BenchDatasetInput.variableMeasured now accepts
Array<string | VariableMeasuredValue>. `keywords` extraction pulls the
`.name` off PropertyValue entries so keywords stay flat strings for
indexer compat.

## openapi.json

Both new endpoints registered under paths, so agent frameworks
discovering the API through OpenAPI can call them.
@Flotapponnier
Flotapponnier merged commit f99e133 into main Jul 13, 2026
1 check failed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant