Sun & Rain Works Engineer Portfolio · Est. 2005
Linked Art SaaS · cultural heritage data

Meta Museum

Source-backed museum data, gated to production by evidence.

A public-facing Linked Art web app that turns 14 museum collection APIs into source-backed exploration, rights-aware review, and governed publication. JSON-LD is canonical end to end, AI agents draft cited, rights-checked notes while humans approve before anything ships. Built on Next.js 16 and React 19, AIDD + TDD-driven, with a strict 10/10 readiness gate that stays closed until real-world reliability evidence matures. The product now splits in two: a plain-language public museum for visitors, and a professional workspace for researchers and partner organizations.

Live in production
Visit metamuseum.org Proprietary source
Next.js 16 React 19 TypeScript Linked Art Neon Postgres FastAPI Solr 9 GraphDB Anthropic Claude IIIF Stripe
The idea

A museum-data product with a trust model, not just a search UI

Collection records are only valuable when researchers can inspect provenance, rights, citations, and transformation history. Meta Museum bets on Linked Art JSON-LD as the canonical model, then exposes it through web pages, APIs, agent-assisted review, and governed publication paths.

Most aggregators flatten provider quirks into a lowest-common-denominator search box. Meta Museum keeps each source faithful: fourteen museums sit behind one gateway, each isolated in its own adapter, with raw payloads preserved and provenance carried on every record-touching path. Public pages and APIs share the same source-backed evidence instead of detached marketing copy, and every image surface shows rights, reuse status, and attribution, with unknown rights rendered as an explicit non-reuse warning.

14
museum collections
175
App Router API handlers
1,704
passing tests
89.4%
line coverage
216
routes in the production build
105
a11y route cases, 0 severe
Architecture

Layered Next.js product over an adapter boundary

A TypeScript App Router front of house, a faithful provider-integration layer, and Python services for validation and reconciliation, joined by a canonical Linked Art model that maps to UI shapes only at the boundary.

Web & API

Next.js 16 App Router

React 19 pages and 175 app/api route handlers serve public explore surfaces, records, docs, trust pages, and Linked Art endpoints, with Zod contracts as leaf modules and content negotiation for application/ld+json. The production build compiles 216 routes.

Integration

Per-provider adapters

Met, Getty, Rijksmuseum, NGA, RKD, Louvre, Harvard, Smithsonian, V&A, Princeton, Europeana, AIC, CMA, and Museums Victoria each get an isolated adapter behind a stable /api/providers/* facade, cross-provider logic lives in one artwork-builder boundary, and public counts derive from the capability registry rather than copied constants.

Canonical model

Linked Art JSON-LD

Event-centric CIDOC-CRM modeling (Object → Activity → Person), minted URIs with no blank nodes, multi-value properties kept as arrays, and immutable _source.raw payloads transformed only at read time.

Topology

Real production stack

Next.js on Vercel, managed documents in Neon Postgres (JSONB), Python FastAPI validation and reconciliation services on Render, and secured cron drains for background projection and publishing. Solr 9 and GraphDB provide the search and graph scale path.

Core components

Bounded surfaces, adapters, and review services

The product is a set of clearly-owned surfaces: integration boundaries, a canonical normalizer, a human-in-the-loop AI layer, and syndication.

Provider gateway

Fourteen governed collection adapters plus a MoMA snapshot adapter and a capability registry isolate upstream API differences behind one stable facade.

Linked Art normalizer

Keeps JSON-LD canonical, rights entities, identifiers, equivalent links, activities, and immutable source payloads preserved.

AI query & agents

Claude-backed query, chat, content generation, and review agents with cite-or-refuse gates. The paid path is auth-gated, so anonymous traffic falls back to local heuristics.

Rights-first UX

Every card and detail page surfaces source URL, attribution, and a reuse-status badge, and unknown rights flag "Rights, review".

ActivityStreams feed

An Activity Streams 2.0 change feed publishes ordered Create, Update, and Delete pages, harvested by two named clients. The project scores its own outside adoption at 0 of 3.

IIIF & reconciliation

OpenSeadragon deep zoom plus exhibition and literature reconciliation, with multi-tenant orgs and RBAC.

Public discovery

A plain-language visitor track: a provider-balanced homepage rotation, Surprise me, a UTC-dated Artwork of the Day, and public-first artwork pages.

Connections

Artwork-led chaptered journeys that walk source-backed steps to a bounded reveal, keeping fact and inference labels and rejected-claim boundaries visible.

Evidence ledger

A public ledger and an editor-gated readiness page compact partner proof, dataset proof, SLO progress, and open blockers into one reviewable surface.

Agent system

Agents draft, humans approve, nothing ships unreviewed

Janus reconciles across sources, Themis checks rights and provenance, Calliope drafts curatorial copy, Clio handles scoped research, and Mercator maps unfamiliar column shapes. Every one of them writes to a review queue with reviewer-facing diagnostics attached, and only a human promotes to production.

Animation of the MetaMuseum agent review pipeline in action
The Meta Museum agent pipeline: Janus reconciles, Themis validates rights, and Calliope drafts copy, each writing to a review queue rather than to the record itself.
Engineering

Standards-grade, tested first, secure by default

The hard part

I wrote the rule that disqualifies my own evidence

Two systems harvest this feed in production. The project scores its outside adoption at zero out of three, and that is not an oversight.

The partner quickstart spells out what counts as strict adoption evidence: a stable partner-owned consumer id, the organization behind it, a public callback URL, a contact who can confirm what they observed, and a real reference such as a ticket or a log export. Then it names what does not count, and the list ends with MetaMuseum-owned IDs.

That clause disqualifies my own work. Both live consumers of this feed are other systems in this portfolio, so under the project’s own rule they earn exactly nothing toward the adoption number. The ledger reads 0/3 while two integrations run every day, and it will keep reading zero until somebody I do not control subscribes.

The rule points outward too. In August 2026 I opened a pull request against the Linked Art specification itself, a one-line clarification adding Getty’s existing ulan1102_student_of predicate to the unmodeled-relationship example. The predicate and its inverse direction were checked against the Getty Vocabulary Program ontology, the shape was tested here against the canonical context, and the upstream documentation site was built clean in a fresh environment before anything was submitted. It was raised in the Linked Art meeting channel first.

It is open for community review and has not been accepted. The contribution packet in this repository says so in as many words: submission is implementation evidence, not acceptance or community consensus. That sentence was written before there was any reason to soften it, which is the only time such a sentence is worth anything.

Two of the specification questions this project already implements against are still open, and the contribution there is implementation experience rather than proposed wording. On negative reconciliation the point worth making is that an automated no-link result is not a confirmed negative, and a property writable by any reconciliation pipeline will fill with "not yet matched" instead. On bounded response profiles it is that a brief record carrying a link to the full one avoids the circularity of having to fetch everything in order to ask for less.

The same instinct runs through the commercial side. Paid-pilot proof rejects invoice references that look like demo, fixture, placeholder, sample, smoke, or test data before they can satisfy anything, and sandbox Stripe receipts are permanently excluded from revenue. Every one of these gates exists to stop one specific person from believing a number he generated himself.

It is easy to write a metric you can pass. The useful skill is writing the one you currently fail, and then leaving it on the page where a buyer can read it.

Outcome

Live, faithful, and honest about readiness

Meta Museum runs in production at metamuseum.org on Vercel, Neon, and Render. It showcases standards-grade Linked Art modeling, a fourteen-provider integration gateway, responsible AI with citation and rights gates, and evidence-driven release engineering. Every claim on the site is tied to a source or a passing check, including the claims the project makes about itself.