Skip to content

Footnotes modularization & fragments migration

Last updated on June 8, 2026

This week brought major structural improvements to the footnotes system, excerpt automation for SEO, infrastructure cleanup, the launch of a new Fragment CPT, and template updates across the site.

Footnotes system refactor (inc/footnotes)

Modularization: Broke down the original monolithic inc/footnotes.php into individual modules (quotes.php, lyrics.php, excerpts.php, concepts.php, organizations.php, references.php, images.php, themes.php, videos.php, etc.). Each CPT/section now has its own function (fn_quotes, fn_excerpts, etc.) and is required dynamically via glob().

Consistency improvements: Unified layout structure (referenced‑group wrapper, consistent <ul><li> styling, thumbnails left + text right). Each group pulls its label (title, emoji, link) from a central $group_titles array. Standardized use of wp_trim_words() for excerpts and lyrics. Clean handling of artist/song logic (primary vs. secondary, featured vs. referenced).

Thumbnail handling: Quotes and excerpts now correctly pull images from their source CPTs (books, movies, references). Added fallback to source CPT’s featured image if no custom cover_image is present (fix for references). Profiles, lyrics, concepts, etc., each have tailored thumbnail rules.

Video handling: Moved video logic into its own section, simplified output. Primary + secondary featured songs display screenshots if available, with toggle for hiding secondary.

Efficiency tradeoff → modularity: Accepted some redundancy in favor of modularity. Functions are now easier to swap, debug, or extend without breaking unrelated CPTs.

Status: Almost all sections are stable and visually consistent. Only excerpts.php needed a last‑minute tweak for image fallbacks. Alignment and source display are now fixed.

Excerpt automation across CPTs

Built multiple WP‑CLI scripts to populate Yoast excerpts from custom fields. Scripts trim content (~157 chars) and add “…” for proper snippet length. Versions created for:

  • Quotes → quote_plain_text
  • Excerpts → excerpt_plain_text
  • Lyrics → lyric_plain_text
  • Concepts → definition

Each CPT now has a forceful version (always overwrite excerpt) and a conditional version (only set if excerpt is empty).

Featured image alignment with Yoast

Planned a script to copy ACF portrait_image (or other CPT‑specific image fields) into _thumbnail_id. This ensures Yoast picks up the correct image (og:image + twitter:image) instead of unrelated generic placeholders.

SEO behavior observations

  • Confirmed that generic placeholder images are often ignored by Google in search previews.
  • Verified Yoast is correctly outputting og:image once _thumbnail_id is updated.
  • Determined Google reindexing delay is normal — images may take weeks to start showing in results.

Net result: Excerpts standardized across all CPTs for Yoast. Image metadata alignment in progress via ACF → featured image sync. SEO previews improved by removing generics and ensuring snippets/images are populated consistently.

PHP upgrade & VPS cleanup

PHP upgrade & cleanup: Verified server had PHP 8.2, 8.3, and 8.4 installed. Removed unnecessary Apache‑related PHP modules. Set PHP 8.3‑FPM as the active version for Nginx. Ensured old 8.2 services were disabled to avoid conflicts. Rebooted VPS and confirmed Nginx + PHP‑FPM working correctly.

Nginx configuration: Cleaned up duplicate location blocks. Updated PHP handler to consistently use PHP 8.3‑FPM sockets. Verified server blocks for dev, www, and redirects were consistent. Resolved a temporary 502 Bad Gateway issue caused by PHP‑FPM service not running.

WordPress monitoring: Noted a temporary action_scheduler_run_queue late warning after reboot — expected after restart, not a persistent problem.

Disk usage prep for VPS migration: Began cleaning space in preparation for copying the VPS disk. Identified large files and databases using du (e.g., wp_mailpoet_log.ibd). Planned to use pigz for parallel compression during backup/migration.

Profile CPT updates (quotes & excerpts)

Added Quotes and Excerpts sections to the Profile CPT template. Fixed an issue where they didn’t appear because quote_source/excerpt_source only pointed to Books, Movies, or References. Adjusted logic so Profiles now pull quotes and excerpts through their authored books. Implemented extra spacing above and below Quotes and Excerpts for better separation from each other and from the Books grid. Centered section titles and lists to match the overall page layout.

Narrative Threads → Fragments migration & template updates

CPT migration: Created a new Fragment CPT as a lighter‑weight narrative building block. Migrated select chapters into fragments with preserved ACF data. Fixed an issue where migrated posts turned into attachment type — resolved by restoring post_type and correcting post_status (inheritpublish). Identified that the Themes taxonomy wasn’t attached to fragments initially — once re‑registered, existing term relationships reappeared (no data loss).

Artist templates: Reviewed Artists Featured page — confirmed original queries for feature_level taxonomy didn’t need changes just for fragments. Ensured secondary artists and non‑rappers remain visible.

Song template (content-song.php): Reordered layout — Song Excerpts now appear above YouTube embeds. Added Fragments grids beneath Narrative Threads, keeping “Referenced In” last for logical flow. Updated queries to pull both chapter and fragment CPTs when associating with songs.

Books integration: Adjusted logic so books can appear in “featured” slots of fragments/threads, even though they’re not primaries.

Chapters by Song (index pages): Expanded tables to now include 4 sections: Chapters in Order, Fragments in Order, Chapters by Artist, Fragments by Artist. Kept them as separate tables (not merged) for clarity.

General migration safety: Determined that ACF JSON field groups should remain identical across CPTs for interoperability. Recommended reimporting with unified headers rather than maintaining divergent “fragments‑only” groups.