# daw v0.5.0 — Upgrade Plan (working doc) Living plan for migrating the `daw` theme from a 22-year-old classic PHP theme to a modern FSE block theme. Update freely as we go. Companion: [[dependencies]]. ## Goal Bring `daw` in line with how I build themes now (the `srh` theme is the reference), shedding accumulated cruft along the way — without losing the bespoke, hand-crafted character of the site. ## Locked decisions (2026-06-15) 1. **Full block / FSE theme** — `theme.json` + `templates/` + `parts/` + `patterns/` + `blocks/`, Site-Editor driven (like `srh`). 2. **Build:** `@wordpress/scripts` + webpack — replaces the gulp pipeline. 3. **Homepage stays bespoke** — keep the hand-rolled `front-page.php` (centered card, davo-bot, inline critical CSS); a classic PHP front-page coexists fine inside a block theme. ## Target conventions (from the `srh` theme) - **Loader:** thin `functions.php` → `require_once` of `inc//loader.php`; each subdir's loader requires its peers. Consistent `dw_` function prefix. - **`inc/` by concern:** e.g. `seo/`, `analytics/`, `perf/`, `a11y/`, `integrations/` — each procedural, hooked to `wp_head`/`wp_footer`/`wp_enqueue_scripts`. - **`theme.json` v3:** `settings` (layout contentSize/wideSize, color palette, typography fontFamilies/fontSizes, spacing) + `styles` (elements). Design tokens live here, not in CSS. - **`templates/` + `parts/`:** block-markup `*.html` (`index/single/archive/page/home/search/404/category`); parts for `header`/`footer`. - **`patterns/`:** auto-discovered from `/patterns/` via PHP file headers (Title/Slug/Categories/Block Types). Categories registered in `functions.php`. - **`blocks/`:** per-block `block.json` (apiVersion 3) + `render.php`; `autoRegister:true` for render-only blocks (WP 7.0+), manual `register_block_type` + editor script for interactive ones. - **Build:** `wp-scripts build`/`start`, custom `webpack.config.js` for extra entries + BrowserSync, `.babelrc` with `wp.element.createElement` pragma. --- ## Phases ### Phase 0 — Get a handle on it (done) - [x] Document existing dependencies → [[dependencies]] - [~] **Refactor `functions.php` → modular `inc/`** — **deferred** (2026-06-15): it's only ~200 lines and readable enough; not worth chopping yet. The `inc/` modularization will happen naturally as the FSE build grows. Map kept below for when we do. **Proposed `functions.php` → `inc/` map (deferred — reference)** (current responsibilities → modules): | Current (in functions.php) | New home | |---|---| | `dw_setup()` — theme supports, image sizes | `inc/setup.php` | | `dw_scripts()` — the per-page enqueue ladder | `inc/assets.php` (the big readability win) | | `dw_editor()` — editor styles | `inc/assets.php` | | `dw_analytics()` — Matomo footer | `inc/analytics/matomo.php` | | `dw_login_session()` — auth cookie filter | `inc/auth.php` | | `dw_ask_widget()` — davo-bot loader | `inc/integrations/davo-bot.php` | | `dw_plugs()` → smtp | `inc/integrations/smtp.php` (wraps existing `inc/smtp.php`) | | existing `inc/{utils,template,tweaks,form,analytics}.php` | keep; fold into loader | `functions.php` ends up a thin bootstrap: define constants → `require inc/loader.php`. **Behavior must be byte-for-byte identical** at this stage (pure reorg, no feature change). ### Phase 1 — Build toolchain (in progress) - [x] Stand up `@wordpress/scripts` + webpack: `package.json` (build/start scripts + deps), `.babelrc`, `webpack.config.js` (browser-sync proxying `daw.stu:3030`), `src/` → `build/` seed - [x] `npm install` + `npm run build` verified (compiles `src/` → `build/index.js`). `npm start` wired (browser-sync `daw.stu:3030`), not yet run. - [x] **CSS build → webpack** (2026-06-15): `v4-style.min.css` is now built by webpack — `src/legacy-style.js` imports the 5 sources in gulp's order → MiniCssExtractPlugin → theme root, `css-loader { url:false }` (keeps `fonts/…` paths), cssnano `discardComments.removeAll` (matches old clean-css). Faithful 1:1: 444 KB vs gulp 451 KB, fonts/sources/order intact, serves 200. **`style-min` enqueue unchanged.** The `cssf` → `v4-front.min.css` output was dead (nothing enqueues it) — skipped. ⚠️ **Don't run `gulp build`** now — it would overwrite `v4-style.min.css` with the (equivalent) clean-css version; webpack owns it. JS bundles still on gulp (`js`/`jsf`). - [ ] Port front-end JS into webpack incrementally as behaviors modernize (Phases 2–4) **Decision (2026-06-15):** new toolchain runs **alongside** the existing gulp build, not replacing it yet. **Gulp is still the active build** — it pulls vendor packages out of `node_modules` (bootstrap, jquery, fullcalendar, svg-morpheus, animate, …) and concats/minifies them with `style.css`/`styles.css` into the `v4-*.min.*` files the live theme enqueues (`gulp copy`/`mixin`/`build`/`js`/`jsf`/`cssf`). It keeps running normally; wp-scripts just adds a second, block-aware pipeline. **Retiring gulp + the `v4-*` outputs happens in Phase 5**, once block templates + `theme.json` supersede those assets. New source is isolated in `src/` → `build/` so it never collides with the legacy files in `js/`. **JS bundle audit (2026-06-15, corrected).** ⚠️ My first two broad greps were unreliable — **zsh doesn't word-split an unquoted file-list variable**, so the multi-file searches erred into false "unused." Re-audited with literal file args + context + DB content scan. Corrected result: **`scripts.js` is the plugin *library* the per-page scripts call into — mostly load-bearing, not dead.** - **KEEPERS (verified in use):** - jQuery + bootstrap/Carousel — site-wide (jQuery via webpack `ProvidePlugin`) - **WOW** — about, studio, art, desk - **DrawFillSVG** — about, studio (animates the inline SVGs `#sv`, `#brain`, `#svg-device`…) - **backstretch** — studio (`#studio-caro` hero background) - **lazyload** — desk - **js-cookie** (`Cookies`) — single - **jQuery Validation** (`.validate()`) — WP comment form (`#commentform`) on single + about - **Rainbow.js** — `code.js` defines the grammars; 20 posts use `data-language` (candidate to replace with a modern highlighter in Phase 4) - **SVGMorpheus** — front-page only (icon morph) - page scripts `about/studio/music/art/desk/contact/single/analytics/code.js` + `front-page.js` - **DROP (verified unused — 0 in page scripts, templates, content):** Typed.js, Formstone Wallpaper, smoothState, jQuery Waypoints, jquery.appear, **jquery-scrollto** (the `scrollTo` hits were native `$(window).scrollTop()`), Modernizr, **ghembedder** (post 1341 cleaned; only a 2023 revision still references `.github-widget`). [**fullcalendar is NOT droppable** — used on the About page calendar; my earlier "0 usage" was a case-sensitivity miss (`FullCalendar.Calendar`).] - **Implication → revised build rec:** most legacy plugins are in use *and* are exactly the ones slated for native/modern replacement in Phases 3–4 (WOW→IntersectionObserver/CSS, lazyload→`loading=lazy`, backstretch→CSS bg, Rainbow→Prism, comment validation→native). Porting them to webpack **now** is throwaway work. So: **port CSS to webpack now; leave JS on gulp** and migrate it to webpack incrementally as each behavior is modernized — don't reproduce the fragile jQuery-plugin bundle just to delete it. - **Reversibility:** nothing deleted — `scripts.js`/gulp/`v4-*` stay on disk + in git; enqueues switch only after page verification. ### Phase 2 — theme.json foundation - [x] `theme.json` v3 (2026-06-17): layout (contentSize 1170 / wideSize 1280), 12-color palette (daw's real tokens — maroon link `#67000a`, terminal green `#34f743`, slate page bgs, ink/contrast), 7-size type scale, 4 fontFamilies (Computer Modern w/ `fontFace` → existing `fonts/cmun*`, Georgia, Helvetica Neue, Courier), element styles (h1–h6 scale, link maroon→blue hover, headings `#000`, button). Tokens mined from `style.css`/`styles.scss`. - **Classic-theme caveat:** theme.json is active but the front end is still `style.css`/ `v4-style.min.css`-driven. WP injects global-styles via low-specificity `:where()`, so the built CSS wins on conflicts — theme.json today mainly powers the **block editor** + the Phase-3 block templates. `useRootPaddingAwareAlignments:false` (no body-padding injection); `front-page.php` skips `wp_head()` so the bespoke homepage is unaffected. Verified `/`, `/about/`, `/studio/` all 200 with global styles emitting. - **Deferred to Phase 3:** fluid typography (off for predictability now), gradients/duotone, trimming the duplicate `@font-face` (theme.json now emits CM; `style.css` still does too — reconcile when `style.css` gets pared down). ### Phase 3 — Block templates + parts - [ ] `templates/`: index, single, archive, page, home, search, 404, category, tag - [ ] `parts/`: header, footer (retire `header-*.php` / `footer-*.php` variants) - [ ] Keep `front-page.php` bespoke (coexists) - [ ] Decide each legacy `page-*.php`: → block template, → pattern, → retire (see open questions) - **Interim done (2026-06-16):** the title-droppers `page-cv.php`/`page-shop.php` collapsed into a selectable classic template **`page-no-title.php`** ("No Title"; CV+shop assigned via `_wp_page_template`). In Phase 3 this becomes **`templates/page-no-title.html`**. NOTE: can't add block templates piecemeal — WP treats the theme as FSE only once `templates/index.html` exists, which flips *everything* off the classic PHP templates. So classic PHP is the correct interim until the full flip. - The whole `page-*.php` whittling is Phase-3 work: title-droppers → No Title template; bespoke pages (about/studio) → patterns; rest → block templates or retire. ### Phase 4 — Patterns + custom blocks - [ ] `patterns/` for reusable sections - [ ] `blocks/` for dynamic bits (music/last.fm, desk loop → Query Loop, etc.) ### Phase 5 — Cleanup (the "additional cleanup") - [ ] Drop confirmed-dead deps per [[dependencies]] (terminal.js, messenger, modernizr, jasny, animate.css…) - [ ] Resolve audits: Twilio call/SMS/chat, fullcalendar, simple_html_dom, Stripe v2, icon fonts - [ ] Remove legacy build outputs + `style.min.css` ### Phase 6 — New features - [ ] _TBD — to be specified_ --- ## Open questions / decisions to make - Sign-off on the Phase 0 `inc/` module map above. - **Page audit:** which legacy pages survive vs retire? Candidates to confirm: `bio`, `cv`, `shop`, `archive`, `chat`. - **Feature audits:** is the Twilio phone/SMS/chat feature still live? Is `fullcalendar` still rendered anywhere? Is `simple_html_dom` still used? - New features list (Phase 6). ## Domain migration (under consideration, 2026-06-19) Considering moving the whole site from **davidawindham.com → davidwindham.com**. - **`/work`** is currently just a nav item (homepage + header) → 404s for now. It will become the **davidwindham.com one-pager**, served as a static **`/work/` directory at the WP root** (Apache serves real dirs directly via `RewriteCond %{REQUEST_FILENAME} !-d`, bypassing WP — so no WP `work` page; don't create one or it'd shadow the dir). - **Migration scope (audit at migration time):** hardcoded hosts in templates — `davidawindham.com` (~14 refs) + `davidwindham.com` (~8) + subdomains (`radio`/`code`/`chess`/`photo`/`invoice`/`show`). Note `davidwindham` is a substring of `david**a**windham` — greps overlap, so audit carefully. Also: DB `siteurl`/`home` + content URLs, canonical + JSON-LD blocks (front-page.php, header.php), local dev hostnames (`daw.stu`, `daw.ovid`), and the BrowserSync config (`daw.stu:81` in webpack.config.js + the `rest_after_insert` reload ping in functions.php). ## Changelog - **2026-06-17** — **Dead-code cull (pre-Phase-3 simplification).** Decisions locked: standardize on the modern `header.php` (Bootstrap Icons, flat nav); do dead-code removal now, the header/footer + `page-*.php` consolidation in the Phase-3 FSE flip. This pass: - **Removed `page-chat.php`** (abandoned self-contained Twilio chat) + its only-consumer assets (`js/front.min.js`, `css/front.min.css`, `js/chat.js`, `js/chat.min.js`, `js/chat_func.js`, `css/chat.css`) and **trashed the published `/chat/` page** (ID 1241, recoverable). `/chat/` now 404s. - **Removed the duplicate `header-studio.php`** — it was byte-identical to `header-home.php` except the meta-description string. Repointed `page-studio.php` → `get_header('home')` (no render change; studio's meta desc is now header-home's generic one — fine, redone in Phase 3). - **Removed `dw_online_get_chat()`** from `inc/tweaks.php` (broken `Messenger()` polling + `.chat` modal trigger; `page-chat` was its only caller). Verified valid PHP; `/`, `/studio/`, `/about/`, `/desk/` all 200. - **Then removed the whole "DAW Online / Messenger" feature** (2026-06-17, unused for years): the `dwstatus` admin settings page + 6 `daw_is_online_*`/`dw_online_get_status` functions (cut from `inc/tweaks.php`), the `dw_online_get_status()` call in `front-page.php`, the `daw_is_online_settings` DB option (deleted), `css/messenger.css`, and the orphaned `js/front-page.min.js` (old pre-webpack bundle with Messenger baked in). Also deleted the **stale root `tweaks.php`** (verified required nowhere — `functions.php` loads `inc/tweaks.php`). Verified: `php -l` clean, `/`, `/about/`, `/studio/`, `/contact/` all 200, no Messenger in output. Only "messenger" left in the theme is the unrelated `.bi-messenger` Bootstrap icon. - **Removed orphaned `js/terminal.js`** (old terminal emulator, replaced by davo-bot; verified unreferenced). - **2026-06-17** — **gulp retired entirely.** Deleted `gulpfile.js` + the 8 gulp-only devDeps (`gulp`, `gulp-clean-css/concat/rename/sass/terser/uglify`, `streamqueue`); kept `browser-sync` + `sass` (webpack uses both). Removed 19 orphaned files (all git-tracked → reversible): the gulp vendor copies (`v4-jquery/bootstrap/fullcalendar/svg-morpheus.js` + `bootstrap.bundle.js.map`), the dropped/replaced gulp JS inputs (`modernizr/validate/scripts/svg-morpheus/messenger`), superseded old outputs (`script.min/validate.min/fullcalendar/fullcalendar.min/moment.min/drawfillsvg`), and orphaned CSS (`v4-animate.css`, `styles.css`, `v4-front.min.css`). **Kept (load-bearing/out-of-scope):** `js/front.min.js` (page-chat.php loads it!), `terminal.js`/`code.js`/`color.js` (orphan but not build artifacts — didn't write them). `npm run build` verified clean; outputs unchanged. webpack.config.js header + CLAUDE.md Build section updated to reflect webpack-only. **`npm run build` / `npm start` is now the whole toolchain.** - **2026-06-16** — **JS bundles → webpack** (`v4-front.min.js` + `v4-script.min.js` now built by `src/front.js`/`src/main.js`; npm vendor + 2 self-exposing vendored files `src/vendor/{rainbow,drawfillsvg}.js`). **Studio slider regression diagnosed + fixed via a jsdom harness** (load built bundle in a real DOM, assert every global): two crashes — (1) `drawfillsvg.js` referenced the now-dropped `Modernizr` global (`Modernizr.prefixed('transition')`) → top-level ReferenceError that **aborted the whole main bundle** (so jQuery/bootstrap/WOW/everything was undefined, not just Studio). Replaced with the unprefixed `"transitionend"` (universal today) — Modernizr fully gone. (2) FullCalendar v5 `main.js`'s exports object carries `__esModule:true` but no `.default`, so a *default* import unwrapped to `undefined`; switched `src/main.js` to a namespace import. Verified all 12 deps resolve (jQuery, bootstrap.Carousel, FullCalendar.Calendar, WOW, Cookies, DrawFillSVG, Rainbow, `$.fn.{backstretch,lazyload,validate,tab,carousel}`). `$.fn.tab/carousel` re-attach via Bootstrap 5's `defineJQueryPlugin` at DOMContentLoaded (needs `window.jQuery` set first — it is). **Browser verification of affected pages pending; then drop gulp + orphaned legacy JS.** - **2026-06-16** — **CSS pipeline fully on webpack.** Wired `sass-loader` (`implementation: require('sass')`, `quietDeps`) so webpack compiles `styles.scss` directly (Bootstrap + bootstrap-icons from `node_modules`) instead of importing the gulp-compiled `styles.css`. gulp's `mixin` / CSS `copy` / `build` / `cssf` are now **fully superseded** — `styles.css` is an orphaned artifact (source of truth = `styles.scss`). Then **upgraded Bootstrap 5.2.3 → 5.3.8** (flows straight through the webpack sass compile; bundle 440→470 KB from 5.3's color-mode vars). Removed `jasny-bootstrap` (unused). **Visual verification pending.** Next dep upgrades (bootstrap-icons, animate.css) flow the same way. gulp still owns JS bundles until the JS migration; once that's done, gulp goes entirely. - **2026-06-15** — Fixed intermittent **stuck loader** (reported on Studio). Cause: `#loader` was hidden only by per-page `$(window).bind('load', …fadeOut)` with no fallback — if a resource hung (Studio backstretches `camera.mp4`) or `load` already fired, it stuck forever. Fix: `loader.php` now hides the preloader itself in vanilla JS (runs in the header, before `load`), with a `setTimeout` fail-safe (6s) + `readyState` check. The per-page `fadeOut` bindings in `studio/about/art/desk.js` are now redundant (harmless; clean up when those scripts are modernized in Phases 3–4). Not caused by the CSS build change — pre-existing. - **2026-06-15** — Plan created; dependencies documented; decisions locked (FSE / wp-scripts / bespoke homepage).