KJP Website Updates — Project Hub

Consolidated from Notion 2026-04-23. Notion is deprecated; this file is canonical.

Client: Kurt Johnson Photography Site: kurtjohnsonphotography.com G&M Contact: Eric Downs KJP Contacts: Casey Kurz (project lead, MailChimp, wrote original descriptions), Tori Gerkin / Victoria Gerkin (Art Director, email contact), Kurt & Carolyn Johnson (photographer + business partner), Jerred (Casey's partner) Client Timeline: No hard deadline ("it took us a year to make this list") — proceed at our pace

Project Documents

Document What it is For
phase-2/KJP-AI-Feature-Brief.md What the client asked for, what we're building, plain-English process overview Client-facing
phase-2/KJP-AI-Tagging-PRD.md Full technical spec — architecture, data model, API routes, WP plugin, build order Internal / Dev
phase-2/KJP-AI-Cost-Estimate.md Per-image token costs, model comparison, OpenRouter strategy, client invoice numbers Internal / Dev
phase-2/KJP-AI-LLM-Strategy.md Three tiered AI options (Small/Medium/Large) + LLM discoverability strategy Discovery framing
phase-1/PHASE-1-SCOPE-AND-OUTLINE.md Signed Phase 1 SOW scope with dev outline Active build
phase-1/KJP-Website-Updates-Working-Doc.md Detailed per-item specs, code snippets, hours Active build

Timeline Summary

Signed Phase 1 SOW (✅ Launched 2026-05-09)

Amount: $1,800 / 8 hrs / 14-day production PDF: phase-1/2026-018_SOW_Phase2-SIGNED.pdf Loom walkthrough (original): https://www.loom.com/share/956083d2d25f422db797958547ee80bc

Line items: Gallery Lightbox (Photography + Installations), Installation Slider dynamic sidebar, Newsletter MailChimp + Name Fields, Exclude Team from Analytics, Search > 200.

Full dev outline: phase-1/PHASE-1-SCOPE-AND-OUTLINE.md.

Site Stats

Metric Count Notes
Photography posts 8,372 Tags/type 99%+ covered
Installations 486 10-30 photos each in slider
Missing descriptions 6,124 (73%) Primary AI tool target
Missing color 3,416 (41%) Client interested in AI tagging this
Missing region 4,630 (55%) Client will handle manually (overlapping regions)

Environment & Access

Item Detail
Host Kinsta
SSH ssh kurtjohnsonphotographycom@34.162.230.19 -p 61436
WP path (prod) /www/kurtjohnsonphotographycom_376/public
Theme gmlaunch
Local dev DevKinsta (Docker, not Local by Flywheel)
Local URL http://kurtjohnsonphotographycom.local:50381
GA4 Property G-RF1XX48Q59
Image storage Flat files at /wp-content/uploads/wpallimport/files/ — NOT in Media Library
Import Google Sheet https://docs.google.com/spreadsheets/d/1YYkMxk3xBrMHBywyEqWFbvo75qTyyU2G3s2hsb9NKso

Feature Requests — Status & Decisions

Status: Scoped — ready to build Client asks: - Hover over image in archive grid → image pops up slightly larger showing full crop + KJP 4-digit code - Click image → opens full-size lightbox with all metadata + prev/next arrows to browse all images on that page - Works on both Photography AND Installation archive pages

Solution: PhotoSwipe 5 (MIT, zero dependencies, ~5kb, built for photography)

Client Decisions:

Question Answer
Click or hover? Both. Hover = slightly larger preview + code. Click = full lightbox with arrows.
Arrow browsing scope All images on the current page
Info in lightbox Hover: just KJP 4-digit code. Click/lightbox: all info + arrows
Which archives? Both Photography and Installations

Dev note: Two-part interaction — hover preview (CSS/JS tooltip) + click-to-open lightbox (PhotoSwipe). Hover preview is separate from the lightbox and needs custom implementation. Files: loop-photo.php, functions.php, slick-init.js, FacetWP facetwp-loaded rebinding.

Scope question (Apr 23): Signed SOW only mentions click lightbox. Hover preview was in the original quote. At trimmed 8 hrs, need Eric's call on whether hover stays in Phase 1.

2. Installation Slider — Dynamic Sidebar (Phase 1 — Active)

Status: Scoped — ready to build (KJP handles data entry)

What they want: When clicking through installation photos, the sidebar info should change per slide — everything except title and institution.

Solution: Extend ACF installations_photos_2 repeater with per-photo subfields + JS sidebar swap on Slick afterChange.

Client Decisions:

Question Answer
What changes per photo? Everything EXCEPT title and institution. Description, type, tags all change.
Institution stays same? Yes — project name stays, browse photos within that one installation
Who enters the data? KJP handles data entry. They have most of it already.
Simpler version? No — they want full data per photo, not just captions

Dev note: We build the fields and the JS swap logic. KJP populates 486 installations worth of per-photo data. They said "we will rewrite descriptions to better match the photos." Files: single-installations.php, slick-init.js, ACF field group for repeater subfields.

3. Newsletter — MailChimp + Name Fields (Phase 1 — Active)

Status: Scoped — ready to build (need MailChimp API key from Casey)

What they want: Newsletter form → MailChimp integration, add first/last name fields, sitewide.

Solution: Gravity Forms MailChimp Add-On + reCAPTCHA v3 (98% spam rate found in Q1 maintenance).

Client Decisions:

Question Answer
MailChimp account? Yes. Casey is lead and can provide API key.
Keep email to Tori? Yes, keep as backup
Sitewide or homepage? Sitewide (footer form on all pages + homepage module)
Name fields required? Yes, required

Blocker: MailChimp API key from Casey.

4. Exclude Team from Analytics (Phase 1 — Active)

Status: Scoped — ready to configure (no code changes)

What they want: Remove KJP team from GA4 tracking.

Solution: GA4 internal traffic filters (IP-based for office/studio) + Google Analytics Opt-out browser extension for home.

Client Info: - 4 team members: Casey & Jerred (live together), Kurt & Carolyn (live together) - All work from home AND a studio - Need: 3 IP addresses (2 homes + 1 studio) + browser extensions for all 4

Blocker: Need the 3 IP addresses — Casey/Jerred home, Kurt/Carolyn home, studio. Each person Googles "what is my IP" from each location.

6. Search Results Limit (Phase 1 — Active)

Status: Ready to deploy — one-line fix

What they want: Search caps at 200, show all results.

Solution: Change cap in FacetWP/SearchWP integration from 200 → 2,000. Use SearchWP per_page filter (fires after FacetWP's override). Do NOT edit FacetWP plugin file directly (overwritten on update).

No client input needed. Ready to ship today.

7. AI-Generated Tags & Descriptions (Phase 2 — Deferred)

Status: DEFERRED to fall/winter 2026 per Tori (4/17). Original SOW sent 3/10 ($5,625 / 25 hrs) superseded by Phase 1 signed 4/21.

Original plan: Custom AI tool to backfill 6,124 missing descriptions with a feedback/learning loop.

Scope evolution (Casey's input 3/10):

Key insight from Casey: "More than having descriptions for each image, we think it would be more beneficial to have AI generate the searchable tags for each image." Tags are their priority — designers search by mood (uplifting, calm, soothing), flower types, etc. Descriptions are secondary and only worth it if they significantly help SEO.

What Casey wants (priority order): 1. AI-generated tags — mood (uplifting, calm, soothing), specific flower/plant species, visual descriptors. #1 ask. 2. AI color classification — Casey interested in AI tagging dominant color(s). Asked: "Does AI have capability of picking the most prominent color(s)?" 3. AI descriptions — open to it IF reasonably priced and good for SEO, but not the priority. 4. Region — NO. They overlap regions and handle manually.

Voice/tone guidance (for descriptions if we do them): - Match Casey's existing description style - Healthcare-focused client base — avoid negative, dark, or threatening words - Never use the word "magical" — Kurt hates it

Review process: KJP reviews everything before publish. No auto-publish. Ongoing: Yes, auto-tag new uploads.

Full spec: phase-2/KJP-AI-Tagging-PRD.md · Costs: phase-2/KJP-AI-Cost-Estimate.md · Tiers: phase-2/KJP-AI-LLM-Strategy.md

Action Items — G&M (as of hub consolidation)

Phase 1 (Active): - [ ] Request MailChimp API key from Casey - [ ] Request 3 IPs (Casey/Jerred home, Kurt/Carolyn home, studio) - [ ] Deploy search limit fix (no blockers, do it) - [ ] Resolve hover-preview scope question with Eric - [ ] Build calendar + kickoff email to Tori

Phase 2 (AI — Deferred): - [ ] Follow up with Casey re: AI tags vs descriptions — scope tagging system (mood, species, visual descriptors) - [ ] Answer Casey's multi-color question — yes, AI can tag multiple or pick dominant - [ ] Assess SEO value of descriptions — give Casey a straight answer - [ ] Taxonomy cleanup before any AI work (Pruple, Yelllow, Gold, Grasses, Gray, Black + zero-post region/type terms)

Outstanding Questions (for when Phase 2 activates)

  1. MailChimp API key — Casey said she'd provide it (still open for Phase 1 too)
  2. IP addresses for analytics filtering — still open for Phase 1
  3. AI scope clarification — mood tag categories, supplement vs replace, descriptions in or out
  4. Multi-color tagging — all prominent vs dominant
  5. Budget/timeline expectations for Phase 2

Completed Work

2026-04-23 — Alphabetized website By Type filter (FacetWP type facet orderby flipped from count to display_value via direct SQL on facetwp_settings). Verified in Chrome. No charge, Phase 1 goodwill.

2026-04-17 — Fixed the Number/Featured Image column swap that broke 69 photography posts. Patched production DB, corrected sheet rows, added hard data validation. Full post-mortem in theme docs.

Q1 2026 Maintenance (Feb) — DevKinsta setup (MariaDB auth, port conflicts, SSH key, rsync sync, 52k URL replacements). Bug fixes: PHP warnings on Photography archive (loop-photography.php line 65 $have_posts$wp_query), ACF translation loading notice (wrapped acf_add_options_page() in init hook), deactivated Bulk Delete plugin. Spam finding: 98% of form entries were spam bots.

Project Quote Reference

Approach: No formal design pass — we build to match the existing site's look and feel, then show a working mockup for client review before finalizing.

Original estimate (pre-Phase 1 signing):

# Item Hours Status
1+5 Gallery Lightbox + Hover Preview 5 Signed Phase 1 (trimmed to fit 8-hr budget)
2 Installation Slider — Dynamic Sidebar 2 Signed Phase 1
3 Newsletter — MailChimp + Name Fields 0.5 Signed Phase 1 (waiting on API key)
4 Exclude Team from Analytics 0.5 Signed Phase 1 (waiting on IPs)
6 Search Results Limit Fix 0.5 Signed Phase 1 (ready to deploy)
QA, Testing & Launch 1 Signed Phase 1
7 AI & LLM Strategy — Discovery 3–5 Deferred to Phase 2
7 AI & LLM Strategy — Build TBD (S/M/L tiers) Deferred to Phase 2

Signed Phase 1 SOW total: 8 hrs / $1,800 (well below the 23.5–36 hr original range). Eric's call: assume intentional, work to 8 hrs.

Technical Reference

Taxonomy Data (from production DB)

Tags: 2,778 terms (396 zero-post), 59,446 assignments across 8,372 posts. Free-form hierarchical. Significant duplicates (flower/flowers, landscape/landscapes, tree/trees) and typos (testure, tesures, palicans, slouds, photgraphy).

Top 15 tags by usage: flower (2,425), flowers (2,290), landscape (1,944), green (1,678), trees (1,642), grasses (1,590), landscapes (1,448), leaves (1,349), tree (1,309), water (1,261), waterscape (1,211), midwest (1,096), texture (1,075), leaf (1,041), waterscapes (990).

What's missing (Casey's ask): Mood/emotional tags (uplifting, calm, soothing, serene, energetic). Specific plant species (lily exists; most flowers aren't identified by species).

Color: 16 terms (6 zero-post). Active: Green (1,501), Yellow (681), Pink (644), Orange (527), White (519), Blue (501), Purple (495), Red (416), Brown (273), Black/White (82). Junk: Pruple, Black, Gold, Gray, Yelllow, Grasses. Total coverage: 5,639 of 8,372 posts (67%).

Type: 14 active (as of 2026-04-23): Flowers (2,067), Landscapes (1,551), Waterscapes (1,108), Leaves (990), Trees (954), Grasses (781), Animals (615), Panoramas (603), Textures (456), Vectors (273), Impressionism (190), Slices (126), Layers (75), Whimsy (44). Typos to clean (all 0): Wasterscapes, Gresses, Landscaspes, Watescapes, Ainmals, Aninmals, Aniamls, Graasses, Grassses, Panoramics, Flower, Vector, Texture, Landscape, Interpretations, Filters.

Region: 11 terms (4 zero-post). Active: Midwest (1,575), Southeast (814), Southwest (475), East (347), Rocky Mountains (335), Pacific (217), Noncontiguous (8). Unused: Great Lakes, Northeast, Mid-Atlantic, East Coast.

Key File Paths

Purpose File
Photography CPT + taxonomies functions/post-type-photography.php
Installations CPT + taxonomies functions/post-type-installations.php
Photography archive archive-photography.phpinc/cpt-loops/loop-photography.php
Photo grid item inc/loops/loop-photo.php
Installation single + slider single-installations.php
Slick slider config js/slick-init.js
Footer (newsletter form) footer.php (Gravity Form ID 2)
Newsletter CTA module inc/page-modules/2_column_email_signup_cta_module.php
FacetWP rebinding + scroll header.php (facetwp-loaded event)
Search 200 limit (source) plugins/facetwp/includes/integrations/searchwp/searchwp.php line 187
ACF: Installation photos repeater acf-json/group_62741bba884ac.json
ACF: Page modules acf-json/group_5afb1724c1090.json
FacetWP settings functions/wp-facet-settings.php (theme filter hooks) — main settings live in facetwp_settings WP option

Architecture Notes