| type | bundle-collection | |||||
|---|---|---|---|---|---|---|
| title | Civic Knowledge Sample | |||||
| description | Fifteen synthetic nonprofit organization bundles in the Open Knowledge Format, plus the x-civic civic profile they conform to. | |||||
| resource | https://github.com/TechSoup/okf-civic-sample | |||||
| tags |
|
|||||
| synthetic | true | |||||
| status | stable | |||||
| generated |
|
|||||
| x-civic |
|
Fifteen synthetic nonprofit organization bundles, a graph you can query, and a five-field profile extension for the civic sector.
Learn more about TechSoup · Support TechSoup
All fifteen organizations are invented. The names, registration numbers, addresses, websites, budget figures, staff, programs, technology inventories, verification determinations, and volunteer projects are made up. Nothing here describes a real nonprofit.
Every folder name and title carries a
synthetic-prefix. Every record carriessynthetic: truein its frontmatter — at the record level, not just here, because files get separated from their README.Do not load this collection into a production graph, count these organizations in any total, cite a figure from them, or let a script that writes to real systems read them without a
synthetic: truefilter.Two things here are not fabricated, and are marked
synthetic: false: the Candid PCS classification codes and the places. Those are real. The reasoning is in_shared/.
A reference implementation showing how a nonprofit organization can be described in Google's Open Knowledge Format — plain markdown with YAML frontmatter, no database, no platform, no lock-in — plus a proposed civic profile (x-civic) for the handful of things the sector needs that core OKF deliberately leaves open.
It is also a working Obsidian vault. Clone it, open the folder in Obsidian, and open graph view. The clusters, the cross-border coalition edges, and the unresolved emergent terms are all visible immediately.
Start with organizations/synthetic-frogtown-community-table/. It is the worked reference: the smallest organization in the set, the tidiest, and the one carrying the fullest explanation of why the frontmatter looks the way it does.
organizations/ the fifteen org bundles, one folder each — see its own README
_shared/ classification and place nodes the bundles link to
docs/ the civic profile, worked use cases, and the field-level data dictionary
schemas/ JSON Schema for the profile, plus fixtures that must fail
scripts/ validator, hub generator, PCS extractor, per-org JSON export, and schema-mapping (e.g. PDC)
examples/ generated schema-mapping output, one file per org (e.g. PDC) — see its own README
Everything that describes an organization is under organizations/, which carries its own README covering what the bundles are for, what is in one, and which three are deliberately broken.
civic/0.6 requires this much, on the one record with type: org:
x-civic:
profile: civic/0.6
subject: [SS030601, SS030600] # Candid PCS Subject — what it does
population: [PG010000, PG030000] # Candid PCS Population — who it serves
org_type: EA040000 # Candid PCS OrgType — what kind of organization
registration_country: US # ISO 3166-1 alpha-2That is the whole thing. Core OKF requires only type; the profile adds four bindings to controlled vocabularies and stops.
Everything else the bundles carry — programs, populations in prose, impact narratives, funding priorities in the organization's own voice, technology inventories, capability assessments, volunteer constraints and requests, partnership and coalition edges, budgets, SDG and NTEE codes, place nodes, third-party determinations — is optional enrichment. It makes a bundle far more useful and none of it affects conformance. See docs/civic-profile.md for the reasoning, docs/use-cases.md for what the optional layers buy you, and docs/data-dictionary.md for the field-by-field reference.
Required frontmatter edges are controlled. PCS Subject, PCS Population, OrgType, ISO country. They generate the hub pages in _shared/, and they are what make a bundle comparable to any other producer's bundle anywhere.
Prose wikilinks are emergent. An organization writing [[Karen]], [[Mixteco]], [[consejos comunitarios]], or [[Dholuo]] about the people it serves is authoring a term nobody pre-approved. OKF v0.2 §6.1 requires a consumer to tolerate a link whose target does not exist — "it may simply represent not-yet-written knowledge" — so an unresolved wikilink is not an error, it is a proto-hub. When enough bundles reach for the same term, the shape becomes visible in the graph and somebody can write the page.
This matters because PCS Population has exactly one code for LGBTQIA+ people, one for immigrants and migrants, one for farm workers. Those codes are correct, and they are the least interesting true thing about who any of these organizations serves.
The controlled vocabulary makes bundles comparable. The emergent one makes them true. A bundle needs both layers, and only one of them is required.
Run python3 scripts/validate.py --terms to see every emergent term in the collection and how many records reach for it.
All under organizations/. Three organizations in each of five program areas, scattered across geography on purpose so the program areas do not collapse into isolated islands. Sizes span roughly $430K to $7.9M and the equivalent in local currency abroad.
| Organization | Program area | Place | Rough size | State |
|---|---|---|---|---|
| Frogtown Community Table | Food security | Saint Paul, MN | $430K | worked reference |
| Eastside Harvest Collective | Food security | Detroit, MI | $1.4M | ⚠ budget unreconciled |
| Valle Verde Food Network | Food security | Fresno County, CA | $2.1M | clean |
| Riverbend Air Alliance | Environmental justice | Detroit, MI | $680K | clean |
| Gulf Corridor Justice Project | Environmental justice | New Orleans, LA | $1.5M | clean |
| Corporación Río Vivo | Environmental justice | Cali, Colombia | COP 1,900M | clean |
| Motor City Trades Institute | Workforce training | Detroit, MI | $3.2M | clean |
| Black Mountain Workforce Partnership | Workforce training | Letcher County, KY | $920K | clean |
| Crescent City Career Lab | Workforce training | New Orleans, LA | $1.7M | ⚠ determination lapsed |
| Central Valley Farmworker Law Center | Legal aid & immigration | Fresno County, CA | $1.8M | clean |
| North Star Immigrant Defense | Legal aid & immigration | Saint Paul, MN | $2.6M | clean |
| Fundacja Prawo i Schronienie | Legal aid & immigration | Warsaw, Poland | PLN 4.8M | clean |
| Sierra Foothills Community Health | Rural health | Fresno County, CA | $7.9M | clean |
| Cumberland Gap Health Cooperative | Rural health | Letcher County, KY | $1.1M | clean |
| Nyando Community Health Trust | Rural health | Kisumu County, Kenya | KES 62M | ⚠ evidence insufficient |
Three of the fifteen carry an unresolved problem, in three program areas, three countries, three different failure modes. If your tooling only ever sees the twelve clean ones, it is not tested.
- Eastside Harvest Collective — eligible, but its self-reported budget and its filed return disagree by 47% and nobody reconciled them. The bundle refuses to pick a number. Tests: does your code pick one, or notice there are two?
- Crescent City Career Lab — was approved, then the determination expired. Its
stale_afteris in the past. Tests: does your code check freshness, or assume a determination on file means yes? - Nyando Community Health Trust — organization-shaped but thinly sourced: no usable registry record, almost no web presence, and no
verifiedkey at all, which under OKF §5.3 is the unverified tier. Tests: can your logic say "I don't know" instead of "no"?
The third one is the important one. Core OKF makes "nobody has confirmed this" a first-class, non-rejectable state — §11 requires a consumer to accept it. That is not something this profile had to invent.
1. Required classification → PCS hub. Every organization links to _shared/pcs/ nodes through its required frontmatter. This is the edge a rollup walks, and the only layer that reaches all fifteen.
2. Place → situation node. Eight situation nodes hold community context, most hosting organizations from different program areas. Detroit has food security, environmental justice, and workforce training pointing at one place node. That is what makes "who else works here" answerable.
Read Letcher County for the strongest argument in the collection: two organizations in unrelated sectors, and the same community fact — broadband — defeated a program at each. One cause, two sectors, one address. Store connectivity as an organizational attribute and you record two independent weaknesses and miss that there is a single problem belonging to the county.
3. Organization → organization. Five same-place partnerships, drawn across program areas because that is how referral actually works — a food line is a legal-intake doorway, a farm crew is a trades pipeline.
4. Edges that ignore geography. A three-organization environmental-justice coalition spanning Detroit, New Orleans, and Cali; and a cross-border rural-health peer-learning pair, California and Kenya. Two clinics, wildly different stacks, same problem. The organization with the closest peers is the one whose peers are farthest away — see Detroit.
1. ein and 501(c)(3) do not generalize. Neither exists in Poland, Colombia, or Kenya. The required identity field is registration_country; the scheme and identifier are optional, because Nyando has no usable registry record and requiring an ID would make "insufficient evidence" unrepresentable.
2. PCS reaches everywhere; NTEE cannot. NTEE is an IRS vocabulary, so an NTEE rollup silently covers 80% of this collection — no error, no null, the three international organizations simply are not in the result set. PCS classifies activity and people rather than tax status. That is why PCS is the required layer and NTEE is optional. One honest caveat: PCS is not uniformly neutral — Candid's own scope note for EA040000 (Public charities) describes US 501(c) organizations, which is why the two non-US organizations without a matching legal form sit at the generic EA000000 and say so in org_type_note.
3. Money needs a currency, and conversion is somebody else's job. Every budget figure carries budget_currency. The international bundles state PLN, COP, and KES and do not convert, because a converted number is an exchange rate on an unstated date pretending to be a fact about an organization.
4. Verification confidence measures legibility, not competence. Frogtown Table scores 0.88 and runs the tidiest technology in the collection. Motor City Trades scores 0.96 at 7.5× the budget, with three participant systems that disagree and a CRM abandoned mid-implementation. Both numbers are correct and the ordering is the point. If you are building anything that ranks organizations on a confidence figure, that pair is your test case.
Two independent levels, and the second cannot affect the first:
- Core OKF v0.2: conformant. Every non-reserved
.mdhas parseable frontmatter and a non-emptytype;index.mdis a listing carrying at mostokf_version;log.mduses the §9 date-grouped shape. Provenance rides onsourceswith footnote attribution, trust ongenerated/verified, lifecycle onstatus/stale_after. - civic/0.6: conformant. Every record declaring
x-civic.profilesatisfies the profile, and everytype: orgrecord carries the five required keys with codes that resolve against the vendored PCS subset.
Nothing under x-civic can make a bundle non-conformant with core OKF — §11 requires consumers to tolerate unknown keys. That is the whole reason the extension is namespaced.
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
./venv/bin/python scripts/validate.py # both levels, plus hub freshness
./venv/bin/python scripts/validate.py --terms # the emergent vocabulary
./venv/bin/python scripts/build_hubs.py # regenerate every membership listFor per-organization JSON export and mapping a bundle's frontmatter onto another schema (a worked example targets Philanthropy Data Commons), see scripts/README.md.
Every <!-- GENERATED --> block in _shared/ is rebuilt from the organizations' own frontmatter by scripts/build_hubs.py, and validate.py fails if one is stale. Earlier versions of this collection maintained those lists by hand and documented the drift as a known problem; it is now a tool instead of a caveat.
As sample data. Build, test, break, and demo against it — a crosswalk script, a graph query, an eligibility rule, an agent that reads a bundle and drafts a volunteer request — without exposing a real organization's data to a prototype. Because it is synthetic you can paste it into any prompt, log, or transcript.
As agent input. Point a model at one bundle and ask what an organization would ask: scope a volunteer project, summarize what we run, tell me what's missing. Each bundle has enough structure to answer and enough gaps to be interesting. Note that a bundle's technical-volunteers/constraints.md is org-authored and binding — it carries generated.by: human:org-staff, and a tool that scopes work from a bundle must honor it.
As a fixture. Fifteen bundles, forty-odd shared nodes, three deliberate defects, stable file paths, a validator. Good enough to assert against.
As an Obsidian vault. Open the repo root as the vault so links resolve across bundle boundaries.
See docs/use-cases.md for worked examples with the queries written out.
Add a sixteenth by copying a bundle folder inside organizations/, renaming it synthetic-<something>, rewriting the contents, and assigning PCS codes. Then run scripts/build_hubs.py — the hub membership lists, the situation rosters, and the _shared/ indexes all rebuild themselves. If you use a PCS code the collection has not used before, run scripts/extract_pcs.py against Candid's published taxonomy first so its title and scope note get vendored.
If you add a real organization to this collection, you have broken the one guarantee it makes. Don't.
For human-services data the sector's established standard is Open Referral / HSDS (v3.0.1). This does not compete with it: HSDS is the structured data-exchange layer — normalized UUID-keyed objects, JSON Schema, an API — and OKF plus x-civic is the human- and AI-readable knowledge layer beside it. An organization bundle maps onto HSDS Organization; see the crosswalk in docs/civic-profile.md. What OKF adds is the verbose context a model needs to actually advise someone, human editability in Git, and the prose that has no HSDS equivalent. What HSDS does better is strict validation, relational integrity, and a mature exchange ecosystem.
Content licensed under CC BY-SA 4.0 — deliberately viral, so derivatives stay open and credit the source.
The Philanthropy Classification System is © Candid, used under CC BY 4.0, unmodified. Source: https://taxonomy.candid.org. See NOTICE.
This is a reference implementation and an open invitation — adopt the pattern, or argue with the profile. See CONTRIBUTING.md.
Developed with AI assistance: drafted and structured in collaboration with Anthropic's Claude, using Claude Code. The direction, data choices, profile design, and review were human (TechSoup). We name it in the spirit of showing the work.