DLF Core
Custom back-end code for the Dalai Lama Fellows WordPress site: fellow content model, editing UI, region auto-derivation, and archive REST endpoint. Companion to the dlf-child theme.
by UVA Contemplative Sciences Center · github.com/uva-csc/dlf-plugin · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/uva-csc/dlf-plugin/archive/refs/heads/main.zipReadme
DLF Core
All the custom back-end code for the Dalai Lama Fellows
WordPress site — the parts that aren't presentation. It defines the content
model (the fellow custom post type and its taxonomies), the editing experience
in wp-admin, the logic that keeps derived data correct, and a small read API the
front end uses. Everything visual lives in the companion theme,
dlf-child.
Together, dlf-child (theme) + dlf-plugin (this) are the only two custom
pieces the site needs on top of WordPress core.
What's in it
The plugin is one installable unit made of focused modules under includes/,
loaded by dlf-plugin.php (the model first, so the post type exists before the
code that hangs off it):
| Module | Responsibility |
|---|---|
model.php |
Registers the fellow custom post type and the fellowship_year, region, and country taxonomies, plus the structured post-meta fields (leadership_vision, project_description, learn_more). The data model is defined entirely in code so it's reproducible without a database export. |
acf-fields.php |
Registers the Leadership Vision / Project Description editing fields via ACF's PHP API (not the DB-stored field-group UI), rendered right under the title. ACF is used purely as an editing surface — the underlying post-meta keys are the source of truth. |
learn-more.php |
A small hand-rolled repeater metabox for the learn_more field (a list of {text, url} link pairs), with its own JS/CSS in assets/. |
region-derive.php |
Makes region a derived value: each country term carries a region (in term meta), and a fellow's regions are recomputed from its countries on every save. Includes the Country-screen region dropdown, the "hide the Regions box on the fellow screen" behavior, an admin notice for unmapped countries, and a one-time backfill. |
rest.php |
A single lean, flat, unpaginated endpoint — GET /wp-json/dlf/v1/fellows — that returns every published fellow for the client-side facet filter and card modal on the fellows archive. |
redirects.php |
301-redirects legacy URLs: /faq → /apply/#faq, and /dalai-lama-fellows → /fellows/ (the SquareSpace fellows-listing path). |
Requirements
- WordPress 6.0+ and PHP 8.0+.
- Advanced Custom Fields (free) — provides the editing UI for Leadership Vision / Project Description. Only the free tier is used; there is no ACF PRO dependency (that's why
learn_moreis a hand-rolled repeater rather than an ACF Repeater field). - Radio Buttons for Taxonomies — turns
fellowship_yearinto a single-select radio UI (a fellow belongs to exactly one cohort year). The plugin configures this automatically once the helper is active.
These two are ordinary WordPress plugins — install them from the plugin directory. They are intentionally not bundled here.
Install / update
The plugin is self-contained (all its own PHP/JS/CSS); there is no build step.
Install — clone (or upload a ZIP) into wp-content/plugins/, then activate:
cd wp-content/plugins
git clone https://github.com/uva-csc/dlf-plugin.git
wp plugin activate dlf-plugin # or activate it from Plugins in wp-admin
Update — pull the latest:
cd wp-content/plugins/dlf-plugin
git pull
(If the server runs OPcache and a change doesn't appear, flush OPcache / restart PHP. New files are always picked up; changed files can lag.)
Pin to a release (recommended for production). Tracking main gives you the
latest commit; to pin production to a tagged release instead, check out the tag:
cd wp-content/plugins/dlf-plugin
git fetch --tags
git checkout v1.0.0 # a specific release; `git checkout main` returns to latest
Releases are listed at https://github.com/uva-csc/dlf-plugin/releases. To move to
a newer release later, git fetch --tags && git checkout vX.Y.Z.
Note — no Deactivate link. Because this plugin registers the site's content model, deactivating it would hide every fellow from wp-admin (the data stays safe in the database, but the post type and its screens disappear). It's meant to be always-on, like the theme, so the "Deactivate" action is removed from the Plugins list on purpose. To genuinely remove it, delete the folder.
Note — region backfill. On the first wp-admin page load after installing on a
site that has fellow data, region-derive.php runs a one-time backfill that
assigns each existing Country term its region (from a seed map), then guards
itself so it never runs again. It only writes country term meta — existing
fellows are left untouched and re-derive their regions the next time each is
saved.
How editors use it
- Fellows are edited on a stripped-down screen: title, then Leadership Vision and Project Description, then Learn More links, then the cohort year and countries in the sidebar. There is deliberately no body editor — a fellow's public profile is built from the structured fields, not free-form post content.
- Region is never edited by hand. Editors pick a fellow's countries; the region(s) follow automatically. Which region a country belongs to is set once, per country, on Fellows → Countries (a Region dropdown on the Add/Edit Country screen). The dropdown lists whatever Region terms exist, so an administrator can add or rename regions natively under Fellows → Regions and they appear immediately — no code change required.
Development history — the salient points
This code grew out of the 2026 migration of dalailamafellows.com from Squarespace to self-hosted WordPress. A few decisions shaped what it is:
- Code-first data model. The
fellowpost type, its taxonomies, and its meta fields are all registered in PHP rather than clicked together in a plugin UI, so the whole structure is reproducible from source and lives in version control. The same meta keys are shared by the import pipeline that generated the initial content (WXR) and by this plugin's REST endpoint. - No paid plugins. The site avoids recurring plugin licenses. Where a paid
feature would normally be reached for, a small purpose-built alternative was
written instead:
learn_moreis a hand-rolled repeater (not ACF PRO's Repeater), and the archive filter is a custom REST endpoint + vanilla JS in the theme (not FacetWP/JetEngine). With ~250 fellows and three facets, fetching the dataset once and filtering client-side is faster and simpler than a generic faceting widget, and carries no license. regionas a derived field. Region began as a single Squarespace tag, but fellows can span multiple countries across multiple regions, so region became multi-value. Originally the country→region mapping lived in the import script as a hardcoded table. It was later moved into the database — a region stored per Country term, editable by administrators — and a fellow's regions are now computed as the union of its countries' regions on save. This removed a hand-managed field from the editing workflow and made the mapping self-service.- The fellow body was removed. The post body only ever held the raw imported HTML that the structured fields were parsed from, so it was a dead surface for editors and was dropped from the post type (existing body content remains in the database, untouched).
- From mu-plugins to one plugin. These modules started life as separate
must-use plugins during the migration. In July 2026 they were consolidated into
this single, versioned, installable plugin with its own repository — so the
deployable site is just core +
dlf-childtheme +dlf-plugin, each installed or updated the same way, instead of a loose pile of files that had to travel inside a database/file backup.
License
GPL-2.0-or-later. See LICENSE.
Read the full README on GitHub →
Releases
| Tag | Published |
|---|---|
| v1.0.0 | Jul 30, 2026 |
These releases are tags only. The author does not attach a packaged zip, so there are no download counts to report.