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]].
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.
theme.json + templates/ + parts/ + patterns/ + blocks/, Site-Editor driven (like srh).@wordpress/scripts + webpack — replaces the gulp pipeline.front-page.php (centered card, davo-bot, inline critical CSS); a classic PHP front-page coexists fine inside a block theme.srh theme)functions.php → require_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.wp-scripts build/start, custom webpack.config.js for extra entries + BrowserSync, .babelrc with wp.element.createElement pragma.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).
@wordpress/scripts + webpack: package.json (build/start scripts + deps), .babelrc, webpack.config.js (browser-sync proxying daw.stu:3030), src/ → build/ seednpm install + npm run build verified (compiles src/ → build/index.js). npm start wired (browser-sync daw.stu:3030), not yet run.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).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.
ProvidePlugin)#sv, #brain, #svg-device…)#studio-caro hero background)Cookies) — single.validate()) — WP comment form (#commentform) on single + aboutcode.js defines the grammars; 20 posts use data-language (candidate to replace with a modern highlighter in Phase 4)about/studio/music/art/desk/contact/single/analytics/code.js + front-page.jsscrollTo 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).]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.scripts.js/gulp/v4-* stay on disk + in git; enqueues switch only after page verification.theme.json v3: layout, color palette, typography, spacing, element stylesstyle.css/styles.scsstemplates/: index, single, archive, page, home, search, 404, category, tagparts/: header, footer (retire header-*.php / footer-*.php variants)front-page.php bespoke (coexists)page-*.php: → block template, → pattern, → retire (see open questions)
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.page-*.php whittling is Phase-3 work: title-droppers → No Title template; bespoke pages (about/studio) → patterns; rest → block templates or retire.patterns/ for reusable sectionsblocks/ for dynamic bits (music/last.fm, desk loop → Query Loop, etc.)style.min.cssinc/ module map above.bio, cv, shop, archive, chat.fullcalendar still rendered anywhere? Is simple_html_dom still used?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).