Design: Ingest Buckyverse Zotero collections into the wiki
Date: 2026-06-30
Source item: IMP-5 (work/IMPROVEMENTS.md) — "Ingest all items in Zotero collections for Buckyverse"
Status: Approved (brainstorming)
Goal
Pull every item in the Buckyverse Zotero group's curated collections into the
active llm-wiki ingest pipeline (.wiki/raw/**) as raw source records, so the
collection enters the knowledge base and can be compiled and queried. The job
must be idempotent — safe to re-run as the Zotero library grows.
Decisions (from brainstorming)
- End product: raw sources in
.wiki/raw/**(thewiki:ingestlayer), not a
flat catalog page and not per-item repo-root directories. - Source: the live local Zotero API (
http://localhost:23119/api), group
5189518("Buckyverse"). The local API is enabled and reachable. - Scope: the curated collections (not the ~1170-item raw group library):
- Bucky Shelf
L84AV9YL(301) - Books
BK23LBDC(165) → By BuckyYAAHI5VV(37) - Wish List
HLYVN3EP(17) - People
R5ID4MAH(42 — encyclopedia articles / webpages about people)
- Bucky Shelf
- Depth: metadata + attachment full text when present + live URL fetch.
Architecture
A single reusable Python script, zotero/ingest_to_wiki.py, run from the repo
root. Pure standard library where possible (urllib for the local API). It is the
only new moving part; it reads Zotero and writes .wiki/raw/**.
Pipeline stages (each independently testable):
- Fetch — for each target collection, GET
…/collections/<key>/items/top
(paginated,format=json,Zotero-API-Version: 3). Merge and dedupe by
item key. Record which collection(s) each item came from (for tagging
Wish List items). Write the merged set tozotero/buckyverse_collections.json
as a committed audit snapshot. - Classify — map each item's
itemTypeto a wiki raw type and target path
(table below). - Resolve dedup — decide create / enrich / skip against existing
.wiki/raw
records and repo-root book dirs. - Enrich (optional fetch) — pull attachment text and/or live URL content.
- Write — emit/patch the raw markdown record with frontmatter.
- Index + report — update
_index.mdfiles and print a summary.
A --dry-run flag runs stages 1–4 and reports planned actions without writing
any .wiki/raw files or the snapshot.
Type → raw mapping
Zotero itemType |
raw type |
path |
|---|---|---|
book, bookSection |
repos |
raw/repos/<slug>.md (by ref) |
journalArticle, report |
papers |
raw/papers/<slug>.md |
webpage, blogPost, newspaperArticle, magazineArticle, document, radioBroadcast, tvBroadcast |
articles |
raw/articles/<ingested>-<slug>.md |
encyclopediaArticle (incl. People collection) |
articles |
raw/articles/<ingested>-<slug>.md |
videoRecording, film |
notes |
raw/notes/<slug>.md |
Unknown/other types fall back to articles and are flagged in the report.
Frontmatter
Standard .wiki fields plus Zotero provenance:
---
title: "<item title>"
source: "<best URL: item url, else DOI link, else zotero://select/...>"
type: <repos|papers|articles|notes>
ingested: <YYYY-MM-DD>
tags: [<authorship-tag>, <zotero tags…>, <wish-list if applicable>]
summary: "<abstractNote, trimmed; else generated one-liner>"
zotero_key: <item key> # provenance + idempotency anchor
zotero_collections: [<names>] # which collections it came from
held: true|false # false for Wish List items
isbn: "<ISBN>" # books, when present
doi: "<DOI>" # papers, when present
fetch_status: ok|metadata-only|failed
---
authorship-tag follows the repo convention: buckminster-fuller (By Bucky
collection), else about-buckminster-fuller / fuller-adjacent by best guess
from creators/title (default about-buckminster-fuller).
Dedup & idempotency
Match an incoming item to an existing record in this order:
- By
zotero_keyfound in any existing.wiki/raw/**frontmatter. - By slug against existing
raw/repos/*.mdand repo-root book dirs
(normalized: lowercase, punctuation stripped, spaces→-).
- Match → enrich: add missing
zotero_key/isbn/doiand a
zotero_collectionsentry to the existing record. Never create a duplicate,
never overwrite hand-written body content. - No match → create the new record.
Re-running the whole script therefore creates zero new files on an unchanged
library (idempotency is the primary verification signal). Books that already
exist as repo-root sources are enriched in their raw/repos/<slug>.md pointer,
not re-ingested.
Full-text fetch
- Attachments: if
meta.numChildren > 0, GET…/items/<key>/children; for
attachments with a stored file, GET…/items/<childKey>/file. Extract text
from PDFs (best-effort) and snapshot HTML (readability/strip-tags). Append
under a## Full text (attachment)heading. - Live URL: if the item has a
url, fetch the page and extract readable text
under## Page content (<url>). Politeness: short timeout, single attempt,
skip obvious binaries. - Failure handling: any fetch failure is non-fatal — write the
metadata-only record withfetch_status: metadata-only(orfailed) and
continue. The run never aborts on a single item.
Books-without-local-copy (most By-Bucky/Books items not already a repo dir) get a
raw/repos/<slug>.md reference record with held reflecting ownership and a note
that no local file exists; they are not forced to fetch anything.
Indexes & report
- Update
.wiki/raw/_index.mdstatistics and per-category_index.mdcounts. - Add a dated line to
.wiki/raw/_index.md"Recent Changes". - Print and write a run summary (
zotero/last-ingest-report.md): totals for
created / enriched / skipped / fetch-failed, broken down by type, plus the
list of unknown item types encountered.
Error handling
- Local API unreachable / non-200 → stop early with a clear message (Zotero not
running or local API disabled). - Per-item errors are caught, logged to the report, and do not abort the run.
- The audit snapshot is written only after a successful fetch of all collections.
Verification
This is a content repo with no unit-test suite; verification is behavioral:
--dry-run— review planned create/enrich/skip counts for sanity.- Real run — generates records + snapshot + indexes.
- Idempotency: immediate second run reports 0 created (only re-confirms).
- Spot-check 3–5 generated records across types (a book, a People encyclopedia
article, a webpage with fetched content, a Wish List item). /wiki:lintpasses (no broken indexes/links introduced).
Out of scope
- Ingesting the full ~1170-item raw group library (only curated collections).
- Compiling
wiki/topics/*articles from these raw sources (separate step). - Modifying the legacy flat
zotero/index.mdbibliography. - Writing back to Zotero (read-only against the library).