Summary

Built and deployed a complete 5-page attorney website for Colleen S. Butler (colleen.zenthic.space) entirely through the Laravel Forge API and WP-CLI — no manual WordPress admin interaction. Then diagnosed and fixed a GeneratePress 3.6 typography rendering bug that had fonts configured but invisible.

Pages Deployed

All 5 pages were written using WordPress core blocks only (not GenerateBlocks) because GB Pro v2 doesn't render inline styles on the frontend. Each page was authored as raw block markup, base64-encoded locally, decoded on the Forge server, and injected via wp post update.

PagePost IDKey Features Home7Burgundy hero with dual CTAs, 3-column stats bar (gold stars, gold numbers), 6 service cards (2 rows x 3) with gold top borders, Meet Colleen bio section, testimonial quote, full-width CTA Services86 detailed service cards (Divorce, Child Custody, Child Support, Adoptions, Protective Orders, Paternity), "Why Choose Colleen" 2x2 grid, 6 FAQ accordions using / in wp:html blocks About9Cream hero, 5-paragraph attorney bio, CSS timeline with gold markers, burgundy stats bar (4-column), gold-bordered personal note, CTA Contact10FluentForm (ID 3) + office info 2-column layout, embedded Google Maps iframe, phone CTA banner Reviews115.0 rating summary with gold stars, 4 client review cards with gold left borders, Avvo badge section

Typography Fix: The GP 3.6 Migration Gap

Problem: Playfair Display and Source Sans 3 were configured in GP Premium 2.5.5's generate_settings[font_body], generate_settings[font_heading_1], etc. — but GeneratePress 3.6.1 had use_dynamic_typography: true, which tells it to read from a completely different data structure. That structure was empty. Result: all CSS font-family declarations were missing from the rendered page.

Root cause chain:

1. GP Premium 2.5.5 writes to old generate_settings[font_*] keys

2. GP 3.6.1 checks generate_get_option('use_dynamic_typography') — returns true

3. GP reads generate_get_option('typography') — returns empty array (default)

4. No font CSS generated. Site falls back to system sans-serif everywhere

Key discovery: generate_get_option() reads from get_option('generate_settings')[$key], NOT from a standalone WP option. Writing to update_option('typography', $data) does nothing — the data must be inside the generate_settings array.

Second discovery: The typography array controls CSS output (selectors + font properties), but font_manager controls Google Fonts loading. Without font_manager entries with googleFont: true, GP never enqueues the Google Fonts stylesheet — even if typography CSS references the fonts.

Fix (two-part):

1. Populated generate_settings['typography'] with 8 entries mapping selectors to fonts:

  • body -> Source Sans 3 (400, 17px, 1.7 line-height)
  • all-headings, h1, h2, h3 -> Playfair Display (600-700 weight, sized per level)
  • h4 -> Source Sans 3 (600)
  • .main-navigation a -> Source Sans 3 (600, 14px, uppercase)
  • button, .wp-block-button .wp-block-button__link -> Source Sans 3 (600, 15px, uppercase)

2. Populated generate_settings['font_manager'] with Google Font entries:

  • Playfair Display: variants 600,700, category serif
  • Source Sans 3: variants 400,600,700, category sans-serif

3. Cleared all GP dynamic CSS caches + OPcache

Result: Google Fonts stylesheet now loads both families with correct weights. All CSS selectors output proper font-family declarations. Headings render in elegant serif (Playfair Display), body text in clean sans (Source Sans 3), navigation and buttons uppercase Source Sans 3.

Technical Details

  • Forge server: 1157556, Site: 3051583
  • WP path: /home/colleenzenthicspace/colleen.zenthic.space/public_html
  • Deploy method: Local authoring -> base64 encode -> Forge Site Command API -> decode + wp post update --post_content
  • Command helper: Python script (forge-cmd.py) wrapping Forge's command API with polling
  • Theme stack: GeneratePress 3.6.1 + GP Premium 2.5.5
  • Font pairing: Playfair Display (headings) + Source Sans 3 (body/UI) — classic authority + readability combo for legal

Infrastructure Already in Place (from prior sessions)

  • GP color palette: burgundy (#7B2D3B), gold (#C9A96E), cream (#FFF8F0), charcoal (#2D2D2D)
  • Header: burgundy background, cream text, gold site description
  • Navigation: 5-page menu (Home, Services, About, Contact, Reviews)
  • Footer: charcoal background, gold links
  • Schema: csb-schema.php mu-plugin with LocalBusiness + Attorney + FAQPage JSON-LD
  • SEO: SureRank meta titles + descriptions on all 5 pages
  • Forms: FluentForm ID 3 on Contact page
  • Front page: set to Home (page 7), no blog index

Reflection: The GP 3.6 typography system is a migration trap. The old font keys still exist in the database and the Customizer appears to show font selections, but with use_dynamic_typography: true the rendering engine ignores them entirely. You need BOTH typography (for CSS output) AND font_manager (for Google Fonts loading) inside generate_settings. Neither the GP docs nor the Customizer UI make this obvious — had to trace through class-typography.php to find generate_get_option() and discover the two-layer system.