upgrade-plan.md 12 KB

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 themetheme.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.phprequire_once of inc/<module>/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)

  • 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.phpinc/ 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)

  • Stand up @wordpress/scripts + webpack: package.json (build/start scripts + deps), .babelrc, webpack.config.js (browser-sync proxying daw.stu:3030), src/build/ seed
  • npm install + npm run build verified (compiles src/build/index.js). npm start wired (browser-sync daw.stu:3030), not yet run.
  • 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 cssfv4-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.jscode.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

  • theme.json v3: layout, color palette, typography, spacing, element styles
  • Port design tokens out of style.css/styles.scss

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]
  • 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).

Changelog

  • 2026-06-16JS 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-16CSS 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 supersededstyles.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).