🔵 other: Rename project and publish

This commit is contained in:
Keith Solomon
2026-07-29 14:25:19 -05:00
parent 5512918b0f
commit 7dbb991fb9
70 changed files with 558 additions and 5386 deletions
+2 -20
View File
@@ -1,23 +1,5 @@
{ {
"permissions": { "env": {
"allow": [ "OTEL_RESOURCE_ATTRIBUTES": "project.name=SoloFrame-Evo,project_name=SoloFrame-Evo,env=WordPress,service.namespace=development,tool=claude-code"
"Bash(mkdir -p \"C:/Users/ksolo/Projects/Work Projects/VDI-Starter-v5/.understand-anything/intermediate\")",
"Bash(mkdir -p \"C:/Users/ksolo/Projects/Work Projects/VDI-Starter-v5/.understand-anything/tmp\")",
"Bash(grep -v \"knowledge-graph.json$\")",
"Bash(npm --version)",
"Bash(npm install *)",
"Bash(pnpm --version)",
"Read(//c/Users/ksolo/.claude/plugins/cache/understand-anything/understand-anything/2.5.0/**)",
"Bash(pnpm install *)",
"Bash(pnpm --filter @understand-anything/core build)",
"Bash(node -e ' *)",
"Bash(node *)",
"Bash(python \"C:/Users/ksolo/.claude/plugins/cache/understand-anything/understand-anything/2.5.0/skills/understand/merge-batch-graphs.py\" \"C:/Users/ksolo/Projects/Work Projects/VDI-Starter-v5\")",
"Bash([ -d \"$PLUGIN_ROOT/packages/dashboard\" ])",
"Bash(GRAPH_DIR=\"C:/Users/ksolo/Projects/Work Projects/VDI-Starter-v5\" npx vite --host 127.0.0.1)",
"Bash(git add *)",
"Bash(git commit -m ' *)",
"Bash(git checkout *)"
]
} }
} }
+2 -2
View File
@@ -59,6 +59,6 @@ jobs:
uses: wpengine/github-action-wpe-site-deploy@v3 uses: wpengine/github-action-wpe-site-deploy@v3
with: with:
WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }} WPE_SSHG_KEY_PRIVATE: ${{ secrets.WPE_SSHG_KEY_PRIVATE }}
WPE_ENV: vdiv5 WPE_ENV: <change-me>
FLAGS: '-azvr --inplace --delete --exclude=".*"' FLAGS: '-azvr --inplace --delete --exclude=".*"'
REMOTE_PATH: "wp-content/themes/vdi-v5" REMOTE_PATH: "wp-content/themes/<change-me>"
-32
View File
@@ -1,32 +0,0 @@
# .understandignore — patterns for files/dirs to exclude from analysis
# Syntax: same as .gitignore (globs, # comments, ! negation, trailing / for dirs)
# Lines below are suggestions — uncomment to activate.
# Use ! prefix to force-include something excluded by defaults.
#
# Built-in defaults (always excluded unless negated):
# node_modules/, .git/, dist/, build/, obj/, *.lock, *.min.js, etc.
#
# --- From .gitignore (uncomment to exclude) ---
# *~
# .DS_Store
# static/dist/
# .env
# bak/
# testimonials.class.php
# resource-filter/
# phpcs-results.txt
# /test-results/
# /playwright-report/
# /blob-report/
# /playwright/.cache/
# --- Detected directories (uncomment to exclude) ---
# tests/
# --- Test file patterns (uncomment to exclude) ---
# *.test.*
# *.spec.*
# *.snap
-712
View File
@@ -1,712 +0,0 @@
{
".env.example": {
"size": 58,
"mtime": 1777825781884.629,
"hash": "9c87082bd45460db86334fd3acea3b44"
},
".github/workflows/phpcs.yml": {
"size": 1020,
"mtime": 1777825781886.1328,
"hash": "955988d8d00a489b15aa88a88aae21a4"
},
".github/workflows/todos.yml": {
"size": 527,
"mtime": 1777825781886.1328,
"hash": "6fda48c7bbdadcf8e1acccd906f229ee"
},
".github/workflows/wpengine.yml": {
"size": 1931,
"mtime": 1777825781886.1328,
"hash": "87dfd255f35b4b499aa94d9e42bc7091"
},
".phpcs.xml": {
"size": 2478,
"mtime": 1777825781887.1445,
"hash": "04d7057ecdc57cca79bef5866b5189d2"
},
"404.php": {
"size": 1507,
"mtime": 1777825781888.1372,
"hash": "8ab93a649e112fe2768b988cd655d0ae"
},
"README.md": {
"size": 18416,
"mtime": 1777825781888.1372,
"hash": "4f6f07adeb2af3edf17d013eb304f481"
},
"acf/group_5f7f85a2a3e13.json": {
"size": 6396,
"mtime": 1777825781889.1365,
"hash": "2a88ba2db688528090946d956e2b56ef"
},
"acf/group_5fd3e006e5da5.json": {
"size": 15908,
"mtime": 1777825781889.1365,
"hash": "a1fc1fb34007909b16644e81cba4ef81"
},
"acf/group_600f5a9e242c3.json": {
"size": 10147,
"mtime": 1777825781889.1365,
"hash": "5008ba179d87feeb1248e18d6e6ba260"
},
"acf/group_60106ed700da3.json": {
"size": 7160,
"mtime": 1777825781890.65,
"hash": "9e3e91ae651bed941daf8707ec7a9fa7"
},
"acf/group_60bfb84ae973c.json": {
"size": 5506,
"mtime": 1777825781890.65,
"hash": "0053d6b09c043521cc434eb2a3473011"
},
"acf/group_60bfdb328901d.json": {
"size": 3036,
"mtime": 1777825781890.65,
"hash": "6a8f66b681bcd266d8c1ab54ef98e2ab"
},
"acf/group_6261bc658dd80.json": {
"size": 12859,
"mtime": 1777825781891.6606,
"hash": "5d28ff3cf8dfc2e277147d6d8438aa00"
},
"acf/group_645e51f721207.json": {
"size": 4156,
"mtime": 1777825781891.6606,
"hash": "f7b6adbd69a0f366caa44332434b6dd9"
},
"acf/group_645e7cf448e66.json": {
"size": 12304,
"mtime": 1777825781891.6606,
"hash": "08d883e93358825224d87c531f364244"
},
"bin/.build.js": {
"size": 648,
"mtime": 1777825781892.6602,
"hash": "ff47325f676fff321b2d745eb0ce607b"
},
"bin/.utils.js": {
"size": 637,
"mtime": 1777825781892.6602,
"hash": "fbf52725e6516a6177d366d227bd72f4"
},
"bin/.watch.js": {
"size": 1202,
"mtime": 1777825781893.6606,
"hash": "5167fae70eb7e1ed06210194f4769f1a"
},
"composer.json": {
"size": 873,
"mtime": 1777825781893.6606,
"hash": "231db8fffc6fcb14cb591ec8c12c9c02"
},
"content/basic-wp-test-content.xml": {
"size": 791437,
"mtime": 1777825781897.214,
"hash": "39f05bef4706c4ab5dbeb8ea3145654c"
},
"footer.php": {
"size": 4240,
"mtime": 1777825781897.214,
"hash": "50fc9d771ef337378105785b21dc6fe3"
},
"front-page.php": {
"size": 351,
"mtime": 1777825781897.214,
"hash": "85b76eebf72977bdd039ed3f15bc2593"
},
"functions.php": {
"size": 1074,
"mtime": 1777825781898.2146,
"hash": "3c137712c6f7498749c913ea81c46b79"
},
"header.php": {
"size": 1695,
"mtime": 1777825781898.2146,
"hash": "2e3526258a06b3d1d4f4c6432bcb13c2"
},
"index.php": {
"size": 3695,
"mtime": 1777825781898.2146,
"hash": "433ba96ca2ecb0e280915a01d27ac190"
},
"lib/activation.php": {
"size": 7278,
"mtime": 1777825781899.7202,
"hash": "a57c588d45ad1b89e29b8bb489db43eb"
},
"lib/class-acf.php": {
"size": 1361,
"mtime": 1777825781900.2366,
"hash": "449906c43d7b6c3c3b3a09475e7d725e"
},
"lib/class-breadcrumbs.php": {
"size": 14272,
"mtime": 1777825781900.2366,
"hash": "4de39580babb14c094ca4c56768e7bab"
},
"lib/class-enqueue.php": {
"size": 4076,
"mtime": 1777825781901.2432,
"hash": "45fac2122b6afa64b814b170dcb2b30d"
},
"lib/class-menuitems.php": {
"size": 4658,
"mtime": 1777825781901.2432,
"hash": "fd0c0e87ddfcfa68ec59e0f15b50a69a"
},
"lib/class-resources.php": {
"size": 3910,
"mtime": 1777825781902.1833,
"hash": "32a8fe6eec6dd9eb29af7e367893b0de"
},
"lib/extras.php": {
"size": 6860,
"mtime": 1777825781902.1833,
"hash": "7adc58c4c81579ac00ca69c5d04e7fac"
},
"lib/helpers.php": {
"size": 6680,
"mtime": 1777825781903.1887,
"hash": "60d1207517fb0da64403cf1b7dbb6539"
},
"lib/hooks.php": {
"size": 7439,
"mtime": 1777825781903.1887,
"hash": "0f3de261772dc2bf2b5953b2c28b4005"
},
"lib/search-features.php": {
"size": 3183,
"mtime": 1777825781903.7036,
"hash": "6440cdd4de9075dc69324f9cf7930b6f"
},
"lib/show-template.php": {
"size": 4595,
"mtime": 1777825781904.219,
"hash": "ecb952d6c204358a73936af2c033d83a"
},
"package.json": {
"size": 1362,
"mtime": 1777825781905.6797,
"hash": "a4e1eac2cfb9895612d80bc21e1939e6"
},
"page.php": {
"size": 778,
"mtime": 1777825781905.6797,
"hash": "6a3fc28312789659b55abc7a32ded8c0"
},
"playwright.config.js": {
"size": 2327,
"mtime": 1777825781905.6797,
"hash": "7bf73735c56c1d2927d6a160f7aaf7fb"
},
"search.php": {
"size": 3850,
"mtime": 1777825781907.687,
"hash": "9e4ae80991d630321ac71ef0cb1d6694"
},
"sidebar-page.php": {
"size": 244,
"mtime": 1777825781907.687,
"hash": "b0373affab0db0d85986f96517639c25"
},
"sidebar.php": {
"size": 168,
"mtime": 1777825781907.687,
"hash": "360467fe7477f49e98e472f3dc4f6955"
},
"single.php": {
"size": 2146,
"mtime": 1777825781908.6858,
"hash": "965c3dee07716fafd73989c903238578"
},
"static/js/admin.js": {
"size": 237,
"mtime": 1777825781910.7087,
"hash": "13ca21b03b0f87a97b393c976fd7e1d4"
},
"static/js/components/backToTop.js": {
"size": 1081,
"mtime": 1777825781910.7087,
"hash": "f158c4c1059fef386165dae93ce3f7b0"
},
"static/js/components/button.js": {
"size": 2888,
"mtime": 1777825781911.7075,
"hash": "34c562742779794ffd99385654924054"
},
"static/js/modules/GetHeaderHeight.js": {
"size": 370,
"mtime": 1777825781911.7075,
"hash": "04e6ab8db754c70f77dfd3c6a9c55946"
},
"static/js/modules/Navigation.js": {
"size": 18649,
"mtime": 1777825781911.7075,
"hash": "1347fd5408738f67d5599c86b17c7d01"
},
"static/js/modules/TagExternalLinks.js": {
"size": 1459,
"mtime": 1777825781911.7075,
"hash": "8f87f5354de0f983a912fda1ecf690dd"
},
"static/js/theme.js": {
"size": 2365,
"mtime": 1777825781913.213,
"hash": "2e6a048774813e1bb6b203e1b3d2e4ca"
},
"style.css": {
"size": 178,
"mtime": 1777825781913.213,
"hash": "2e92dcc1e52546309822b60a46423698"
},
"styles/backend/admin.css": {
"size": 63,
"mtime": 1777825781914.2341,
"hash": "01d28aa008b74cf5218535f7c12c46ee"
},
"styles/backend/editor.css": {
"size": 1467,
"mtime": 1777825781914.2341,
"hash": "5299a07817c81cb4bad10bd194d4415c"
},
"styles/base/break-out.css": {
"size": 621,
"mtime": 1777825781915.3032,
"hash": "a37de9ae25ff01581f1480117ec09556"
},
"styles/base/colors.css": {
"size": 2163,
"mtime": 1777825781915.3032,
"hash": "95de198691c4f6cb41b0873917229493"
},
"styles/base/forms.css": {
"size": 2008,
"mtime": 1777825781915.3032,
"hash": "107aab79fea61c090f8cd48e4f00448d"
},
"styles/base/global.css": {
"size": 1918,
"mtime": 1777825781916.2947,
"hash": "ae8df6bfce807baa3475f3956cb028fc"
},
"styles/base/index.css": {
"size": 205,
"mtime": 1777825781916.2947,
"hash": "ac5dde7d13978b751ff8f42bfb3773f6"
},
"styles/base/misc.css": {
"size": 34,
"mtime": 1777825781916.2947,
"hash": "47e77d13ea40808d5dbe4c6ef32d126b"
},
"styles/base/prose.css": {
"size": 1911,
"mtime": 1777825781916.2947,
"hash": "3efddc6366c6c4fbcd6144875fb6117f"
},
"styles/base/skip-link.css": {
"size": 528,
"mtime": 1777825781917.295,
"hash": "809617c7a5f61b31e6d9e0eae13b4179"
},
"styles/base/typography.css": {
"size": 5219,
"mtime": 1777825781917.295,
"hash": "4fe5505c437c471f557ad5be946dad3c"
},
"styles/blocks/buttons.css": {
"size": 6260,
"mtime": 1777825781918.432,
"hash": "f4cba12a016e9e30fa7a24a5b7715c56"
},
"styles/blocks/core.css": {
"size": 103,
"mtime": 1777825781918.432,
"hash": "6bcbd78bf19a67b54627546b33c5d5cd"
},
"styles/blocks/index.css": {
"size": 77,
"mtime": 1777825781918.432,
"hash": "56028790f82e8ccc98c912536aa774f2"
},
"styles/components/breadcrumbs.css": {
"size": 215,
"mtime": 1777825781919.433,
"hash": "5fabf70478264c3865676e9f67cbb9fc"
},
"styles/components/index.css": {
"size": 205,
"mtime": 1777825781919.433,
"hash": "a1261bd940ead1cbcdde91c4170dc2c6"
},
"styles/components/pagination.css": {
"size": 1039,
"mtime": 1777825781920.4336,
"hash": "2ae9c16d59f4cab33a99df3065d61670"
},
"styles/components/post-list.css": {
"size": 598,
"mtime": 1777825781920.4336,
"hash": "f7f37b20749734761de3be0d6be2e282"
},
"styles/components/sidebar.css": {
"size": 505,
"mtime": 1777825781920.4336,
"hash": "b12c0335ba1e3fac4b3787675d8a6212"
},
"styles/components/site-footer.css": {
"size": 825,
"mtime": 1777825781921.4446,
"hash": "9c1d4b76f87f60cff9efa3f4b3735836"
},
"styles/components/site-header.css": {
"size": 369,
"mtime": 1777825781921.4446,
"hash": "9133b9bf75dab0c1cfc3c7cb367f867a"
},
"styles/fonts/lineicons.css": {
"size": 45564,
"mtime": 1777825781930.8862,
"hash": "e452d71b3ef8171cf944cd98e08fdc34"
},
"styles/navigation/index.css": {
"size": 1109,
"mtime": 1777825781931.898,
"hash": "28ddb2adae05fc7e68a3e60b2b1665e5"
},
"styles/navigation/nav-aux.css": {
"size": 893,
"mtime": 1777825781932.8987,
"hash": "ea8dcd8a588e5df2b1a45158ad661a47"
},
"styles/navigation/nav-footer.css": {
"size": 2117,
"mtime": 1777825781933.9001,
"hash": "8c7b0110320476f715805d325f08840a"
},
"styles/navigation/nav-functional.css": {
"size": 2272,
"mtime": 1777825781933.9001,
"hash": "afe257894f4d65a67e39ce2973cd2706"
},
"styles/navigation/nav-main-default.css": {
"size": 1638,
"mtime": 1777825781933.9001,
"hash": "96cf7a64c5f0e9bfe812f17a68f9b805"
},
"styles/navigation/nav-main-mega.css": {
"size": 2880,
"mtime": 1777825781935.4058,
"hash": "aa1d27e4635d8376be5c3a18d832df73"
},
"styles/navigation/nav-mobile-accordion.css": {
"size": 1368,
"mtime": 1777825781935.4058,
"hash": "761cfa36b712e142edac8b8fc877fd8d"
},
"styles/navigation/nav-mobile-sliding.css": {
"size": 3700,
"mtime": 1777825781936.4126,
"hash": "82fac7165c53b9cf670b96f29de109ac"
},
"styles/theme.css": {
"size": 519,
"mtime": 1777825781936.4126,
"hash": "95ea2ebd0ca96908f9091594935e0344"
},
"tests/site-a11y.spec.js": {
"size": 2066,
"mtime": 1777825781937.4146,
"hash": "4f080be14808e2da3d5b0cb220dba1f2"
},
"theme.json": {
"size": 6054,
"mtime": 1777825781937.4146,
"hash": "2a0fbef9becf6301f529a6153b688f6f"
},
"views/blocks/accordion/accordion.css": {
"size": 1528,
"mtime": 1777825781938.4128,
"hash": "56f033d708d93ad79c41c2c74c4132d2"
},
"views/blocks/accordion/accordion.php": {
"size": 1585,
"mtime": 1777825781938.4128,
"hash": "71463047c491068471355e5cb638ba6c"
},
"views/blocks/accordion/block.json": {
"size": 536,
"mtime": 1777825781939.9185,
"hash": "7a1add0f62b40208b5c4b80bcfabe92d"
},
"views/blocks/boilerplate/block.json": {
"size": 595,
"mtime": 1777825781940.9243,
"hash": "6b87816fdbd0bdfd69c9fcbbd69247d8"
},
"views/blocks/boilerplate/boilerplate.css": {
"size": 0,
"mtime": 1777825781940.9243,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/boilerplate/boilerplate.php": {
"size": 511,
"mtime": 1777825781941.8308,
"hash": "1a95084b5da0e23e9be4245c510e52e2"
},
"views/blocks/button/block.json": {
"size": 453,
"mtime": 1777825781941.8308,
"hash": "cd5d1611c7cc5de7d6e295693f3fa372"
},
"views/blocks/button/button.php": {
"size": 1492,
"mtime": 1777825781942.8354,
"hash": "84e2ddbc1ff1d2ddbcc38984adfa6df1"
},
"views/blocks/buttons/block.json": {
"size": 481,
"mtime": 1777825781942.8354,
"hash": "94cf5b9d7bf6a47efa9da9a29041dadd"
},
"views/blocks/buttons/buttons.php": {
"size": 506,
"mtime": 1777825781942.8354,
"hash": "de91ee9a77d5a81f8db4b919b43b5f0d"
},
"views/blocks/contact-info/block.json": {
"size": 636,
"mtime": 1777825781944.3481,
"hash": "2229315da64e61c2b793eae04e74710d"
},
"views/blocks/contact-info/contact-info.css": {
"size": 0,
"mtime": 1777825781944.3481,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/contact-info/contact-info.php": {
"size": 1605,
"mtime": 1777825781945.8645,
"hash": "0356348ae30b343a109fae42e2c0b533"
},
"views/blocks/grid-cell/block.json": {
"size": 520,
"mtime": 1777825781946.87,
"hash": "125ff116a0ea042fbfb5639104f42df4"
},
"views/blocks/grid-cell/grid-cell.css": {
"size": 0,
"mtime": 1777825781946.87,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/grid-cell/grid-cell.php": {
"size": 1020,
"mtime": 1777825781946.87,
"hash": "dcc8c272645da336a4090034e6963794"
},
"views/blocks/grid/block.json": {
"size": 513,
"mtime": 1777825781946.87,
"hash": "754d826d448aace6e2a5ff83a9bc4e8e"
},
"views/blocks/grid/grid.css": {
"size": 0,
"mtime": 1777825781948.7903,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/grid/grid.php": {
"size": 1139,
"mtime": 1777825781948.7903,
"hash": "c6d1d48d35dd122b21eff6fb1c64d06e"
},
"views/blocks/homepage-hero/block.json": {
"size": 541,
"mtime": 1777825781949.7954,
"hash": "6129c6269cc9d03d0bbbfbc89a508712"
},
"views/blocks/homepage-hero/homepage-hero.css": {
"size": 0,
"mtime": 1777825781949.7954,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/homepage-hero/homepage-hero.php": {
"size": 1926,
"mtime": 1777825781950.797,
"hash": "ab4084346343efab9c7ea8b039543194"
},
"views/blocks/media-text-innerblocks/block.json": {
"size": 669,
"mtime": 1777825781950.797,
"hash": "9bd57859917b5ecabf25dca938de0468"
},
"views/blocks/media-text-innerblocks/media-text-innerblocks.css": {
"size": 0,
"mtime": 1777825781951.796,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/media-text-innerblocks/media-text-innerblocks.php": {
"size": 1848,
"mtime": 1777825781951.796,
"hash": "657cfdbb55232c469a910021fe09892b"
},
"views/blocks/media-text/block.json": {
"size": 611,
"mtime": 1777825781951.796,
"hash": "3393eda2493e5f58ee720a0582c99f5c"
},
"views/blocks/media-text/media-text.css": {
"size": 0,
"mtime": 1777825781951.796,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/media-text/media-text.php": {
"size": 3574,
"mtime": 1777825781953.3013,
"hash": "f90e05790f9213186f4bdd1bdfe0b96f"
},
"views/blocks/page-children/block.json": {
"size": 606,
"mtime": 1777825781953.3013,
"hash": "188a5891ee40fd21ad29718370aedabf"
},
"views/blocks/page-children/page-children.css": {
"size": 0,
"mtime": 1777825781954.3088,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/page-children/page-children.php": {
"size": 5987,
"mtime": 1777825781954.3088,
"hash": "fe92977dce68904fb4bc06c54ff3e446"
},
"views/blocks/section/block.json": {
"size": 485,
"mtime": 1777825781954.3088,
"hash": "73a372aac3416824d5ef23db34d091bf"
},
"views/blocks/section/section.css": {
"size": 0,
"mtime": 1777825781954.3088,
"hash": "d41d8cd98f00b204e9800998ecf8427e"
},
"views/blocks/section/section.php": {
"size": 2095,
"mtime": 1777825781955.8137,
"hash": "6e4504fd83601eb01a1f3eb873156d2f"
},
"views/components/menu-items/has-children.php": {
"size": 2813,
"mtime": 1777825781955.8137,
"hash": "1a8aa09cd21c8db30d1463a6250dc3b6"
},
"views/components/menu-items/index.php": {
"size": 935,
"mtime": 1777825781956.8318,
"hash": "526811dd0098d380edcebfcef1621e32"
},
"views/components/menu-items/single.php": {
"size": 1021,
"mtime": 1777825781956.8318,
"hash": "64be46dbd08d637d19a322e860ed8ea1"
},
"views/components/nav-aux.php": {
"size": 1043,
"mtime": 1777825781956.8318,
"hash": "0ed85cb990d7b3ae31c730723a4d6e74"
},
"views/components/nav-main.php": {
"size": 548,
"mtime": 1777825781957.8252,
"hash": "7a9fe22a0083b29d18f2dbc32077e64e"
},
"views/components/nav-main__toggle.php": {
"size": 1499,
"mtime": 1777825781958.3442,
"hash": "52bdc7efc28113c2352436618c2708f3"
},
"views/forms/search.php": {
"size": 1561,
"mtime": 1777825781958.3442,
"hash": "556adef0c6550114a3ddd7d5c5cfc39a"
},
"views/icons/facebook.php": {
"size": 31,
"mtime": 1777825781959.3416,
"hash": "aab70d132f1217d1518620198545fd51"
},
"views/icons/heart.php": {
"size": 481,
"mtime": 1777825781959.3416,
"hash": "a072424d8c330d8b39966d1a53b23c69"
},
"views/icons/instagram.php": {
"size": 32,
"mtime": 1777825781959.3416,
"hash": "419d4db42de56eb157b95c95e41b9652"
},
"views/icons/linkedin.php": {
"size": 31,
"mtime": 1777825781960.341,
"hash": "331b0e87d54b8463cfa8f23552823b8f"
},
"views/icons/menu.php": {
"size": 46,
"mtime": 1777825781960.341,
"hash": "ea55de11ec126433429a0c2ee4cfa165"
},
"views/icons/pinterest.php": {
"size": 32,
"mtime": 1777825781960.341,
"hash": "c7e3c2d8d92d5c3874bbd759bfc1b650"
},
"views/icons/search.php": {
"size": 592,
"mtime": 1777825781961.3496,
"hash": "e1dd2e58f826f18f93685d20f45fdcd9"
},
"views/icons/shop.php": {
"size": 27,
"mtime": 1777825781961.3496,
"hash": "760cac61de143a536417225f2aefbf42"
},
"views/icons/shopping-basket.php": {
"size": 803,
"mtime": 1777825781961.3496,
"hash": "5d65124138a3401017a894524361a06b"
},
"views/icons/twitter-.php": {
"size": 30,
"mtime": 1777825781962.3413,
"hash": "6c7604c7c0a3f98479668136cf4c7c8a"
},
"views/icons/twitter.php": {
"size": 24,
"mtime": 1777825781962.3413,
"hash": "c5aa48dfdbc559246297e2efc64659ca"
},
"views/icons/user.php": {
"size": 580,
"mtime": 1777825781962.3413,
"hash": "e0d22c3cde5a1b62db6fbd390cca62d2"
},
"views/icons/youtube.php": {
"size": 30,
"mtime": 1777825781962.3413,
"hash": "4b470494537d81f6b16874a639d957fd"
},
"views/partials/page-hero.php": {
"size": 1582,
"mtime": 1777825781963.5125,
"hash": "e58b6957a66d7e8ff200390630110abb"
},
"views/partials/social-media.php": {
"size": 1378,
"mtime": 1777825781963.5125,
"hash": "e9e66dfe0edd982394ca30bdcc5cc93e"
},
"whitelist.php": {
"size": 4636,
"mtime": 1777825781964.5107,
"hash": "ffaf553fec77c8899fed05522dc2102c"
}
}
File diff suppressed because it is too large Load Diff
-6
View File
@@ -1,6 +0,0 @@
{
"lastAnalyzedAt": "2026-05-03T17:58:02.312Z",
"gitCommitHash": "7a578c67c0c0eec7abbe4ad40a01db0e4c67aeb7",
"version": "1.0.0",
"analyzedFiles": 142
}
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Page Not Found * Page Not Found
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
get_header(); get_header();
?> ?>
+19 -20
View File
@@ -1,14 +1,13 @@
# VDI WordPress Theme Starter v5 # SoloFrame Evo
VDI WordPress Theme Starter v5 is a minimal WordPress theme designed as a starting point for custom theme development. It focuses on modern development approaches with a lean architecture that avoids the overhead of theme frameworks. SoloFrame Evo is a minimal WordPress theme designed as a starting point for custom theme development. It focuses on modern development approaches with a lean architecture that avoids the overhead of theme frameworks.
Repo: [https://github.com/Vincent-Design-Inc/VDI-Starter-v5](https://github.com/Vincent-Design-Inc/VDI-Starter-v5) Repo: [https://github.com/ksolomon/SoloFrame-Evo](https://github.com/ksolomon/SoloFrame-Evo)
AC Bug/Issue Tracking: [https://next-app.activecollab.com/119590/projects/4553?modal=Task-98192-4553](https://next-app.activecollab.com/119590/projects/4553?modal=Task-98192-4553)
## Key Features ## Key Features
- Tailwind CSS v4 (CSS-first configuration, no `tailwind.config.js`) - Tailwind CSS v4 (CSS-first configuration, no `tailwind.config.js`)
- Namespaced PHP (`BasicWP` namespace) for isolation - Namespaced PHP (`SoloFrameEvo` namespace) for isolation
- Built-in support for ACF blocks with auto-registration - Built-in support for ACF blocks with auto-registration
- Fast development workflow with BrowserSync live reload - Fast development workflow with BrowserSync live reload
- WordPress 6.5+ script modules for modern JS loading - WordPress 6.5+ script modules for modern JS loading
@@ -17,7 +16,7 @@ AC Bug/Issue Tracking: [https://next-app.activecollab.com/119590/projects/4553?m
## Documentation ## Documentation
| Guide | Description | | Guide | Description |
|-------|-------------| | ------- | ------------- |
| [Getting Started](docs/getting-started.md) | Setup from zero, local WordPress, environment config, troubleshooting | | [Getting Started](docs/getting-started.md) | Setup from zero, local WordPress, environment config, troubleshooting |
| [Architecture](docs/architecture.md) | Bootstrap flow, layers, namespace conventions, hooks, enqueue system, theme.json | | [Architecture](docs/architecture.md) | Bootstrap flow, layers, namespace conventions, hooks, enqueue system, theme.json |
| [Creating Blocks](docs/creating-blocks.md) | Step-by-step ACF block creation tutorial with examples | | [Creating Blocks](docs/creating-blocks.md) | Step-by-step ACF block creation tutorial with examples |
@@ -25,15 +24,15 @@ AC Bug/Issue Tracking: [https://next-app.activecollab.com/119590/projects/4553?m
## Project Structure ## Project Structure
``` ```plain
VDI-Starter-v5/ SoloFrame-Evo/
├── acf/ # ACF field group JSON definitions ├── acf/ # ACF/SCF field group JSON definitions
├── bin/ # Build scripts (.build.js, .watch.js, .utils.js) ├── bin/ # Build scripts (.build.js, .watch.js, .utils.js)
├── content/ # Sample page and post content for testing ├── content/ # Sample page and post content for testing
├── docs/ # Documentation guides ├── docs/ # Documentation guides
├── lib/ # PHP library files ├── lib/ # PHP library files
│ ├── activation.php # Theme activation handler (plugins, pages, settings) │ ├── activation.php # Theme activation handler (plugins, pages, settings)
│ ├── class-acf.php # ACF integration (JSON sync paths) │ ├── class-acf.php # ACF/SCF integration (JSON sync paths)
│ ├── class-breadcrumbs.php # Breadcrumb generation with Schema.org markup │ ├── class-breadcrumbs.php # Breadcrumb generation with Schema.org markup
│ ├── class-enqueue.php # Assets enqueuing (CSS, JS, fonts) │ ├── class-enqueue.php # Assets enqueuing (CSS, JS, fonts)
│ ├── class-menuitems.php # Navigation menu builder │ ├── class-menuitems.php # Navigation menu builder
@@ -61,7 +60,7 @@ VDI-Starter-v5/
├── tests/ # Automated Playwright tests ├── tests/ # Automated Playwright tests
│ └── site-a11y.spec.js # Site Accessibility tests │ └── site-a11y.spec.js # Site Accessibility tests
├── views/ # Template views ├── views/ # Template views
│ ├── blocks/ # Custom ACF blocks (accordion, button, grid, section, etc.) │ ├── blocks/ # Custom ACF/SCF blocks (accordion, button, grid, section, etc.)
│ ├── icons/ # SVG icon templates │ ├── icons/ # SVG icon templates
│ ├── forms/ # Form templates (search) │ ├── forms/ # Form templates (search)
│ └── partials/ # Reusable template parts (page-hero, social-media) │ └── partials/ # Reusable template parts (page-hero, social-media)
@@ -86,18 +85,18 @@ VDI-Starter-v5/
The project uses several naming conventions. Here's how they relate: The project uses several naming conventions. Here's how they relate:
| Convention | Value | Where Used | | Convention | Value | Where Used |
|-----------|-------|-----------| | ----------- | ------- | ----------- |
| PHP namespace | `BasicWP` | All PHP files | | PHP namespace | `SoloFrameEvo` | All PHP files |
| Text domain | `basicwp` | WordPress translations | | Text domain | `sf-evo` | WordPress translations |
| Block category | `vdi-blocks` | Groups blocks in the editor | | Block category | `sf-blocks` | Groups blocks in the editor |
| Script module IDs | `basicwp-theme`, `basicwp-button`, `basicwp-admin` | JS module registration | | Script module IDs | `sf-evo-theme`, `sf-evo-button`, `sf-evo-admin` | JS module registration |
| WP Engine folder | `vdi-v5` | Deployment target | | WP Engine folder | `<change-me>>` | Deployment target |
| Theme directory | `VDI-Starter-v5` | Git repo name | | Theme directory | `SoloFrame-Evo` | Git repo name |
## Included Blocks ## Included Blocks
| Block | Purpose | | Block | Purpose |
|-------|---------| | ------- | --------- |
| Accordion | Collapsible content sections | | Accordion | Collapsible content sections |
| Buttons | Container for Button blocks | | Buttons | Container for Button blocks |
| Button | Configurable button element (`<x-button>` custom element) | | Button | Configurable button element (`<x-button>` custom element) |
@@ -124,7 +123,7 @@ The project uses several naming conventions. Here's how they relate:
``` ```
4. Copy `.env.example` to `.env` and set: 4. Copy `.env.example` to `.env` and set:
- `LOCALHOST_URL`: Your local development URL (e.g., `http://localhost:1000`) - `LOCALHOST_URL`: Your local development URL (e.g., `http://site-dev.local`)
- `BROWSERSYNC_PORT`: Port for BrowserSync (default: `5000`) - `BROWSERSYNC_PORT`: Port for BrowserSync (default: `5000`)
5. Run the initial build: 5. Run the initial build:
+65 -48
View File
@@ -1,29 +1,46 @@
# Architecture # Architecture
A deep dive into how VDI-Starter-v5 is organized, how it boots, and the conventions it uses. A deep dive into how SoloFrame Evo is organized, how it boots, and the conventions it uses.
## Table of Contents ## Table of Contents
- [Bootstrap Flow](#bootstrap-flow) - [Architecture](#architecture)
- [Architectural Layers](#architectural-layers) - [Table of Contents](#table-of-contents)
- [Namespace Conventions](#namespace-conventions) - [Bootstrap Flow](#bootstrap-flow)
- [Global Variables](#global-variables) - [Architectural Layers](#architectural-layers)
- [WordPress Hooks Cleanup](#wordpress-hooks-cleanup) - [1. Entry Layer](#1-entry-layer)
- [Enqueue System](#enqueue-system) - [2. Service Layer](#2-service-layer)
- [theme.json Design System](#themjson-design-system) - [3. UI Templates and Components](#3-ui-templates-and-components)
- [4. Styling](#4-styling)
- [5. Client Scripts](#5-client-scripts)
- [6. Data Layer](#6-data-layer)
- [7. Infrastructure](#7-infrastructure)
- [Namespace Conventions](#namespace-conventions)
- [Global Variables](#global-variables)
- [WordPress Hooks Cleanup](#wordpress-hooks-cleanup)
- [Enqueue System](#enqueue-system)
- [Frontend (`enqFEAssets()`)](#frontend-enqfeassets)
- [Admin (`enqBEAssets()`)](#admin-enqbeassets)
- [Block Editor (`enqEditorAssets()`)](#block-editor-enqeditorassets)
- [theme.json Design System](#themejson-design-system)
- [Colors](#colors)
- [Typography](#typography)
- [Layout](#layout)
- [Spacing](#spacing)
- [Global Styles](#global-styles)
## Bootstrap Flow ## Bootstrap Flow
When WordPress loads a theme, it starts with `style.css` (for theme metadata) and `functions.php` (for logic). Here's exactly what happens in VDI-Starter-v5: When WordPress loads a theme, it starts with `style.css` (for theme metadata) and `functions.php` (for logic). Here's exactly what happens in SoloFrame Evo:
``` ```plain
WordPress loads the theme WordPress loads the theme
├─ style.css → Theme declaration (name, description, version) ├─ style.css → Theme declaration (name, description, version)
└─ functions.php → Entry point └─ functions.php → Entry point
├─ namespace BasicWP ├─ namespace SoloFrameEvo
├─ glob(__DIR__ . '/lib/*.php') → Autoloads every PHP file in lib/ ├─ glob(__DIR__ . '/lib/*.php') → Autoloads every PHP file in lib/
│ ├─ activation.php → Theme activation handler (runs once) │ ├─ activation.php → Theme activation handler (runs once)
@@ -55,7 +72,7 @@ The theme is organized into seven distinct layers, each with a clear responsibil
The two files WordPress needs to recognize the theme: The two files WordPress needs to recognize the theme:
| File | Purpose | | File | Purpose |
|------|---------| | ------ | --------- |
| `functions.php` | Autoloads `lib/*.php`, registers ACF blocks on `init` | | `functions.php` | Autoloads `lib/*.php`, registers ACF blocks on `init` |
| `style.css` | Theme declaration — name, description, version, author | | `style.css` | Theme declaration — name, description, version, author |
@@ -66,7 +83,7 @@ The two files WordPress needs to recognize the theme:
PHP classes and utility functions in `lib/` that provide core functionality: PHP classes and utility functions in `lib/` that provide core functionality:
| File | Class/Function | Purpose | | File | Class/Function | Purpose |
|------|---------------|---------| | ------ | --------------- | --------- |
| `class-enqueue.php` | `Enqueue` | Loads all frontend CSS, JS, and fonts with cache-busting | | `class-enqueue.php` | `Enqueue` | Loads all frontend CSS, JS, and fonts with cache-busting |
| `class-menuitems.php` | `MenuItems` | Resolves WordPress nav menus into renderable item trees | | `class-menuitems.php` | `MenuItems` | Resolves WordPress nav menus into renderable item trees |
| `class-breadcrumbs.php` | `Breadcrumbs` | Context-aware breadcrumb trails with Schema.org markup | | `class-breadcrumbs.php` | `Breadcrumbs` | Context-aware breadcrumb trails with Schema.org markup |
@@ -86,7 +103,7 @@ WordPress template hierarchy files, ACF blocks, reusable components, and icons:
**Template Hierarchy:** **Template Hierarchy:**
| File | WordPress Template For | | File | WordPress Template For |
|------|----------------------| | ------ | ---------------------- |
| `front-page.php` | The front page | | `front-page.php` | The front page |
| `index.php` | Blog posts listing (fallback for all) | | `index.php` | Blog posts listing (fallback for all) |
| `single.php` | Individual posts | | `single.php` | Individual posts |
@@ -103,7 +120,7 @@ WordPress template hierarchy files, ACF blocks, reusable components, and icons:
Each block follows a consistent three-file pattern: `block.json` (registration) + `{name}.php` (template) + `{name}.css` (styles). Each block follows a consistent three-file pattern: `block.json` (registration) + `{name}.php` (template) + `{name}.css` (styles).
| Block | Purpose | | Block | Purpose |
|-------|---------| | ------- | --------- |
| `accordion` | Collapsible content sections | | `accordion` | Collapsible content sections |
| `boilerplate` | Starting template for new blocks (not registered) | | `boilerplate` | Starting template for new blocks (not registered) |
| `button` | Single configurable button element | | `button` | Single configurable button element |
@@ -120,7 +137,7 @@ Each block follows a consistent three-file pattern: `block.json` (registration)
**Components (in `views/components/`):** **Components (in `views/components/`):**
| Component | Purpose | | Component | Purpose |
|-----------|---------| | ----------- | --------- |
| `nav-aux.php` | Auxiliary navigation bar (social links + search) | | `nav-aux.php` | Auxiliary navigation bar (social links + search) |
| `nav-main.php` | Primary navigation menu | | `nav-main.php` | Primary navigation menu |
| `nav-main__toggle.php` | Mobile menu toggle button | | `nav-main__toggle.php` | Mobile menu toggle button |
@@ -129,7 +146,7 @@ Each block follows a consistent three-file pattern: `block.json` (registration)
**Partials (in `views/partials/`):** **Partials (in `views/partials/`):**
| Partial | Purpose | | Partial | Purpose |
|---------|---------| | --------- | --------- |
| `page-hero.php` | Page hero section | | `page-hero.php` | Page hero section |
| `social-media.php` | Social media links | | `social-media.php` | Social media links |
@@ -141,7 +158,7 @@ SVG icon partials for Facebook, Instagram, LinkedIn, Pinterest, Twitter, YouTube
CSS is organized as a layered cascade, managed through Tailwind CSS v4: CSS is organized as a layered cascade, managed through Tailwind CSS v4:
``` ```plain
styles/theme.css ← Entry point (imports everything below) styles/theme.css ← Entry point (imports everything below)
├── @import "tailwindcss" ← Tailwind CSS v4 base ├── @import "tailwindcss" ← Tailwind CSS v4 base
├── @import "./base/index.css" ← Base styles barrel file ├── @import "./base/index.css" ← Base styles barrel file
@@ -183,7 +200,7 @@ styles/theme.css ← Entry point (imports everything below)
JavaScript modules loaded via WordPress's `wp_enqueue_script_module()` API (requires WordPress 6.5+): JavaScript modules loaded via WordPress's `wp_enqueue_script_module()` API (requires WordPress 6.5+):
``` ```plain
static/js/theme.js (entry point for frontend) static/js/theme.js (entry point for frontend)
├── Navigation.js → Mobile menu, sliding viewport, keyboard nav ├── Navigation.js → Mobile menu, sliding viewport, keyboard nav
├── backToTop.js → BackToTopButton custom element ├── backToTop.js → BackToTopButton custom element
@@ -195,7 +212,7 @@ static/js/admin.js (entry point for editor)
└── button.js → ButtonComponent for editor context └── button.js → ButtonComponent for editor context
``` ```
**How script modules work:** WordPress's `wp_enqueue_script_module()` creates proper ES module dependencies. The `Enqueue` class registers `basicwp-theme` (theme.js) as a root module, and `basicwp-button` (button.js) declares a dependency on it. This means button.js won't load until theme.js has loaded — no more manual script ordering. **How script modules work:** WordPress's `wp_enqueue_script_module()` creates proper ES module dependencies. The `Enqueue` class registers `sf-evo-theme` (theme.js) as a root module, and `sf-evo-button` (button.js) declares a dependency on it. This means button.js won't load until theme.js has loaded — no more manual script ordering.
**Passive event listener polyfill:** `theme.js` includes a polyfill that makes scroll, touch, and mouse event listeners passive by default. This improves scrolling performance without requiring `addEventListener(..., { passive: true })` on every listener. **Passive event listener polyfill:** `theme.js` includes a polyfill that makes scroll, touch, and mouse event listeners passive by default. This improves scrolling performance without requiring `addEventListener(..., { passive: true })` on every listener.
@@ -203,10 +220,10 @@ static/js/admin.js (entry point for editor)
### 6. Data Layer ### 6. Data Layer
ACF field group JSON files in the `acf/` directory: SCF/ACF field group JSON files in the `acf/` directory:
| File | Block/Feature | | File | Block/Feature |
|------|-------------| | ------ | ------------- |
| `group_5f7f85a2a3e13.json` | Accordion block fields | | `group_5f7f85a2a3e13.json` | Accordion block fields |
| `group_5fd3e006e5da5.json` | Global Fields (site-wide contact, social, footer settings) | | `group_5fd3e006e5da5.json` | Global Fields (site-wide contact, social, footer settings) |
| `group_600f5a9e242c3.json` | Grid block fields | | `group_600f5a9e242c3.json` | Grid block fields |
@@ -218,6 +235,7 @@ ACF field group JSON files in the `acf/` directory:
| `group_645e7cf448e66.json` | Contact Info block fields | | `group_645e7cf448e66.json` | Contact Info block fields |
**Why JSON sync?** The `ACF` class in `class-acf.php` sets custom save/load paths so that field groups created in the WordPress admin are automatically saved as JSON files. This means: **Why JSON sync?** The `ACF` class in `class-acf.php` sets custom save/load paths so that field groups created in the WordPress admin are automatically saved as JSON files. This means:
- Field group configurations are version-controlled in Git - Field group configurations are version-controlled in Git
- Field groups survive database resets - Field groups survive database resets
- Multiple environments stay in sync - Multiple environments stay in sync
@@ -228,7 +246,7 @@ ACF field group JSON files in the `acf/` directory:
Build, CI/CD, and configuration files that support development and deployment: Build, CI/CD, and configuration files that support development and deployment:
| File | Purpose | | File | Purpose |
|------|---------| | ------ | --------- |
| `bin/.build.js` | Production build script — compiles Tailwind CSS with `--optimize` | | `bin/.build.js` | Production build script — compiles Tailwind CSS with `--optimize` |
| `bin/.watch.js` | Development server — BrowserSync with live reload | | `bin/.watch.js` | Development server — BrowserSync with live reload |
| `bin/.utils.js` | Shared utilities for build scripts (`tailwindToCSS`, debounce) | | `bin/.utils.js` | Shared utilities for build scripts (`tailwindToCSS`, debounce) |
@@ -248,15 +266,13 @@ Build, CI/CD, and configuration files that support development and deployment:
The project uses several naming conventions that can be confusing at first: The project uses several naming conventions that can be confusing at first:
| Convention | Value | Where Used | | Convention | Value | Where Used |
|-----------|-------|-----------| | ----------- | ------- | ----------- |
| PHP namespace | `BasicWP` | All PHP files use `namespace BasicWP;` | | PHP namespace | `SoloFrameEvo` | All PHP files use `namespace SoloFrameEvo;` |
| Text domain | `basicwp` | WordPress translation functions (`__()` , `_e()`) | | Text domain | `sf-evo` | WordPress translation functions (`__()` , `_e()`) |
| Block category | `vdi-blocks` | Groups custom blocks in the editor (defined in `helpers.php::blockCategories()`) | | Block category | `sf-blocks` | Groups custom blocks in the editor (defined in `helpers.php::blockCategories()`) |
| Script module IDs | `basicwp-theme`, `basicwp-button`, `basicwp-admin` | JavaScript module registration in `class-enqueue.php` | | Script module IDs | `sf-evo-theme`, `sf-evo-button`, `sf-evo-admin` | JavaScript module registration in `class-enqueue.php` |
| WP Engine folder | `vdi-v5` | Deployment target in `.github/workflows/wpengine.yml` | | WP Engine folder | `soloframe-evo` | Deployment target in `.github/workflows/wpengine.yml` |
| Git repo name | `VDI-Starter-v5` | The repository and theme directory name | | Git repo name | `SoloFrame-Evo` | The repository and theme directory name |
**The story:** "VDI" is Vincent Design Inc., the agency. "BasicWP" was the original internal code name. "vdi-blocks" and "vdi-v5" are deployment-facing names that align with the client's branding. They all refer to the same theme — just used in different contexts.
## Global Variables ## Global Variables
@@ -264,13 +280,14 @@ Two global variables are defined in `helpers.php`:
```php ```php
global $theme, $views; global $theme, $views;
$theme = get_template_directory(); // e.g., /var/www/wp-content/themes/VDI-Starter-v5 $theme = get_template_directory(); // e.g., /var/www/wp-content/themes/SoloFrame Evo
$views = $theme . '/views'; // e.g., /var/www/wp-content/themes/VDI-Starter-v5/views $views = $theme . '/views'; // e.g., /var/www/wp-content/themes/SoloFrame Evo/views
``` ```
**`$theme`** — Absolute path to the theme directory. Used when including files that need the full server path. **`$theme`** — Absolute path to the theme directory. Used when including files that need the full server path.
**`$views`** — Absolute path to the views directory. Used by `MenuItems::render()` to include navigation templates: **`$views`** — Absolute path to the views directory. Used by `MenuItems::render()` to include navigation templates:
```php ```php
include $views . '/components/menu-items/index.php'; include $views . '/components/menu-items/index.php';
``` ```
@@ -284,7 +301,7 @@ The `init()` function in `hooks.php` runs on every page load at priority 1. It p
**What gets removed:** **What gets removed:**
| What | Why | | What | Why |
|------|-----| | ------ | ----- |
| Emoji detection scripts & styles | Most sites don't use WordPress emojis; they add ~10KB to every page | | Emoji detection scripts & styles | Most sites don't use WordPress emojis; they add ~10KB to every page |
| `wp-block-library` styles | Theme provides its own block styles; core defaults add ~100KB | | `wp-block-library` styles | Theme provides its own block styles; core defaults add ~100KB |
| `global-styles` & `core-block-styles` | Theme overrides these via `theme.json` and custom CSS | | `global-styles` & `core-block-styles` | Theme overrides these via `theme.json` and custom CSS |
@@ -304,7 +321,7 @@ The `init()` function in `hooks.php` runs on every page load at priority 1. It p
**What gets added:** **What gets added:**
| Feature | Why | | Feature | Why |
|---------|-----| | --------- | ----- |
| `post-thumbnails` | Featured image support | | `post-thumbnails` | Featured image support |
| `title-tag` | WordPress manages `<title>` tag | | `title-tag` | WordPress manages `<title>` tag |
| `html5` (caption, comment-form, comment-list, gallery, search-form, script, style) | Modern HTML5 markup | | `html5` (caption, comment-form, comment-list, gallery, search-form, script, style) | Modern HTML5 markup |
@@ -323,32 +340,32 @@ The `Enqueue` class (in `class-enqueue.php`) manages all asset loading:
### Frontend (`enqFEAssets()`) ### Frontend (`enqFEAssets()`)
| Asset | Method | Notes | | Asset | Method | Notes |
|-------|--------|-------| | ------- | -------- | ------- |
| `static/dist/theme.css` | `wp_enqueue_style()` | Compiled Tailwind CSS, cache-busted with `filemtime()` | | `static/dist/theme.css` | `wp_enqueue_style()` | Compiled Tailwind CSS, cache-busted with `filemtime()` |
| Raleway font | `wp_enqueue_style()` | Google Fonts with `preconnect` hint | | Raleway font | `wp_enqueue_style()` | Google Fonts with `preconnect` hint |
| `basicwp-theme` (theme.js) | `wp_enqueue_script_module()` | Frontend entry point | | `sf-evo-theme` (theme.js) | `wp_enqueue_script_module()` | Frontend entry point |
| `basicwp-button` (button.js) | `wp_enqueue_script_module()` | Depends on `basicwp-theme` | | `sf-evo-button` (button.js) | `wp_enqueue_script_module()` | Depends on `sf-evo-theme` |
| jQuery | `wp_enqueue_script()` | Needed by downstream scripts; modules can't depend on classic scripts | | jQuery | `wp_enqueue_script()` | Needed by downstream scripts; modules can't depend on classic scripts |
### Admin (`enqBEAssets()`) ### Admin (`enqBEAssets()`)
| Asset | Method | Notes | | Asset | Method | Notes |
|-------|--------|-------| | ------- | -------- | ------- |
| Raleway font | `wp_enqueue_style()` | Same Google Fonts | | Raleway font | `wp_enqueue_style()` | Same Google Fonts |
| `styles/backend/admin.css` | `wp_enqueue_style()` | Admin-specific overrides | | `styles/backend/admin.css` | `wp_enqueue_style()` | Admin-specific overrides |
| `basicwp-admin` (admin.js) | `wp_enqueue_script_module()` | Admin entry point | | `sf-evo-admin` (admin.js) | `wp_enqueue_script_module()` | Admin entry point |
| `basicwp-button` (button.js) | `wp_enqueue_script_module()` | Depends on `basicwp-admin` | | `sf-evo-button` (button.js) | `wp_enqueue_script_module()` | Depends on `sf-evo-admin` |
### Block Editor (`enqEditorAssets()`) ### Block Editor (`enqEditorAssets()`)
| Asset | Method | Notes | | Asset | Method | Notes |
|-------|--------|-------| | ------- | -------- | ------- |
| Raleway font | `wp_enqueue_style()` | Same Google Fonts | | Raleway font | `wp_enqueue_style()` | Same Google Fonts |
| `styles/backend/editor.css` | `wp_enqueue_style()` | Editor-specific styles, scoped to block editor | | `styles/backend/editor.css` | `wp_enqueue_style()` | Editor-specific styles, scoped to block editor |
**Cache busting:** All enqueued files use `filemtime()` as the version number. This means the browser cache is automatically busted whenever a file changes — no manual version bumps needed. **Cache busting:** All enqueued files use `filemtime()` as the version number. This means the browser cache is automatically busted whenever a file changes — no manual version bumps needed.
**Script modules:** The theme uses `wp_enqueue_script_module()` (WordPress 6.5+) instead of traditional `wp_enqueue_script()` for frontend and admin JavaScript. This creates proper ES module dependencies where `basicwp-button` won't load until `basicwp-theme` has loaded. **Script modules:** The theme uses `wp_enqueue_script_module()` (WordPress 6.5+) instead of traditional `wp_enqueue_script()` for frontend and admin JavaScript. This creates proper ES module dependencies where `sf-evo-button` won't load until `sf-evo-theme` has loaded.
## theme.json Design System ## theme.json Design System
@@ -359,7 +376,7 @@ The `theme.json` file (WordPress block editor v3 schema) defines the design syst
Colors are defined as CSS custom properties and mapped to WordPress editor slugs: Colors are defined as CSS custom properties and mapped to WordPress editor slugs:
| Editor Slug | CSS Variable | Purpose | | Editor Slug | CSS Variable | Purpose |
|------------|-------------|---------| | ------------ | ------------- | --------- |
| `black` | `#000` | Pure black | | `black` | `#000` | Pure black |
| `white` | `#fff` | Pure white | | `white` | `#fff` | Pure white |
| `theme-bg` | `var(--color-background)` | Page background | | `theme-bg` | `var(--color-background)` | Page background |
@@ -380,7 +397,7 @@ The actual color values for the CSS variables are defined in `styles/base/colors
One font family (`var(--font-sans)`) and 15 size presets: One font family (`var(--font-sans)`) and 15 size presets:
| Slug | Variable | Typical Use | | Slug | Variable | Typical Use |
|------|----------|-------------| | ------ | ---------- | ------------- |
| `base` | `var(--text-base)` | Body text | | `base` | `var(--text-base)` | Body text |
| `text-14px` | `var(--text-14px)` | Small text | | `text-14px` | `var(--text-14px)` | Small text |
| `text-16px` | `var(--text-16px)` | Standard text | | `text-16px` | `var(--text-16px)` | Standard text |
@@ -400,7 +417,7 @@ One font family (`var(--font-sans)`) and 15 size presets:
### Layout ### Layout
| Property | Value | Meaning | | Property | Value | Meaning |
|----------|-------|---------| | ---------- | ------- | --------- |
| `contentSize` | `100%` | Default content width (full-width by default) | | `contentSize` | `100%` | Default content width (full-width by default) |
| `wideSize` | `1536px` | Wide-alignment max width | | `wideSize` | `1536px` | Wide-alignment max width |
@@ -411,7 +428,7 @@ Available units: `px`, `em`, `rem`, `vh`, `vw`, `%`
### Global Styles ### Global Styles
| Property | Value | | Property | Value |
|----------|-------| | ---------- | ------- |
| Background | `var(--wp--preset--color--background)` | | Background | `var(--wp--preset--color--background)` |
| Text color | `var(--wp--preset--color--text)` | | Text color | `var(--wp--preset--color--text)` |
| Link color | `var(--wp--preset--color--theme-bodylinks)` | | Link color | `var(--wp--preset--color--theme-bodylinks)` |
+83 -59
View File
@@ -1,40 +1,55 @@
# Creating Blocks in VDI-Starter-v5 # Creating Blocks in SoloFrame Evo
## Table of Contents ## Table of Contents
- [Overview](#overview) - [Creating Blocks in SoloFrame Evo](#creating-blocks-in-soloframe-evo)
- [How Block Registration Works](#how-block-registration-works) - [Table of Contents](#table-of-contents)
- [Block Anatomy: The Three-File Pattern](#block-anatomy-the-three-file-pattern) - [Overview](#overview)
- [How Block Registration Works](#how-block-registration-works)
- [Block Anatomy: The Three-File Pattern](#block-anatomy-the-three-file-pattern)
- [block.json -- The Registration Manifest](#blockjson----the-registration-manifest) - [block.json -- The Registration Manifest](#blockjson----the-registration-manifest)
- [The PHP Template -- Rendering the Block](#the-php-template----rendering-the-block) - [The PHP Template -- Rendering the Block](#the-php-template----rendering-the-block)
- [The CSS File -- Scoped Styles](#the-css-file----scoped-styles) - [The CSS File -- Scoped Styles](#the-css-file----scoped-styles)
- [Helper Functions](#helper-functions) - [Helper Functions](#helper-functions)
- [blockWrapperAttributes()](#blockwrapperattributes) - [blockWrapperAttributes()](#blockwrapperattributes)
- [getFieldValue()](#getfieldvalue) - [getFieldValue()](#getfieldvalue)
- [escEmbeds()](#escembeds) - [escEmbeds()](#escembeds)
- [ACF Field Groups](#acf-field-groups) - [SCF/ACF Field Groups](#scfacf-field-groups)
- [Parent-Child Block Patterns (InnerBlocks)](#parent-child-block-patterns-innerblocks) - [Creating a Field Group](#creating-a-field-group)
- [Tailwind CSS in Blocks](#tailwind-css-in-blocks) - [JSON Sync](#json-sync)
- [Step-by-Step: Creating a New Block](#step-by-step-creating-a-new-block) - [Parent-Child Block Patterns (InnerBlocks)](#parent-child-block-patterns-innerblocks)
- [Basic InnerBlocks](#basic-innerblocks)
- [Restricted InnerBlocks](#restricted-innerblocks)
- [Enabling InnerBlocks in block.json](#enabling-innerblocks-in-blockjson)
- [Adding Classes to InnerBlocks](#adding-classes-to-innerblocks)
- [Tailwind CSS in Blocks](#tailwind-css-in-blocks)
- [How Tailwind is Set Up](#how-tailwind-is-set-up)
- [Using Tailwind Classes in Blocks](#using-tailwind-classes-in-blocks)
- [Whitelisting Editor-Only Classes](#whitelisting-editor-only-classes)
- [Block-Specific CSS Files](#block-specific-css-files)
- [Step-by-Step: Creating a New Block](#step-by-step-creating-a-new-block)
- [1. Create the Block Directory](#1-create-the-block-directory) - [1. Create the Block Directory](#1-create-the-block-directory)
- [2. Create block.json](#2-create-blockjson) - [2. Create block.json](#2-create-blockjson)
- [3. Create the PHP Template](#3-create-the-php-template) - [3. Create the PHP Template](#3-create-the-php-template)
- [4. Create the CSS File](#4-create-the-css-file) - [4. Create the CSS File](#4-create-the-css-file)
- [5. Create ACF Field Groups in WordPress Admin](#5-create-acf-field-groups-in-wordpress-admin) - [5. Create SCF/ACF Field Groups in WordPress Admin](#5-create-scfacf-field-groups-in-wordpress-admin)
- [6. Build and Verify](#6-build-and-verify) - [6. Build and Verify](#6-build-and-verify)
- [Real-World Examples from This Theme](#real-world-examples-from-this-theme) - [Real-World Examples from This Theme](#real-world-examples-from-this-theme)
- [Simple Block: Homepage Hero](#simple-block-homepage-hero) - [Simple Block: Homepage Hero](#simple-block-homepage-hero)
- [Parent Block with InnerBlocks: Section](#parent-block-with-innerblocks-section) - [Parent Block with InnerBlocks: Section](#parent-block-with-innerblocks-section)
- [Restricted Parent Block: Buttons](#restricted-parent-block-buttons) - [Restricted Parent Block: Buttons](#restricted-parent-block-buttons)
- [Dynamic Parent Block: Grid](#dynamic-parent-block-grid) - [Dynamic Parent Block: Grid](#dynamic-parent-block-grid)
- [Block Using Global Fields: Contact Info](#block-using-global-fields-contact-info) - [Block Using Global Fields: Contact Info](#block-using-global-fields-contact-info)
- [Common Pitfalls and Best Practices](#common-pitfalls-and-best-practices) - [Common Pitfalls and Best Practices](#common-pitfalls-and-best-practices)
- [Do](#do)
- [Do Not](#do-not)
- [Debugging Tips](#debugging-tips)
--- ---
## Overview ## Overview
VDI-Starter-v5 uses Advanced Custom Fields (ACF) blocks to build page content. ACF blocks are a type of WordPress Gutenberg block where the editing interface comes from ACF field groups and the rendering is handled by a PHP template (instead of React). This approach lets you build rich, structured content blocks using familiar PHP templating and Tailwind CSS, without writing JavaScript. SoloFrame Evo uses Secure Custom Fields (SCF) or Advanced Custom Fields (ACF) blocks to build page content. SCF/ACF blocks are a type of WordPress Gutenberg block where the editing interface comes from SCF/ACF field groups and the rendering is handled by a PHP template (instead of React). This approach lets you build rich, structured content blocks using familiar PHP templating and Tailwind CSS, without writing JavaScript.
Every block in this theme follows the same three-file pattern inside `views/blocks/{block-name}/`, and new blocks are automatically discovered and registered -- no manual registration required. Every block in this theme follows the same three-file pattern inside `views/blocks/{block-name}/`, and new blocks are automatically discovered and registered -- no manual registration required.
@@ -74,9 +89,9 @@ Here is what happens:
## Block Anatomy: The Three-File Pattern ## Block Anatomy: The Three-File Pattern
Every ACF block in this theme consists of exactly three files inside `views/blocks/{block-name}/`: Every SCF/ACF block in this theme consists of exactly three files inside `views/blocks/{block-name}/`:
``` ```plain
views/blocks/ views/blocks/
boilerplate/ <-- Template for creating new blocks (not registered) boilerplate/ <-- Template for creating new blocks (not registered)
block.json block.json
@@ -97,15 +112,15 @@ The naming convention is consistent: the directory name, the PHP file, and the C
### block.json -- The Registration Manifest ### block.json -- The Registration Manifest
The `block.json` file tells WordPress and ACF everything they need to know about the block. Here is the boilerplate version: The `block.json` file tells WordPress and SCF/ACF everything they need to know about the block. Here is the boilerplate version:
```json ```json
{ {
"name": "acf/boilerplate", "name": "acf/boilerplate",
"title": "Block Boilerplate", "title": "Block Boilerplate",
"description": "Boilerplate code to create ACF blocks.", "description": "Boilerplate code to create SCF/ACF blocks.",
"style": ["file:./boilerplate.css"], "style": ["file:./boilerplate.css"],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "block-default", "icon": "block-default",
"keywords": ["boilerplate"], "keywords": ["boilerplate"],
"acf": { "acf": {
@@ -127,13 +142,13 @@ The `block.json` file tells WordPress and ACF everything they need to know about
**Field-by-field explanation:** **Field-by-field explanation:**
| Field | Purpose | | Field | Purpose |
|---|---| | --- | --- |
| `name` | The unique block identifier. **Must be prefixed with `acf/`** for ACF blocks. This becomes the machine name WordPress uses internally (e.g., `acf/testimonial`). | | `name` | The unique block identifier. **Must be prefixed with `acf/`** for ACF blocks. This becomes the machine name WordPress uses internally (e.g., `acf/testimonial`). |
| `title` | The human-readable name shown in the block editor inserter (e.g., "Testimonial"). | | `title` | The human-readable name shown in the block editor inserter (e.g., "Testimonial"). |
| `description` | A short description shown in the block editor to help editors understand what the block does. | | `description` | A short description shown in the block editor to help editors understand what the block does. |
| `style` | An array of CSS files to load when this block renders. Use the `file:./` prefix for block-relative paths. WordPress only loads these stylesheets when the block is actually present on the page. | | `style` | An array of CSS files to load when this block renders. Use the `file:./` prefix for block-relative paths. WordPress only loads these stylesheets when the block is actually present on the page. |
| `category` | Determines which section of the inserter the block appears under. **Always use `vdi-blocks`** in this theme -- this is the custom category registered in `helpers.php` that groups all theme blocks together under "VDI Custom Blocks". | | `category` | Determines which section of the inserter the block appears under. **Always use `sf-blocks`** in this theme -- this is the custom category registered in `helpers.php` that groups all theme blocks together under "VDI Custom Blocks". |
| `icon` | A Dashicon name (without the `dashicons-` prefix) shown next to the block in the inserter. Browse available icons at https://developer.wordpress.org/resource/dashicons/. | | `icon` | A Dashicon name (without the `dashicons-` prefix) shown next to the block in the inserter. Browse available icons at [DashIcons](https://developer.wordpress.org/resource/dashicons/). |
| `keywords` | Additional search terms that help editors find the block in the inserter. For example, a "Testimonial" block might include `["testimonial", "quote", "review"]`. | | `keywords` | Additional search terms that help editors find the block in the inserter. For example, a "Testimonial" block might include `["testimonial", "quote", "review"]`. |
| `acf.mode` | Controls how the block appears in the editor. `preview` shows the rendered block output; `edit` shows the ACF field inputs directly. Most blocks use `preview`. | | `acf.mode` | Controls how the block appears in the editor. `preview` shows the rendered block output; `edit` shows the ACF field inputs directly. Most blocks use `preview`. |
| `acf.renderTemplate` | The PHP file that renders the block on the frontend and in preview mode. This filename must match the actual file in the directory. | | `acf.renderTemplate` | The PHP file that renders the block on the frontend and in preview mode. This filename must match the actual file in the directory. |
@@ -150,10 +165,10 @@ The `block.json` file tells WordPress and ACF everything they need to know about
```json ```json
{ {
"name": "acf/buttons", "name": "acf/buttons",
"title": "Buttons (VDI)", "title": "Buttons",
"description": "A button or group of buttons.", "description": "A button or group of buttons.",
"allowedBlocks": ["acf/button"], "allowedBlocks": ["acf/button"],
"category": "vdi-blocks", "category": "sf-blocks",
... ...
} }
``` ```
@@ -169,10 +184,10 @@ The PHP template is responsible for outputting the block's HTML. Every template
* *
* This is the template for building your own custom blocks. * This is the template for building your own custom blocks.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$classes = 'boilerplate'; $classes = 'boilerplate';
@@ -190,7 +205,7 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
**Key elements explained:** **Key elements explained:**
1. **`namespace BasicWP;`** -- Every block template must declare this namespace. It gives you access to the theme's helper functions (`blockWrapperAttributes`, `getFieldValue`, etc.) without needing fully-qualified class names. 1. **`namespace SoloFrameEvo;`** -- Every block template must declare this namespace. It gives you access to the theme's helper functions (`blockWrapperAttributes`, `getFieldValue`, etc.) without needing fully-qualified class names.
2. **`$is_preview`** -- This is a WordPress global variable that is `true` when the block is being rendered inside the block editor, and `false` on the frontend. You can use it to conditionally show editor-only content or adjust markup for the editor. 2. **`$is_preview`** -- This is a WordPress global variable that is `true` when the block is being rendered inside the block editor, and `false` on the frontend. You can use it to conditionally show editor-only content or adjust markup for the editor.
@@ -214,7 +229,7 @@ The CSS filename must match the block slug and be referenced in `block.json` usi
"style": ["file:./testimonial.css"] "style": ["file:./testimonial.css"]
``` ```
You can use Tailwind utility classes directly in your PHP templates (e.g., `class="flex gap-4 p-6"`), and they will work as long as the Tailwind build process can detect them. For complex or block-specific styles that are not expressible as utility classes, write them in the block's CSS file using the BEM-like naming convention: You can use Tailwind utility classes directly in your PHP templates (e.g., `class="flex gap-4 p-6"`), and they will work as long as the Tailwind build process can detect them. For complex or block-specific styles that are not expressible as utility classes, write them in the block's CSS file. You can also use Tailwind's `@apply` directive in these CSS files to compose utility classes into reusable styles:
```css ```css
/* testimonial.css */ /* testimonial.css */
@@ -238,7 +253,7 @@ The file can be empty initially and filled in as needed.
## Helper Functions ## Helper Functions
The theme provides several helper functions in `lib/helpers.php`, all under the `BasicWP` namespace. Because every block template declares `namespace BasicWP;`, you can call these functions directly without any prefix. The theme provides several helper functions in `lib/helpers.php`, all under the `SoloFrameEvo` namespace. Because every block template declares `namespace SoloFrameEvo;`, you can call these functions directly without any prefix.
### blockWrapperAttributes() ### blockWrapperAttributes()
@@ -249,12 +264,14 @@ function blockWrapperAttributes( $classes, $is_preview )
**Purpose:** Generates the HTML attributes string for a block's root element, handling the difference between the editor and the frontend. **Purpose:** Generates the HTML attributes string for a block's root element, handling the difference between the editor and the frontend.
**Parameters:** **Parameters:**
- `$classes` (string) -- A space-separated list of CSS class names to apply to the block wrapper. - `$classes` (string) -- A space-separated list of CSS class names to apply to the block wrapper.
- `$is_preview` (bool) -- Whether the block is being rendered in the editor. Always pass the global `$is_preview` variable. - `$is_preview` (bool) -- Whether the block is being rendered in the editor. Always pass the global `$is_preview` variable.
**Returns:** A string of HTML attributes ready to echo inside an HTML tag. **Returns:** A string of HTML attributes ready to echo inside an HTML tag.
**How it works:** **How it works:**
- When `$is_preview` is `true` (in the editor), it returns `class="my-class"`. This is a simplified output that avoids rendering issues caused by WordPress's `get_block_wrapper_attributes()` in the editor context. - When `$is_preview` is `true` (in the editor), it returns `class="my-class"`. This is a simplified output that avoids rendering issues caused by WordPress's `get_block_wrapper_attributes()` in the editor context.
- When `$is_preview` is `false` (on the frontend), it calls WordPress's `get_block_wrapper_attributes()` with your classes merged in, producing the full set of attributes including alignment classes, anchor IDs, custom class names from the editor, and more. - When `$is_preview` is `false` (on the frontend), it calls WordPress's `get_block_wrapper_attributes()` with your classes merged in, producing the full set of attributes including alignment classes, anchor IDs, custom class names from the editor, and more.
@@ -280,6 +297,7 @@ function getFieldValue( $field_path )
**Purpose:** Retrieves nested values from ACF option fields (Global Fields) using dot notation. **Purpose:** Retrieves nested values from ACF option fields (Global Fields) using dot notation.
**Parameters:** **Parameters:**
- `$field_path` (string) -- A dot-notated path to the value. For example, `'contact_info.phone'` retrieves the `phone` subfield from the `contact_info` options page field. - `$field_path` (string) -- A dot-notated path to the value. For example, `'contact_info.phone'` retrieves the `phone` subfield from the `contact_info` options page field.
**Returns:** The value at the specified path, or an empty string if the path does not exist. **Returns:** The value at the specified path, or an empty string if the path does not exist.
@@ -314,7 +332,7 @@ echo wp_kses( $video_embed_html, escEmbeds() );
--- ---
## ACF Field Groups ## SCF/ACF Field Groups
After creating your block's three files, you need to create an ACF field group in the WordPress admin. This defines the fields that editors fill in when editing the block. After creating your block's three files, you need to create an ACF field group in the WordPress admin. This defines the fields that editors fill in when editing the block.
@@ -331,12 +349,12 @@ After creating your block's three files, you need to create an ACF field group i
- **Repeater** -- Repeatable groups of fields (for lists, slides, etc.) - **Repeater** -- Repeatable groups of fields (for lists, slides, etc.)
- **Link** -- URL + title + target picker - **Link** -- URL + title + target picker
- **WYSIWYG** -- Rich text editor - **WYSIWYG** -- Rich text editor
4. Set the **location rule** to: **Block > is equal to > [Your Block Name]**. This tells ACF to show these fields when editing your block. 4. Set the **location rule** to: **Block > is equal to > [Your Block Name]**. This tells SCF/ACF to show these fields when editing your block.
5. Click **Save** or **Publish**. 5. Click **Save** or **Publish**.
### JSON Sync ### JSON Sync
The theme's `ACF` class (in `lib/class-acf.php`) configures custom save and load paths for ACF JSON: The theme's `ACF` class (in `lib/class-acf.php`) configures custom save and load paths for SCF/ACF JSON:
```php ```php
class ACF { class ACF {
@@ -359,6 +377,7 @@ class ACF {
``` ```
This means: This means:
- When you save a field group in the admin, ACF writes a JSON file to the `acf/` directory in the theme root. - When you save a field group in the admin, ACF writes a JSON file to the `acf/` directory in the theme root.
- When ACF loads field groups, it reads from the same `acf/` directory. - When ACF loads field groups, it reads from the same `acf/` directory.
- These JSON files are version-controlled, so field group configurations travel with the codebase and sync across environments. - These JSON files are version-controlled, so field group configurations travel with the codebase and sync across environments.
@@ -369,7 +388,7 @@ This means:
## Parent-Child Block Patterns (InnerBlocks) ## Parent-Child Block Patterns (InnerBlocks)
Some blocks act as containers that hold other blocks. WordPress provides `<InnerBlocks />` for this purpose, and ACF blocks can use it too. Some blocks act as containers that hold other blocks. WordPress provides `<InnerBlocks />` for this purpose, and SCF/ACF blocks can use it too.
### Basic InnerBlocks ### Basic InnerBlocks
@@ -506,7 +525,7 @@ To prevent this, add editor-only classes to `whitelist.php`. This file contains
<!-- ... more classes ... --> <!-- ... more classes ... -->
``` ```
The whitelist is primarily used for grid and layout classes that the Grid block applies dynamically through ACF field values (since those class names are generated at runtime, not hardcoded in templates). The whitelist is primarily used for grid and layout classes that the Grid block applies dynamically through SCF/ACF field values (since those class names are generated at runtime, not hardcoded in templates).
### Block-Specific CSS Files ### Block-Specific CSS Files
@@ -524,7 +543,7 @@ This walkthrough demonstrates creating a "Testimonial" block from scratch.
Create a new folder under `views/blocks/` using a lowercase, hyphenated slug: Create a new folder under `views/blocks/` using a lowercase, hyphenated slug:
``` ```plain
views/blocks/testimonial/ views/blocks/testimonial/
``` ```
@@ -538,9 +557,9 @@ Create `views/blocks/testimonial/block.json`:
{ {
"name": "acf/testimonial", "name": "acf/testimonial",
"title": "Testimonial", "title": "Testimonial",
"description": "A customer testimonial with quote, name, and role.", "description": "A customer testimonial with quote, name, image, and role.",
"style": ["file:./testimonial.css"], "style": ["file:./testimonial.css"],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "format-quote", "icon": "format-quote",
"keywords": ["testimonial", "quote", "review"], "keywords": ["testimonial", "quote", "review"],
"acf": { "acf": {
@@ -560,8 +579,9 @@ Create `views/blocks/testimonial/block.json`:
``` ```
**Checklist for `block.json`:** **Checklist for `block.json`:**
- `name` starts with `acf/` - `name` starts with `acf/`
- `category` is set to `vdi-blocks` - `category` is set to `sf-blocks`
- `style` references the CSS file with the `file:./` prefix - `style` references the CSS file with the `file:./` prefix
- `acf.renderTemplate` matches the PHP filename exactly - `acf.renderTemplate` matches the PHP filename exactly
- `supports.html` is `false` (ACF blocks should not support HTML editing) - `supports.html` is `false` (ACF blocks should not support HTML editing)
@@ -578,10 +598,10 @@ Create `views/blocks/testimonial/testimonial.php`:
* *
* A customer testimonial with quote, name, and role. * A customer testimonial with quote, name, and role.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$classes = 'testimonial'; $classes = 'testimonial';
$wrapper = blockWrapperAttributes( $classes, $is_preview ); $wrapper = blockWrapperAttributes( $classes, $is_preview );
@@ -618,14 +638,14 @@ $image = get_field( 'image' );
``` ```
**Checklist for the PHP template:** **Checklist for the PHP template:**
- Always start with `namespace BasicWP;`
- Always start with `namespace SoloFrameEvo;`
- Always call `blockWrapperAttributes( $classes, $is_preview )` and assign it to `$wrapper` - Always call `blockWrapperAttributes( $classes, $is_preview )` and assign it to `$wrapper`
- Always echo `$wrapper` inside the root element with `wp_kses_post()` - Always echo `$wrapper` inside the root element with `wp_kses_post()`
- Use `get_field()` to retrieve ACF field values - Use `get_field()` to retrieve ACF field values
- Use `getFieldValue()` for nested option fields - Use `getFieldValue()` for nested option fields
- Escape all output: `wp_kses_post()` for HTML content, `esc_html()` for plain text, `esc_url()` for URLs, `esc_attr()` for HTML attributes - Escape all output: `wp_kses_post()` for HTML content, `esc_html()` for plain text, `esc_url()` for URLs, `esc_attr()` for HTML attributes
- Use semantic HTML elements (`<section>`, `<blockquote>`, `<cite>`, etc.) - Use semantic HTML elements (`<section>`, `<blockquote>`, `<cite>`, etc.)
- Follow BEM-like naming for CSS classes: `.block`, `.block__element`, `.block__element--modifier`
### 4. Create the CSS File ### 4. Create the CSS File
@@ -665,7 +685,7 @@ Create `views/blocks/testimonial/testimonial.css`. It can start empty or with ba
If you are using Tailwind utility classes in the PHP template, you may not need much custom CSS. The file still needs to exist and be referenced in `block.json` so WordPress can load it. If you are using Tailwind utility classes in the PHP template, you may not need much custom CSS. The file still needs to exist and be referenced in `block.json` so WordPress can load it.
### 5. Create ACF Field Groups in WordPress Admin ### 5. Create SCF/ACF Field Groups in WordPress Admin
1. Log in to the WordPress admin dashboard. 1. Log in to the WordPress admin dashboard.
2. Go to **Custom Fields > Add New**. 2. Go to **Custom Fields > Add New**.
@@ -673,7 +693,7 @@ If you are using Tailwind utility classes in the PHP template, you may not need
4. Add the following fields: 4. Add the following fields:
| Field Label | Field Name | Field Type | Notes | | Field Label | Field Name | Field Type | Notes |
|---|---|---|---| | --- | --- | --- | --- |
| Quote | `quote` | Textarea | The testimonial text | | Quote | `quote` | Textarea | The testimonial text |
| Name | `name` | Text | The customer's name | | Name | `name` | Text | The customer's name |
| Role | `role` | Text | The customer's role or title (optional) | | Role | `role` | Text | The customer's role or title (optional) |
@@ -695,7 +715,7 @@ npm run build
Then verify the block appears in the editor: Then verify the block appears in the editor:
1. Edit a page in the WordPress block editor. 1. Edit a page in the WordPress block editor.
2. Open the inserter and look under **VDI Custom Blocks**. 2. Open the inserter and look under **SoloFrame Custom Blocks**.
3. You should see "Testimonial" with the quote icon. 3. You should see "Testimonial" with the quote icon.
4. Insert the block and fill in the fields. 4. Insert the block and fill in the fields.
5. Save and preview the page on the frontend to confirm rendering works correctly. 5. Save and preview the page on the frontend to confirm rendering works correctly.
@@ -709,7 +729,8 @@ Then verify the block appears in the editor:
The Homepage Hero is a straightforward block that retrieves ACF fields and renders them with Tailwind classes. It does not use InnerBlocks. The Homepage Hero is a straightforward block that retrieves ACF fields and renders them with Tailwind classes. It does not use InnerBlocks.
**Key patterns:** **Key patterns:**
- Retrieves multiple ACF fields with `get_field()`
- Retrieves multiple SCF/ACF fields with `get_field()`
- Conditionally renders sections only when fields have values (`! empty( $heading )`) - Conditionally renders sections only when fields have values (`! empty( $heading )`)
- Uses Tailwind classes extensively for layout and styling - Uses Tailwind classes extensively for layout and styling
- Handles editor vs. frontend differences for link URLs - Handles editor vs. frontend differences for link URLs
@@ -740,9 +761,10 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
### Parent Block with InnerBlocks: Section ### Parent Block with InnerBlocks: Section
The Section block is a container that wraps its child blocks with optional background styling. It demonstrates conditional rendering based on ACF fields. The Section block is a container that wraps its child blocks with optional background styling. It demonstrates conditional rendering based on SCF/ACF fields.
**Key patterns:** **Key patterns:**
- Builds CSS class strings dynamically based on field values - Builds CSS class strings dynamically based on field values
- Builds inline `style` strings from field values - Builds inline `style` strings from field values
- Conditionally renders an overlay div - Conditionally renders an overlay div
@@ -801,6 +823,7 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
The Buttons block is a container that only allows Button blocks as children. It enforces this restriction through both `block.json` and the template. The Buttons block is a container that only allows Button blocks as children. It enforces this restriction through both `block.json` and the template.
**Key patterns:** **Key patterns:**
- Uses `allowedBlocks` in `block.json` to restrict children to `acf/button` - Uses `allowedBlocks` in `block.json` to restrict children to `acf/button`
- Sets `"jsx": true` in `supports` to enable InnerBlocks - Sets `"jsx": true` in `supports` to enable InnerBlocks
- Passes Tailwind classes to InnerBlocks via the `className` prop - Passes Tailwind classes to InnerBlocks via the `className` prop
@@ -835,6 +858,7 @@ Note: The Buttons block uses `esc_attr()` instead of `wp_kses_post()` for the wr
The Grid block builds CSS classes dynamically from ACF field values (columns, breakpoints, gaps). This is a case where runtime-generated class names need to be whitelisted. The Grid block builds CSS classes dynamically from ACF field values (columns, breakpoints, gaps). This is a case where runtime-generated class names need to be whitelisted.
**Key patterns:** **Key patterns:**
- Dynamically constructs Tailwind class names from field values (e.g., `'grid-cols-' . get_field( 'columns' )`) - Dynamically constructs Tailwind class names from field values (e.g., `'grid-cols-' . get_field( 'columns' )`)
- Uses `$block['anchor']` and `$block['className']` for editor-set attributes - Uses `$block['anchor']` and `$block['className']` for editor-set attributes
- These dynamic class names are added to `whitelist.php` so Tailwind includes them in the build - These dynamic class names are added to `whitelist.php` so Tailwind includes them in the build
@@ -873,27 +897,27 @@ Because the class names like `grid-cols-3` and `md:grid-cols-4` are generated at
The Contact Info block demonstrates how to access ACF options page data (Global Fields) using `getFieldValue()`. The Contact Info block demonstrates how to access ACF options page data (Global Fields) using `getFieldValue()`.
**Key patterns:** **Key patterns:**
- Uses `get_field( 'contact_info', 'option' )` to retrieve the options page field group, then accesses sub-fields with array syntax
- Alternatively, could use `getFieldValue( 'contact_info.phone' )` for the same result - Uses `getFieldValue( 'contact_info.phone' )` to retrieve the options page field group, then accesses sub-fields with array syntax
- Combines static content from Global Fields with dynamic InnerBlocks content (a contact form) - Combines static content from Global Fields with dynamic InnerBlocks content (a contact form)
```php ```php
namespace BasicWP; namespace SoloFrameEvo;
$classes = 'contact-info'; $classes = 'contact-info';
$wrapper = blockWrapperAttributes( $classes, $is_preview ); $wrapper = blockWrapperAttributes( $classes, $is_preview );
?> ?>
<section <?php echo esc_attr( $wrapper ); ?>> <section <?php echo wp_kses_post( $wrapper ); ?>>
<div class="flex flex-col lg:flex-row"> <div class="flex flex-col lg:flex-row">
<div class="w-full lg:w-1/2 p-6"> <div class="w-full lg:w-1/2 p-6">
<h2 class="text-2xl font-bold mb-4">Contact Information</h2> <h2 class="text-2xl font-bold mb-4">Contact Information</h2>
<p><?php echo wp_kses_post( get_field( 'contact_info', 'option' )['address'] ); ?></p> <p><?php echo wp_kses_post( getFieldValue( 'contact_info.address' ) ); ?></p>
<p><a href="mailto:<?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?>"> <p><a href="mailto:<?php echo esc_html( getFieldValue( 'contact_info.email' ) ); ?>">
<?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?> <?php echo esc_html( getFieldValue( 'contact_info.email' ) ); ?>
</a></p> </a></p>
<p><a href="tel:<?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?>"> <p><a href="tel:<?php echo esc_html( getFieldValue( 'contact_info.phone' ) ); ?>">
<?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?> <?php echo esc_html( getFieldValue( 'contact_info.phone' ) ); ?>
</a></p> </a></p>
</div> </div>
@@ -910,12 +934,12 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
### Do ### Do
- **Always use `namespace BasicWP;`** at the top of every block PHP template. Without it, helper functions like `blockWrapperAttributes()` and `getFieldValue()` will not be available. - **Always use `namespace SoloFrameEvo;`** at the top of every block PHP template. Without it, helper functions like `blockWrapperAttributes()` and `getFieldValue()` will not be available.
- **Always use `blockWrapperAttributes()`** for the root element's attributes. Never call `get_block_wrapper_attributes()` directly. - **Always use `blockWrapperAttributes()`** for the root element's attributes. Never call `get_block_wrapper_attributes()` directly.
- **Always escape output.** Use `wp_kses_post()` for HTML content, `esc_html()` for plain text, `esc_url()` for URLs, and `esc_attr()` for HTML attribute values. - **Always escape output.** Use `wp_kses_post()` for HTML content, `esc_html()` for plain text, `esc_url()` for URLs, and `esc_attr()` for HTML attribute values.
- **Always set `category` to `vdi-blocks`** in `block.json` so your block appears under "VDI Custom Blocks" in the editor. - **Always set `category` to `sf-blocks`** in `block.json` so your block appears under "VDI Custom Blocks" in the editor.
- **Always prefix `name` with `acf/`** in `block.json` (e.g., `"acf/testimonial"`, not just `"testimonial"`). - **Always prefix `name` with `acf/`** in `block.json` (e.g., `"acf/testimonial"`, not just `"testimonial"`).
- **Always set `supports.html` to `false`** in `block.json` for ACF blocks. ACF blocks use PHP templates, not HTML editing. - **Always set `supports.html` to `false`** in `block.json` for SCF/ACF blocks. SCF/ACF blocks use PHP templates, not HTML editing.
- **Always set `supports.jsx` to `true`** if your block uses `<InnerBlocks />`. Without this, the InnerBlocks area will not render. - **Always set `supports.jsx` to `true`** if your block uses `<InnerBlocks />`. Without this, the InnerBlocks area will not render.
- **Commit ACF JSON files** from the `acf/` directory to version control after creating field groups. - **Commit ACF JSON files** from the `acf/` directory to version control after creating field groups.
- **Use semantic HTML elements** as block wrappers (`<section>`, `<article>`, `<aside>`, `<nav>`, etc.) instead of generic `<div>` elements where appropriate. - **Use semantic HTML elements** as block wrappers (`<section>`, `<article>`, `<aside>`, `<nav>`, etc.) instead of generic `<div>` elements where appropriate.
@@ -929,7 +953,7 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
- **Do not forget to create the CSS file** referenced in `block.json`. Even if the file is empty, WordPress needs it to exist. If the file is missing, WordPress may throw an error when loading the block. - **Do not forget to create the CSS file** referenced in `block.json`. Even if the file is empty, WordPress needs it to exist. If the file is missing, WordPress may throw an error when loading the block.
- **Do not use `'option'` directly with `get_field()` for nested values without null checking.** Prefer `getFieldValue()` which handles missing values gracefully. - **Do not use `'option'` directly with `get_field()` for nested values without null checking.** Prefer `getFieldValue()` which handles missing values gracefully.
- **Do not set `supports.multiple` to `false`** unless the block truly must be unique per page (like a homepage hero). Most blocks should allow multiple instances. - **Do not set `supports.multiple` to `false`** unless the block truly must be unique per page (like a homepage hero). Most blocks should allow multiple instances.
- **Do not hardcode editor-only Tailwind classes in PHP templates** without adding them to `whitelist.php`. If a class only appears in the editor's UI (like grid column classes set via ACF fields), Tailwind will not include it in the build. - **Do not hardcode editor-only Tailwind classes in PHP templates** without adding them to `whitelist.php`. If a class only appears in the editor's UI (like grid column classes set via SCF/ACF fields), Tailwind will not include it in the build.
- **Do not use the `style` attribute on the block's root element alongside `blockWrapperAttributes()` for background colors** unless the block specifically needs it. WordPress's built-in color supports (enabled via `supports.color`) handle this automatically. - **Do not use the `style` attribute on the block's root element alongside `blockWrapperAttributes()` for background colors** unless the block specifically needs it. WordPress's built-in color supports (enabled via `supports.color`) handle this automatically.
### Debugging Tips ### Debugging Tips
+44 -59
View File
@@ -1,6 +1,6 @@
# Getting Started with VDI-Starter-v5 # Getting Started with SoloFrame Evo
This guide walks you through setting up a local development environment for the VDI-Starter-v5 WordPress theme from scratch. It covers prerequisites, installation, configuration, and common development workflows. This guide walks you through setting up a local development environment for the SoloFrame Evo WordPress theme from scratch. It covers prerequisites, installation, configuration, and common development workflows.
--- ---
@@ -15,7 +15,7 @@ This guide walks you through setting up a local development environment for the
7. [Activating the Theme](#activating-the-theme) 7. [Activating the Theme](#activating-the-theme)
8. [Development Workflow](#development-workflow) 8. [Development Workflow](#development-workflow)
9. [Project Architecture](#project-architecture) 9. [Project Architecture](#project-architecture)
10. [Creating Custom ACF Blocks](#creating-custom-acf-blocks) 10. [Creating Custom SCF/ACF Blocks](#creating-custom-scfacf-blocks)
11. [Testing](#testing) 11. [Testing](#testing)
12. [Code Quality](#code-quality) 12. [Code Quality](#code-quality)
13. [Troubleshooting](#troubleshooting) 13. [Troubleshooting](#troubleshooting)
@@ -24,7 +24,7 @@ This guide walks you through setting up a local development environment for the
## Overview ## Overview
VDI-Starter-v5 is a minimal WordPress theme designed as a starting point for custom theme development. It uses a modern stack: SoloFrame Evo is a minimal WordPress theme designed as a starting point for custom theme development. It uses a modern stack:
- **Tailwind CSS v4** for utility-first styling, compiled via the Tailwind CLI - **Tailwind CSS v4** for utility-first styling, compiled via the Tailwind CLI
- **ACF Pro** for custom field management and block registration - **ACF Pro** for custom field management and block registration
@@ -42,7 +42,7 @@ The theme intentionally avoids heavyweight frameworks. Every PHP file in `lib/`
Before you begin, make sure the following tools are installed on your machine. Before you begin, make sure the following tools are installed on your machine.
| Tool | Minimum Version | Why It Is Needed | | Tool | Minimum Version | Why It Is Needed |
|-------------|-----------------|------------------------------------------------------------------------------------------------------| | ------------- | -------------------------- | ---------------------------------------------------------------------------------------------------- |
| Node.js | 22+ | Tailwind CSS v4 CLI requires a modern Node runtime. Older versions will fail during `npm run build`. | | Node.js | 22+ | Tailwind CSS v4 CLI requires a modern Node runtime. Older versions will fail during `npm run build`. |
| npm | Latest (bundled with Node) | Package management for JavaScript dependencies and build scripts. | | npm | Latest (bundled with Node) | Package management for JavaScript dependencies and build scripts. |
| PHP | 8.0+ | WordPress core requirement and theme compatibility. | | PHP | 8.0+ | WordPress core requirement and theme compatibility. |
@@ -96,9 +96,9 @@ Docker gives you the most control and works on any operating system, but it requ
1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop/). 1. Install [Docker Desktop](https://www.docker.com/products/docker-desktop/).
2. Use the official `wordpress` Docker image with a custom theme mount. A minimal `docker-compose.yml` might look like: 2. Use the official `wordpress` Docker image with a custom theme mount. A minimal `docker-compose.yml` might look like:
```yaml ```yaml
version: '3.8' version: '3.8'
services: services:
db: db:
image: mysql:8.0 image: mysql:8.0
environment: environment:
@@ -119,13 +119,13 @@ services:
WORDPRESS_DB_PASSWORD: wordpress WORDPRESS_DB_PASSWORD: wordpress
WORDPRESS_DB_NAME: wordpress WORDPRESS_DB_NAME: wordpress
volumes: volumes:
- ./themes/vdi-starter-v5:/var/www/html/wp-content/themes/vdi-starter-v5 - ./themes/SoloFrame-Evo:/var/www/html/wp-content/themes/SoloFrame-Evo
depends_on: depends_on:
- db - db
volumes: volumes:
db_data: db_data:
``` ```
3. Run `docker compose up -d` and visit `http://localhost:8080` to complete the WordPress installation wizard. 3. Run `docker compose up -d` and visit `http://localhost:8080` to complete the WordPress installation wizard.
@@ -136,29 +136,17 @@ volumes:
### Step 1: Clone the Repository ### Step 1: Clone the Repository
```bash ```bash
git clone https://github.com/Vincent-Design-Inc/VDI-Starter-v5.git git clone https://github.com/ksolomon/SoloFrame-Evo.git
cd VDI-Starter-v5 cd SoloFrame-Evo
``` ```
If you are contributing to an existing project, clone it into your local WordPress `wp-content/themes/` directory so WordPress can detect it: If you are contributing to an existing project, clone it into your local WordPress `wp-content/themes/` directory so WordPress can detect it:
```bash ```bash
cd /path/to/your/local-wp-site/wp-content/themes/ cd /path/to/your/local-wp-site/wp-content/themes/
git clone https://github.com/Vincent-Design-Inc/VDI-Starter-v5.git git clone https://github.com/ksolomon/SoloFrame-Evo.git
``` ```
If you cloned it elsewhere, you can symlink it into the themes directory:
```bash
# macOS/Linux
ln -s /path/to/VDI-Starter-v5 /path/to/wp-content/themes/vdi-starter-v5
# Windows (run in an elevated Command Prompt)
mklink /D "C:\path\to\wp-content\themes\vdi-starter-v5" "C:\path\to\VDI-Starter-v5"
```
Using a symlink means your local edits are immediately reflected in WordPress without copying files.
### Step 2: Install PHP Dependencies ### Step 2: Install PHP Dependencies
```bash ```bash
@@ -173,9 +161,9 @@ This installs PHP_CodeSniffer and the WordPress Coding Standards (WPCS) ruleset.
npm install npm install
``` ```
This installs the frontend build toolchain: Tailwind CSS v4 and its CLI, BrowserSync, Playwright, dotenv, and other utilities. Tailwind v4 uses the `@tailwindcss/cli` package directly (no `tailwind.config.js` file is needed -- configuration lives in `styles/theme.css`). This installs the frontend build toolchain: Tailwind CSS v4 and its CLI, BrowserSync, Playwright, dotenv, and other utilities. Tailwind v4 uses the `@tailwindcss/cli` package directly. No `tailwind.config.js` file is needed -- configuration lives in `styles/theme.css`.
### Step 4: Configure Environment Variables ## Environment Configuration
Copy the example environment file and edit it: Copy the example environment file and edit it:
@@ -186,15 +174,15 @@ cp .env.example .env
Open `.env` and set the two variables: Open `.env` and set the two variables:
| Variable | Description | Example Value | | Variable | Description | Example Value |
|-------------------|-----------------------------------------------------------------------------------------------|------------------------------| | ------------------- | ----------------------------------------------------------------------------------- | ------------------------------ |
| `LOCALHOST_URL` | The full URL of your local WordPress site, including the scheme (`http` or `https`) | `https://vdi-starter.local` | | `LOCALHOST_URL` | The full URL of your local WordPress site, including the scheme (`http` or `https`) | `https://soloframe-evo.local` |
| `BROWSERSYNC_PORT`| The port BrowserSync should listen on. Defaults to `5000` if not set. | `5000` | | `BROWSERSYNC_PORT` | The port BrowserSync should listen on. Defaults to `5000` if not set. | `5000` |
The `LOCALHOST_URL` must match exactly what your local WordPress environment responds to. If you are using Local by Flywheel with SSL enabled, include `https://`. If you are using Docker on port 8080, use `http://localhost:8080`. The `LOCALHOST_URL` must match exactly what your local WordPress environment responds to. If you are using Local by Flywheel with SSL enabled, include `https://`. If you are using Docker on port 8080, use `http://localhost:8080`.
BrowserSync proxies this URL and injects a live-reload script, so any change you make to PHP templates, CSS, or JS files will automatically refresh the browser. BrowserSync proxies this URL and injects a live-reload script, so any change you make to PHP templates, CSS, or JS files will automatically refresh the browser.
### Step 5: Build Assets for the First Time ## Building Assets
Before activating the theme, compile the Tailwind CSS so the theme has its stylesheet: Before activating the theme, compile the Tailwind CSS so the theme has its stylesheet:
@@ -204,7 +192,7 @@ npm run build
This runs: This runs:
``` ```bash
npx @tailwindcss/cli -i ./styles/theme.css -o ./static/dist/theme.css --optimize npx @tailwindcss/cli -i ./styles/theme.css -o ./static/dist/theme.css --optimize
``` ```
@@ -227,15 +215,11 @@ Log into your local WordPress admin dashboard and navigate to **Appearance > The
> - **Creates 4 default pages:** Home, News, Page Not Found (Error 404), and Contact Us. > - **Creates 4 default pages:** Home, News, Page Not Found (Error 404), and Contact Us.
> - **Sets WordPress to use a static front page:** Home becomes the front page, News becomes the posts page. This overrides any existing "Reading Settings". > - **Sets WordPress to use a static front page:** Home becomes the front page, News becomes the posts page. This overrides any existing "Reading Settings".
> - **Deletes the default "Hello World" post** (ID 1) and the **sample page** (ID 2). These are trashed permanently (`wp_delete_post` with `$force_delete = true`). > - **Deletes the default "Hello World" post** (ID 1) and the **sample page** (ID 2). These are trashed permanently (`wp_delete_post` with `$force_delete = true`).
> - **Installs 7 plugins** from external URLs and selectively activates them: > - **Installs 4 plugins** from external URLs and selectively activates them:
> 1. **ACF Pro** -- installed and activated (from `https://docs.vincentdevelopment.ca/files/advanced-custom-fields-pro.zip`) > 1. **Secure Custom Fields** -- installed and activated (from WordPress.org)
> 2. **Gravity Forms** -- installed and activated (from `https://docs.vincentdevelopment.ca/files/gravity-forms.zip`) > 2. **Simple History** -- installed and activated (from WordPress.org)
> 3. **UpdraftPlus** -- installed, NOT activated (from WordPress.org) > 3. **The SEO Framework** -- installed and activated (from WordPress.org)
> 4. **Simple History** -- installed and activated (from WordPress.org) > 4. **Better Search Replace** -- installed and activated (from WordPress.org)
> 5. **The SEO Framework** -- installed and activated (from WordPress.org)
> 6. **Better Search Replace** -- installed and activated (from WordPress.org)
> 7. **Google Site Kit** -- installed, NOT activated (from WordPress.org)
> - **Creates an "Owner" role** (administrator capabilities minus plugin/theme management).
> - **Writes an installation log** to `wp-content/mu-plugin-install.log`. > - **Writes an installation log** to `wp-content/mu-plugin-install.log`.
> >
> **Do NOT activate this theme on an existing production site without reviewing `lib/activation.php` first.** The activation routine is designed for fresh installs and will modify pages, settings, and plugin state without confirmation. > **Do NOT activate this theme on an existing production site without reviewing `lib/activation.php` first.** The activation routine is designed for fresh installs and will modify pages, settings, and plugin state without confirmation.
@@ -271,7 +255,7 @@ This runs `bin/.watch.js`, which starts BrowserSync and watches for file changes
When you edit a `.js` file in `static/js/`, BrowserSync injects the updated script without a full page reload (hot injection). When you edit a `.js` file in `static/js/`, BrowserSync injects the updated script without a full page reload (hot injection).
The dev server is accessible at the `LOCALHOST_URL` you configured, proxied through the `BROWSERSYNC_PORT`. For example, if your `.env` has `LOCALHOST_URL=https://vdi-starter.local` and `BROWSERSYNC_PORT=5000`, your dev URL is `https://vdi-starter.local` with BrowserSync overlay on port 5000. The dev server is accessible at the `LOCALHOST_URL` you configured, proxied through the `BROWSERSYNC_PORT`. For example, if your `.env` has `LOCALHOST_URL=http://soloframe-evo.local` and `BROWSERSYNC_PORT=5000`, your dev URL is `http://soloframe-evo.local` with BrowserSync overlay on port 5000.
### Building for Production ### Building for Production
@@ -291,9 +275,9 @@ This compiles Tailwind CSS with `--optimize` enabled, which minifies the output
Understanding the directory layout helps you know where to find things and where to put new files. Understanding the directory layout helps you know where to find things and where to put new files.
``` ```plain
VDI-Starter-v5/ SoloFrame-Evo/
├── acf/ # ACF Pro field group JSON (auto-synced) ├── acf/ # SCF/ACF Pro field group JSON (auto-synced)
│ └── group_*.json # One file per field group │ └── group_*.json # One file per field group
├── bin/ ├── bin/
│ ├── .watch.js # BrowserSync dev server script │ ├── .watch.js # BrowserSync dev server script
@@ -303,7 +287,7 @@ VDI-Starter-v5/
├── docs/ # Documentation (this guide lives here) ├── docs/ # Documentation (this guide lives here)
├── lib/ # PHP utility classes (auto-loaded) ├── lib/ # PHP utility classes (auto-loaded)
│ ├── activation.php # Theme activation routine (pages, plugins, settings) │ ├── activation.php # Theme activation routine (pages, plugins, settings)
│ ├── class-acf.php # ACF JSON load/save path configuration │ ├── class-acf.php # SCF/ACF JSON load/save path configuration
│ ├── class-breadcrumbs.php # Breadcrumb navigation helper │ ├── class-breadcrumbs.php # Breadcrumb navigation helper
│ ├── class-enqueue.php # Frontend/backend/editor asset enqueueing │ ├── class-enqueue.php # Frontend/backend/editor asset enqueueing
│ ├── class-menuitems.php # Custom menu item handling │ ├── class-menuitems.php # Custom menu item handling
@@ -373,7 +357,7 @@ foreach ( glob( __DIR__ . '/lib/*.php' ) as $filename ) {
This means adding a new file to `lib/` automatically includes it. No manual `require` statements are needed. However, be aware that files are loaded in alphabetical order. If one file depends on something defined in another, you may need to rename files with numeric prefixes to control load order. This means adding a new file to `lib/` automatically includes it. No manual `require` statements are needed. However, be aware that files are loaded in alphabetical order. If one file depends on something defined in another, you may need to rename files with numeric prefixes to control load order.
### How ACF Blocks Are Registered ### How SCF/ACF Blocks Are Registered
The `regACFBlocks()` function in `functions.php` scans the `views/blocks/` directory at runtime: The `regACFBlocks()` function in `functions.php` scans the `views/blocks/` directory at runtime:
@@ -400,19 +384,19 @@ The Tailwind entry point is `styles/theme.css`. It imports sub-stylesheets using
```css ```css
@import "tailwindcss"; /* Tailwind v4 framework */ @import "tailwindcss"; /* Tailwind v4 framework */
@import "./base/index.css"; /* Base styles */ @import "./base/index.css"; /* Base styles */
@import "./navigation/index.css";/* Navigation styles */ @import "./navigation/index.css"; /* Navigation styles */
@import "./fonts/lineicons.css"; /* Icon font */ @import "./fonts/lineicons.css"; /* Icon font */
@import "./base/break-out.css"; /* Break-out utility */ @import "./base/break-out.css"; /* Break-out utility */
@import "./components/index.css";/* Component styles */ @import "./components/index.css"; /* Component styles */
@import "./blocks/index.css"; /* Block-specific styles */ @import "./blocks/index.css"; /* Block-specific styles */
@plugin "@tailwindcss/typography"; /* Typography plugin */ @plugin "@tailwindcss/typography"; /* Tailwind Typography plugin */
``` ```
When you create a new block or component, add its styles to the appropriate subdirectory and make sure it is imported through the corresponding `index.css` file. When you create a new block or component, add its styles to the appropriate subdirectory and make sure it is imported through the corresponding `index.css` file.
--- ---
## Creating Custom ACF Blocks ## Creating Custom SCF/ACF Blocks
To create a new ACF block, use the `boilerplate` directory as a starting point: To create a new ACF block, use the `boilerplate` directory as a starting point:
@@ -424,7 +408,7 @@ To create a new ACF block, use the `boilerplate` directory as a starting point:
2. Edit `views/blocks/my-block/block.json`: 2. Edit `views/blocks/my-block/block.json`:
- Change `"name"` to `"acf/my-block"` - Change `"name"` to `"acf/my-block"`
- Change `"title"` to a human-readable name like `"My Block (VDI)"` - Change `"title"` to a human-readable name like `"My Block"`
- Update `"description"`, `"icon"`, and `"keywords"` as appropriate - Update `"description"`, `"icon"`, and `"keywords"` as appropriate
- If this block should only be nested inside another block, add a `"parent"` array (see `button/block.json` for an example) - If this block should only be nested inside another block, add a `"parent"` array (see `button/block.json` for an example)
@@ -432,7 +416,7 @@ To create a new ACF block, use the `boilerplate` directory as a starting point:
4. If the block needs ACF field groups, create them in the WordPress admin under **Custom Fields > Field Groups** and associate them with the block. ACF will save the field group JSON to the `acf/` directory, which you should commit to version control. 4. If the block needs ACF field groups, create them in the WordPress admin under **Custom Fields > Field Groups** and associate them with the block. ACF will save the field group JSON to the `acf/` directory, which you should commit to version control.
5. Add block-specific styles in `styles/blocks/` and import them through `styles/blocks/index.css`. 5. Add block-specific styles in `my-block.css`.
The block will be automatically discovered and registered on the next page load because `regACFBlocks()` scans the directory on every `init` hook. The block will be automatically discovered and registered on the next page load because `regACFBlocks()` scans the directory on every `init` hook.
@@ -502,12 +486,13 @@ The compilation pipeline is: `styles/theme.css` (entry point with `@import` dire
**Symptom:** The block inserter in the Gutenberg editor does not show custom blocks like "Homepage Hero" or "Section". **Symptom:** The block inserter in the Gutenberg editor does not show custom blocks like "Homepage Hero" or "Section".
**Solution:** ACF Pro must be installed and activated. Blocks are registered by scanning `views/blocks/*/block.json` on the `init` hook. Without ACF Pro, `register_block_type()` still runs, but ACF blocks require the ACF plugin to provide field data and rendering. **Solution:** SCF (installed by default on theme activation) or ACF Pro must be installed and activated. Blocks are registered by scanning `views/blocks/*/block.json` on the `init` hook. Without SCF/ACF Pro, `register_block_type()` still runs, but blocks require the SCF/ACF plugin to provide field data and rendering.
Also check that: Also check that:
- The block directory contains a valid `block.json` file. - The block directory contains a valid `block.json` file.
- The block directory is not named `boilerplate` (this is excluded by design). - The block directory is not named `boilerplate` (this is excluded by design).
- ACF Pro is activated (not just installed). - SCF/ACF Pro is activated (not just installed).
### Menus Are Not Rendering ### Menus Are Not Rendering
@@ -567,7 +552,7 @@ Check `wp-content/mu-plugin-install.log` for detailed error messages. Each plugi
## Quick Reference ## Quick Reference
| Command | Purpose | | Command | Purpose |
|---------------------|--------------------------------------------------------------------| | --------------------- | -------------------------------------------------------------------- |
| `npm run start` | Start BrowserSync dev server with live reload (alias for `watch`) | | `npm run start` | Start BrowserSync dev server with live reload (alias for `watch`) |
| `npm run watch` | Start BrowserSync dev server with live reload | | `npm run watch` | Start BrowserSync dev server with live reload |
| `npm run build` | Compile Tailwind CSS for production (minified, optimized) | | `npm run build` | Compile Tailwind CSS for production (minified, optimized) |
@@ -576,10 +561,10 @@ Check `wp-content/mu-plugin-install.log` for detailed error messages. Each plugi
| `npx playwright test` | Run Playwright end-to-end tests | | `npx playwright test` | Run Playwright end-to-end tests |
| File | Purpose | | File | Purpose |
|-----------------------------------|------------------------------------------------------| | ----------------------------------- | -------------------------------------------------------------- |
| `.env` | Local environment config (`LOCALHOST_URL`, `BROWSERSYNC_PORT`) | | `.env` | Local environment config (`LOCALHOST_URL`, `BROWSERSYNC_PORT`) |
| `styles/theme.css` | Tailwind CSS entry point (edit this to add imports) | | `styles/theme.css` | Tailwind CSS entry point (edit this to add imports) |
| `static/dist/theme.css` | Compiled CSS output (generated, do not edit manually)| | `static/dist/theme.css` | Compiled CSS output (generated, do not edit manually) |
| `views/blocks/*/block.json` | ACF block registration files | | `views/blocks/*/block.json` | ACF block registration files |
| `lib/activation.php` | Theme activation routine (creates pages, installs plugins) | | `lib/activation.php` | Theme activation routine (creates pages, installs plugins) |
| `lib/class-enqueue.php` | Frontend/backend/editor asset loading | | `lib/class-enqueue.php` | Frontend/backend/editor asset loading |
+57 -45
View File
@@ -1,46 +1,56 @@
# VDI-Starter-v5 Theme Reference # SoloFrame Evo Theme Reference
> Quick-lookup reference for the VDI-Starter-v5 WordPress theme. Covers hooks, filters, design tokens, CSS architecture, JS modules, helper functions, class APIs, CLI commands, deployment, and testing. > Quick-lookup reference for the SoloFrame Evo WordPress theme. Covers hooks, filters, design tokens, CSS architecture, JS modules, helper functions, class APIs, CLI commands, deployment, and testing.
--- ---
## Table of Contents ## Table of Contents
- [Hooks and Filters](#hooks-and-filters) - [SoloFrame Evo Theme Reference](#soloframe-evo-theme-reference)
- [hooks.php (BasicWP Namespace)](#hooksphp-basicwp-namespace) - [Table of Contents](#table-of-contents)
- [Hooks and Filters](#hooks-and-filters)
- [hooks.php (SoloFrameEvo Namespace)](#hooksphp-soloframeevo-namespace)
- [extras.php](#extrasphp) - [extras.php](#extrasphp)
- [helpers.php](#helpersphp) - [helpers.php](#helpersphp)
- [class-enqueue.php](#class-enqueuephp) - [class-enqueue.php](#class-enqueuephp)
- [class-breadcrumbs.php](#class-breadcrumbsphp) - [class-breadcrumbs.php](#class-breadcrumbsphp)
- [class-resources.php](#class-resourcesphp) - [class-resources.php](#class-resourcesphp)
- [theme.json Design Tokens](#themejson-design-tokens) - [theme.json Design Tokens](#themejson-design-tokens)
- [Colors](#colors) - [Colors](#colors)
- [Font Sizes](#font-sizes) - [Font Sizes](#font-sizes)
- [Font Family](#font-family) - [Font Family](#font-family)
- [Layout](#layout) - [Layout](#layout)
- [Spacing Units](#spacing-units) - [Spacing Units](#spacing-units)
- [CSS Architecture](#css-architecture) - [CSS Architecture](#css-architecture)
- [Import Order](#import-order) - [Import Order](#import-order)
- [Adding a New Stylesheet](#adding-a-new-stylesheet) - [Adding a New Stylesheet](#adding-a-new-stylesheet)
- [JS Module Dependency Graph](#js-module-dependency-graph) - [JS Module Dependency Graph](#js-module-dependency-graph)
- [Script Module IDs](#script-module-ids) - [Script Module IDs](#script-module-ids)
- [Navigation Class API](#navigation-class-api) - [Navigation Class API](#navigation-class-api)
- [Helper Functions](#helper-functions) - [Constructor](#constructor)
- [Class Reference](#class-reference) - [Methods](#methods)
- [CLI Commands](#cli-commands) - [Helper Functions](#helper-functions)
- [Deployment (GitHub Actions)](#deployment-github-actions) - [Class Reference](#class-reference)
- [Testing](#testing) - [Breadcrumbs Method Details](#breadcrumbs-method-details)
- [CLI Commands](#cli-commands)
- [Deployment (GitHub Actions)](#deployment-github-actions)
- [Deployment Steps](#deployment-steps)
- [rsync Flags](#rsync-flags)
- [Testing](#testing)
- [Accessibility Tests](#accessibility-tests)
- [PHP Linting](#php-linting)
- [Playwright Configuration](#playwright-configuration)
--- ---
## Hooks and Filters ## Hooks and Filters
### hooks.php (BasicWP Namespace) ### hooks.php (SoloFrameEvo Namespace)
All hooks in this file live under the `BasicWP` namespace. All hooks in this file live under the `SoloFrameEvo` namespace.
| Hook | Type | Priority | Args | Description | | Hook | Type | Priority | Args | Description |
|------|------|----------|------|-------------| | ------ | ------ | ---------- | ------ | ------------- |
| `wp_head` | Action | 0 | — | Adds Google Fonts `<link rel="preconnect">` tags | | `wp_head` | Action | 0 | — | Adds Google Fonts `<link rel="preconnect">` tags |
| `register_nav_menus()` | Direct call | — | — | Registers three menus: `main_navigation`, `aux_navigation`, `footer_navigation` | | `register_nav_menus()` | Direct call | — | — | Registers three menus: `main_navigation`, `aux_navigation`, `footer_navigation` |
| `widgets_init` | Action | — | — | Registers four sidebars: `sidebar-primary`, `sidebar-page`, `footer-1`, `footer-2`, `footer-3` | | `widgets_init` | Action | — | — | Registers four sidebars: `sidebar-primary`, `sidebar-page`, `footer-1`, `footer-2`, `footer-3` |
@@ -57,6 +67,7 @@ All hooks in this file live under the `BasicWP` namespace.
**The `init` (priority 1) hook performs aggressive cleanup:** **The `init` (priority 1) hook performs aggressive cleanup:**
Removes: Removes:
- Emoji detection and styles (`remove_action` on `wp_head`) - Emoji detection and styles (`remove_action` on `wp_head`)
- Block library styles (`wp-block-library`) - Block library styles (`wp-block-library`)
- Global styles (`global-styles`) - Global styles (`global-styles`)
@@ -67,6 +78,7 @@ Removes:
- WLW manifest link (`wlwmanifest_link`) - WLW manifest link (`wlwmanifest_link`)
Adds theme supports: Adds theme supports:
- `post-thumbnails` - `post-thumbnails`
- `title-tag` - `title-tag`
- `html5` (search-form, comment-form, comment-list, gallery, caption, style, script) - `html5` (search-form, comment-form, comment-list, gallery, caption, style, script)
@@ -80,7 +92,7 @@ Adds theme supports:
### extras.php ### extras.php
| Hook / Filter | Type | Description | | Hook / Filter | Type | Description |
|---------------|------|-------------| | --------------- | ------ | ------------- |
| `hasSidebar` | Filter | Controls sidebar display based on an ACF true/false field on the current page | | `hasSidebar` | Filter | Controls sidebar display based on an ACF true/false field on the current page |
| `body_class` | Filter | Appends `has-sidebar` class to `<body>` when a sidebar is present | | `body_class` | Filter | Appends `has-sidebar` class to `<body>` when a sidebar is present |
| `the_content` | Filter | `divWrapper()` wraps `<iframe>` and embed elements in `<div class="embed">` | | `the_content` | Filter | `divWrapper()` wraps `<iframe>` and embed elements in `<div class="embed">` |
@@ -94,10 +106,10 @@ Adds theme supports:
### helpers.php ### helpers.php
| Hook / Filter | Type | Priority | Args | Description | | Hook / Filter | Type | Priority | Args | Description |
|---------------|------|----------|------|-------------| | --------------- | ------ | ---------- | ------ | ------------- |
| `custom_menu_order` | Filter | 10 | 1 | Enables custom admin menu ordering | | `custom_menu_order` | Filter | 10 | 1 | Enables custom admin menu ordering |
| `menu_order` | Filter | 10 | 1 | Defines the custom admin menu order | | `menu_order` | Filter | 10 | 1 | Defines the custom admin menu order |
| `block_categories_all` | Filter | 10 | — | Adds the `vdi-blocks` category to the block editor | | `block_categories_all` | Filter | 10 | — | Adds the `sf-blocks` category to the block editor |
| `init` | Action | — | — | Registers the ACF "Global Fields" options page | | `init` | Action | — | — | Registers the ACF "Global Fields" options page |
--- ---
@@ -105,7 +117,7 @@ Adds theme supports:
### class-enqueue.php ### class-enqueue.php
| Hook | Type | Method | Description | | Hook | Type | Method | Description |
|------|------|--------|-------------| | ------ | ------ | -------- | ------------- |
| `wp_enqueue_scripts` | Action | `enqFEAssets()` | Loads frontend CSS and JS | | `wp_enqueue_scripts` | Action | `enqFEAssets()` | Loads frontend CSS and JS |
| `admin_enqueue_scripts` | Action | `enqBEAssets()` | Loads admin CSS and JS | | `admin_enqueue_scripts` | Action | `enqBEAssets()` | Loads admin CSS and JS |
| `enqueue_block_editor_assets` | Action | `enqEditorAssets()` | Loads block editor CSS | | `enqueue_block_editor_assets` | Action | `enqEditorAssets()` | Loads block editor CSS |
@@ -117,7 +129,7 @@ Adds theme supports:
The `Breadcrumbs` class generates Schema.org-compatible breadcrumb markup. Context-specific methods: The `Breadcrumbs` class generates Schema.org-compatible breadcrumb markup. Context-specific methods:
| Method | Context | | Method | Context |
|--------|---------| | -------- | --------- |
| `getHomeBreadcrumb()` | Site front page | | `getHomeBreadcrumb()` | Site front page |
| `getBlogPostsIndexBreadcrumb()` | Blog posts index | | `getBlogPostsIndexBreadcrumb()` | Blog posts index |
| `getSinglePostBreadcrumbs()` | Single post | | `getSinglePostBreadcrumbs()` | Single post |
@@ -134,7 +146,7 @@ The `Breadcrumbs` class generates Schema.org-compatible breadcrumb markup. Conte
### class-resources.php ### class-resources.php
| Hook | Type | Description | | Hook | Type | Description |
|------|------|-------------| | ------ | ------ | ------------- |
| `init` | Action | Registers the `resources` custom post type | | `init` | Action | Registers the `resources` custom post type |
| `post_type_link` | Filter | Customizes resource permalinks to `/resources/{term-slug}/{post-name}` | | `post_type_link` | Filter | Customizes resource permalinks to `/resources/{term-slug}/{post-name}` |
@@ -149,7 +161,7 @@ The `resources` CPT uses a URL rewrite pattern that incorporates the first taxon
All theme colors map to CSS custom properties. Use the CSS variable in your stylesheets or reference the slug in the block editor. All theme colors map to CSS custom properties. Use the CSS variable in your stylesheets or reference the slug in the block editor.
| Slug | CSS Variable | Name | Value | | Slug | CSS Variable | Name | Value |
|------|-------------|------|-------| | ------ | ------------- | ------ | ------- |
| `black` | — | Black | `#000` | | `black` | — | Black | `#000` |
| `white` | — | White | `#fff` | | `white` | — | White | `#fff` |
| `theme-bg` | `var(--color-background)` | Theme Background | Dynamic | | `theme-bg` | `var(--color-background)` | Theme Background | Dynamic |
@@ -187,7 +199,7 @@ The dynamic colors (`theme-*`) resolve to CSS custom properties that can be over
### Font Sizes ### Font Sizes
| Slug | CSS Variable | Name | | Slug | CSS Variable | Name |
|------|-------------|------| | ------ | ------------- | ------ |
| `base` | `var(--text-base)` | Base | | `base` | `var(--text-base)` | Base |
| `text-14px` | `var(--text-14px)` | Text 14px | | `text-14px` | `var(--text-14px)` | Text 14px |
| `text-16px` | `var(--text-16px)` | Text 16px | | `text-16px` | `var(--text-16px)` | Text 16px |
@@ -223,7 +235,7 @@ The dynamic colors (`theme-*`) resolve to CSS custom properties that can be over
### Font Family ### Font Family
| Slug | CSS Variable | Name | | Slug | CSS Variable | Name |
|------|-------------|------| | ------ | ------------- | ------ |
| `theme-sans` | `var(--font-sans)` | Theme Sans | | `theme-sans` | `var(--font-sans)` | Theme Sans |
```css ```css
@@ -237,7 +249,7 @@ body {
### Layout ### Layout
| Setting | Value | | Setting | Value |
|---------|-------| | --------- | ------- |
| `contentSize` | `100%` | | `contentSize` | `100%` |
| `wideSize` | `1536px` | | `wideSize` | `1536px` |
@@ -259,7 +271,7 @@ The entry point is `styles/theme.css`. All imports use the CSS `@import` syntax
### Import Order ### Import Order
``` ```plain
styles/theme.css styles/theme.css
| |
+-- @import "tailwindcss" # Tailwind CSS v4 base +-- @import "tailwindcss" # Tailwind CSS v4 base
@@ -325,7 +337,7 @@ Example -- adding a new `cards.css` component:
## JS Module Dependency Graph ## JS Module Dependency Graph
``` ```plain
theme.js (entry point) theme.js (entry point)
├── Navigation.js # Mobile menu, sliding viewport, keyboard nav ├── Navigation.js # Mobile menu, sliding viewport, keyboard nav
├── backToTop.js # BackToTopButton custom element ├── backToTop.js # BackToTopButton custom element
@@ -342,16 +354,16 @@ admin.js
WordPress registers these script modules via `wp_register_script_module()`: WordPress registers these script modules via `wp_register_script_module()`:
| Module ID | Source | Dependencies | | Module ID | Source | Dependencies |
|-----------|--------|--------------| | ----------- | -------- | -------------- |
| `basicwp-theme` | `theme.js` | None | | `sf-evo-theme` | `theme.js` | None |
| `basicwp-button` | `button.js` | `basicwp-theme` | | `sf-evo-button` | `button.js` | `sf-evo-theme` |
| `basicwp-admin` | `admin.js` | `basicwp-button` | | `sf-evo-admin` | `admin.js` | `sf-evo-button` |
**Loading in a template:** **Loading in a template:**
```php ```php
wp_enqueue_script_module('basicwp-theme'); wp_enqueue_script_module('sf-evo-theme');
wp_enqueue_script_module('basicwp-button'); wp_enqueue_script_module('sf-evo-button');
``` ```
--- ---
@@ -371,7 +383,7 @@ const nav = new Navigation(toggleId, menuSelector);
### Methods ### Methods
| Method | Description | | Method | Description |
|--------|-------------| | -------- | ------------- |
| `desktopMenuDropdowns()` | Enables dropdown menus for desktop navigation | | `desktopMenuDropdowns()` | Enables dropdown menus for desktop navigation |
| `mobileMenuToggle()` | Toggles the mobile hamburger menu open/closed | | `mobileMenuToggle()` | Toggles the mobile hamburger menu open/closed |
| `initializeSlidingViewport()` | Sets up the sliding mobile menu structure | | `initializeSlidingViewport()` | Sets up the sliding mobile menu structure |
@@ -400,11 +412,11 @@ nav.initializeSlidingViewport();
## Helper Functions ## Helper Functions
| Function | File | Signature | Description | | Function | File | Signature | Description |
|----------|------|-----------|-------------| | ---------- | ------ | ----------- | ------------- |
| `getFieldValue` | helpers.php | `getFieldValue($field_path)` | Retrieves nested ACF values using dot notation. E.g., `getFieldValue('contact_info.phone')` resolves `get_field('contact_info', 'option')['phone']`. Uses `'option'` for Global Fields. | | `getFieldValue` | helpers.php | `getFieldValue($field_path)` | Retrieves nested ACF values using dot notation. E.g., `getFieldValue('contact_info.phone')` resolves `get_field('contact_info', 'option')['phone']`. Uses `'option'` for Global Fields. |
| `blockWrapperAttributes` | helpers.php | `blockWrapperAttributes($classes, $is_preview)` | Returns block wrapper attributes. In preview mode returns `class="..."`; on frontend returns `get_block_wrapper_attributes()`. | | `blockWrapperAttributes` | helpers.php | `blockWrapperAttributes($classes, $is_preview)` | Returns block wrapper attributes. In preview mode returns `class="..."`; on frontend returns `get_block_wrapper_attributes()`. |
| `customMenuOrder` | helpers.php | `customMenuOrder($menu_ord)` | Customizes WordPress admin menu order. | | `customMenuOrder` | helpers.php | `customMenuOrder($menu_ord)` | Customizes WordPress admin menu order. |
| `blockCategories` | helpers.php | `blockCategories($categories)` | Adds the `vdi-blocks` category to the block editor. | | `blockCategories` | helpers.php | `blockCategories($categories)` | Adds the `sf-blocks` category to the block editor. |
| `consoleLog` | helpers.php | `consoleLog($data)` | Outputs data to the browser console via `<script>console.log()</script>`. | | `consoleLog` | helpers.php | `consoleLog($data)` | Outputs data to the browser console via `<script>console.log()</script>`. |
| `customExcerpt` | helpers.php | `customExcerpt($text, $number_of_words, $more)` | Generates custom excerpts that end at sentence boundaries instead of mid-sentence. | | `customExcerpt` | helpers.php | `customExcerpt($text, $number_of_words, $more)` | Generates custom excerpts that end at sentence boundaries instead of mid-sentence. |
| `escEmbeds` | helpers.php | `escEmbeds()` | Returns an allowed HTML array for iframe/embed content (used with `wp_kses`). | | `escEmbeds` | helpers.php | `escEmbeds()` | Returns an allowed HTML array for iframe/embed content (used with `wp_kses`). |
@@ -435,7 +447,7 @@ $excerpt = customExcerpt(get_the_content(), 30, '...');
## Class Reference ## Class Reference
| Class | File | Key Methods | Description | | Class | File | Key Methods | Description |
|-------|------|-------------|-------------| | ------- | ------ | ------------- | ------------- |
| `Enqueue` | `class-enqueue.php` | `enqFEAssets()`, `enqBEAssets()`, `enqEditorAssets()` | Manages all asset loading: frontend, admin, and editor | | `Enqueue` | `class-enqueue.php` | `enqFEAssets()`, `enqBEAssets()`, `enqEditorAssets()` | Manages all asset loading: frontend, admin, and editor |
| `ACF` | `class-acf.php` | `saveJson($path)`, `loadJson($paths)` | Sets ACF JSON save/load paths for field group synchronization | | `ACF` | `class-acf.php` | `saveJson($path)`, `loadJson($paths)` | Sets ACF JSON save/load paths for field group synchronization |
| `Breadcrumbs` | `class-breadcrumbs.php` | `generate()`, `render()`, plus per-context methods (see below) | Generates Schema.org-compatible breadcrumb markup | | `Breadcrumbs` | `class-breadcrumbs.php` | `generate()`, `render()`, plus per-context methods (see below) | Generates Schema.org-compatible breadcrumb markup |
@@ -446,7 +458,7 @@ $excerpt = customExcerpt(get_the_content(), 30, '...');
### Breadcrumbs Method Details ### Breadcrumbs Method Details
| Method | Returns | Description | | Method | Returns | Description |
|--------|---------|-------------| | -------- | --------- | ------------- |
| `generate()` | `array` | Builds breadcrumb data array for the current context | | `generate()` | `array` | Builds breadcrumb data array for the current context |
| `render()` | `string` | Outputs breadcrumb HTML with Schema.org markup | | `render()` | `string` | Outputs breadcrumb HTML with Schema.org markup |
| `getHomeBreadcrumb()` | `array` | Breadcrumb for the front page | | `getHomeBreadcrumb()` | `array` | Breadcrumb for the front page |
@@ -472,7 +484,7 @@ echo $breadcrumbs->render();
## CLI Commands ## CLI Commands
| Command | Description | | Command | Description |
|---------|-------------| | --------- | ------------- |
| `npm run build` | Compiles Tailwind CSS v4 from `styles/theme.css` to `static/dist/theme.css` with `--optimize` | | `npm run build` | Compiles Tailwind CSS v4 from `styles/theme.css` to `static/dist/theme.css` with `--optimize` |
| `npm run start` | Starts BrowserSync dev server with live reloading (alias for `npm run watch`) | | `npm run start` | Starts BrowserSync dev server with live reloading (alias for `npm run watch`) |
| `npm run watch` | Runs `.watch.js` -- BrowserSync with CSS injection on changes | | `npm run watch` | Runs `.watch.js` -- BrowserSync with CSS injection on changes |
@@ -488,11 +500,11 @@ echo $breadcrumbs->render();
The deployment workflow is defined in `.github/workflows/wpengine.yml`. The deployment workflow is defined in `.github/workflows/wpengine.yml`.
| Setting | Value | | Setting | Value |
|---------|-------| | --------- | ------- |
| Trigger | `workflow_dispatch` (manual). Push to `main` trigger is commented out. | | Trigger | `workflow_dispatch` (manual). Push to `main` trigger is commented out. |
| Skip condition | Commits containing `#skipGA` in the message are skipped | | Skip condition | Commits containing `#skipGA` in the message are skipped |
| Target path | `wp-content/themes/vdi-v5` | | Target path | `wp-content/themes/ soloframe-evo` |
| WP Engine environment | `vdiv5` | | WP Engine environment | `soloframe-evo` |
| SSH key secret | `WPE_SSHG_KEY_PRIVATE` | | SSH key secret | `WPE_SSHG_KEY_PRIVATE` |
### Deployment Steps ### Deployment Steps
@@ -506,12 +518,12 @@ The deployment workflow is defined in `.github/workflows/wpengine.yml`.
### rsync Flags ### rsync Flags
``` ```plain
-azvr --inplace --delete --exclude=".*" -azvr --inplace --delete --exclude=".*"
``` ```
| Flag | Meaning | | Flag | Meaning |
|------|---------| | ------ | --------- |
| `-a` | Archive mode (preserve permissions, timestamps, etc.) | | `-a` | Archive mode (preserve permissions, timestamps, etc.) |
| `-z` | Compress during transfer | | `-z` | Compress during transfer |
| `-v` | Verbose output | | `-v` | Verbose output |
@@ -1,130 +0,0 @@
# Onboarding Documentation Design
## Goal
Write thorough documentation that enables a new developer (team member or external contributor) to set up, understand, and work with the VDI-Starter-v5 WordPress theme with minimal hand-holding.
## Audience
Both internal team members and external contributors, served with layered docs — quick-start up top, deep dives below.
## Approach
Keep the existing README.md as a project overview (trimmed of deep-dive content that moves to `docs/`). Add a `docs/` directory with four focused guides. The README links to each guide.
## Doc Structure
```
docs/
├── getting-started.md # Setup from zero, local WP, env config, first build
├── architecture.md # Bootstrap flow, layers, conventions, namespacing, globals
├── creating-blocks.md # Step-by-step ACF block creation with block.json, fields, CSS
└── reference.md # Hooks/filters, theme.json tokens, CSS architecture, JS modules, deployment
```
Plus updates to README.md: trim deep-dive content, add Documentation section with links, fix known discrepancies.
## Writing Style
Detailed and explanatory — include context and rationale ("why"), not just "what" and "how". Short paragraphs with code examples and tables where appropriate. Designed to be read end-to-end by a newcomer, but also scannable for quick lookup.
## Guide Contents
### 1. getting-started.md
**Purpose:** Get a developer from zero to a running local environment.
- Prerequisites (Node 22+, pnpm/npm, PHP 8+, Composer, Local by Flywheel or equivalent)
- Local WordPress setup options (Local by Flywheel, DevKinsta, Docker) with pros/cons
- Clone, install, build, run steps (npm install, composer install, npm run build, npm run start/watch)
- .env configuration (LOCALHOST_URL, BROWSERSYNC_PORT)
- BrowserSync behavior (what triggers reload, which port, how to configure)
- What happens on theme activation — **important warning**:
- Plugin auto-installation (7 plugins downloaded from URLs)
- Default page creation (Home, News, 404, Contact Us)
- WordPress reading settings configuration
- Owner role creation
- Warning: do not activate on existing sites without reviewing `lib/activation.php`
- Troubleshooting common issues:
- CSS not compiling → run `npm run build`
- Blocks not appearing → ACF Pro must be active
- Menu not rendering → must assign menu to location in WP admin
- JavaScript not loading → check script module support (WP 6.5+)
### 2. architecture.md
**Purpose:** Explain how the theme is organized and how it boots.
- Bootstrap flow: `functions.php` → glob autoload of `lib/*.php``init` hook → class instantiation
- The 7 architectural layers (from knowledge graph):
1. **Entry**`functions.php` and `style.css` (theme declaration)
2. **Service Layer** — PHP classes in `lib/` (Enqueue, MenuItems, Breadcrumbs, ACF, Resources)
3. **UI Templates** — WordPress template hierarchy, ACF blocks, components, partials, icons
4. **Styling** — Layered CSS with Tailwind v4 (base → components → blocks → navigation)
5. **Client Scripts** — JS modules (Navigation, BackToTop, Button, GetHeaderHeight, TagExternalLinks)
6. **Data Layer** — ACF field group JSON schemas in `acf/`
7. **Infrastructure** — Build scripts, CI/CD pipelines, project configs, tests
- Namespace conventions:
- PHP namespace: `BasicWP`
- Text domain: `basicwp`
- Block category: `vdi-blocks`
- WP Engine folder: `vdi-v5`
- Explain the relationship between these naming choices
- Global variables: `$views` (path to views/ directory) and `$theme` (theme directory path)
- WordPress hooks cleanup in `hooks.php`: what gets removed (emojis, block library styles, REST links, XML-RPC) and why — performance and security rationale
- Enqueue system: `wp_enqueue_script_module()` for JS (dependency graph: theme → button, backToTop, Navigation, etc.) vs traditional `wp_enqueue_script` for admin
- theme.json design system: color palette (12 colors via CSS custom properties), font sizes (15 presets), spacing, layout
### 3. creating-blocks.md
**Purpose:** Teach a developer how to create a new ACF block from scratch.
- Anatomy of a block: `block.json` (registration) + PHP template (rendering) + CSS file (scoped styles)
- Step-by-step tutorial creating a new "Testimonial" block:
1. Create directory `views/blocks/testimonial/`
2. Create `block.json` with required fields (name, title, description, category, icon, supports)
3. Create `testimonial.php` template using `blockWrapperAttributes()` and `getFieldValue()`
4. Create `testimonial.css` for block-specific styles
5. Create ACF field group in WP admin → exported to `acf/` as JSON
- How blocks are auto-registered: `regACFBlocks()` in `functions.php` scans `views/blocks/*/block.json`
- Helper functions: `blockWrapperAttributes()` for class/id passthrough, `getFieldValue()` for dot-notation ACF access
- Parent-child block patterns: buttons→button, grid→grid-cell (using `allowed_blocks` or `InnerBlocks`)
- Tailwind in blocks: how the whitelist system works (`whitelist.php`), how to add editor-only classes
- Block CSS loading: each block's CSS file is auto-enqueued by the block registration
### 4. reference.md
**Purpose:** Complete API and configuration reference for quick lookup.
- **Hooks and Filters** — Complete table of all `add_action`/`add_filter` calls from `hooks.php`, `extras.php`, `search-features.php`, and class files, with priority, callback, and purpose
- **theme.json Design Tokens** — Color palette (12 colors with CSS variable names), font sizes (15 presets with rem values), spacing scale, layout sizes
- **CSS Architecture** — Import tree from `theme.css`, explanation of each layer (base, components, blocks, navigation), how to add new stylesheets
- **JS Module Dependency Graph** — Visual/text tree showing `theme.js` → Navigation, BackToTop, Button, GetHeaderHeight, TagExternalLinks; `admin.js` → Button
- **Navigation Class API** — Methods for the sliding viewport feature (initializeSlidingViewport, navigateToLevel, navigateBack, etc.), configuration options
- **Helper Functions** — `getFieldValue()`, `blockWrapperAttributes()`, `customMenuOrder()`, `blockCategories()`, `consoleLog()`, `customExcerpt()`, `escEmbeds()`
- **Class Reference** — Enqueue (enqFEAssets, enqBEAssets, enqEditorAssets), ACF (saveJson, loadJson), Breadcrumbs (generate, render, and per-page-type methods), MenuItems (render), Resources (CPT + permalink rewrite), ShowTemplate (debug template path)
- **CLI Commands** — `npm run build`, `npm run start`/`npm run watch`, `composer lint`, `composer fix`, Playwright test commands
- **Deployment Workflow** — GitHub Actions `wpengine.yml` pipeline: install deps → build Tailwind → rsync to WP Engine
- **Testing** — Playwright a11y test setup and commands, PHPCS configuration and usage
## README.md Changes
- Trim: Remove the detailed function-level API docs (they move to `reference.md`)
- Trim: Remove the detailed project structure tree (keep a shorter version, point to `architecture.md` for the full picture)
- Add: "Documentation" section with links to all four guides
- Fix: Wrong CSS paths (`views/styles/``styles/`)
- Fix: Missing `contact-info` block from the block list
- Fix: Deployment filename typo (`wpengine,yml``wpengine.yml`)
- Fix: Note that `class-enqueue.php` also has `enqEditorAssets()`
- Add: Mention `backToTop.js` custom element (missing from current README)
- Add: Clarify namespace conventions (BasicWP, basicwp, vdi-blocks, vdi-v5)
## Implementation Plan
This is a documentation-only change — no code modifications. Implementation consists of:
1. Create `docs/` directory with 4 markdown files
2. Update `README.md` with trimmed content and links
3. Fix known discrepancies in README
Estimated scope: ~4 documentation files of ~200-400 lines each, plus README edits.
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Theme footer template * Theme footer template
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$footerLogo = getFieldValue( 'footer.footer_logo.url' ) ? getFieldValue( 'footer.footer_logo.url' ) : ''; $footerLogo = getFieldValue( 'footer.footer_logo.url' ) ? getFieldValue( 'footer.footer_logo.url' ) : '';
$footerDesc = getFieldValue( 'footer.footer_description' ) ? getFieldValue( 'footer.footer_description' ) : ''; $footerDesc = getFieldValue( 'footer.footer_description' ) ? getFieldValue( 'footer.footer_description' ) : '';
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Front Page Template * Front Page Template
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
get_header(); get_header();
?> ?>
+3 -3
View File
@@ -1,15 +1,15 @@
<?php <?php
/** /**
* Functions file for the BasicWP theme. * Functions file for the SoloFrameEvo theme.
* *
* This file initializes the theme by including necessary dependencies * This file initializes the theme by including necessary dependencies
* and loading additional function files. * and loading additional function files.
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Load functions. // Load functions.
foreach ( glob( __DIR__ . '/lib/*.php' ) as $filename ) { foreach ( glob( __DIR__ . '/lib/*.php' ) as $filename ) {
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Theme header template * Theme header template
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
global $views; global $views;
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Blog posts list * Blog posts list
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Determine classes based on sidebar presence // Determine classes based on sidebar presence
if ( hasSidebar() ) { if ( hasSidebar() ) {
+5 -17
View File
@@ -18,11 +18,11 @@ if ( isset( $_GET['activated'] ) && is_admin() ) {
* Sample nested structure * Sample nested structure
* *
* 'Parent Page' => array( * 'Parent Page' => array(
* 'Subpage 1' => array( * 'Child page 1' => array(
* 'Sub-subpage 1', * 'Grandchild page 1',
* 'Sub-subpage 2' * 'Grandchild page 2'
* ), * ),
* 'Subpage 2.2' => array() * 'Child page 2' => array()
* ), * ),
*/ */
); );
@@ -105,17 +105,9 @@ if ( isset( $_GET['activated'] ) && is_admin() ) {
$muPlugins = array( $muPlugins = array(
array( array(
'url' => 'https://docs.vincentdevelopment.ca/files/advanced-custom-fields-pro.zip', 'url' => 'https://downloads.wordpress.org/plugin/secure-custom-fields.6.9.3.zip',
'active' => true, 'active' => true,
), ),
array(
'url' => 'https://docs.vincentdevelopment.ca/files/gravity-forms.zip',
'active' => true,
),
array(
'url' => 'https://updraftplus.com/wp-content/uploads/updraftplus.zip',
'active' => false,
),
array( array(
'url' => 'https://downloads.wordpress.org/plugin/simple-history.5.11.0.zip', 'url' => 'https://downloads.wordpress.org/plugin/simple-history.5.11.0.zip',
'active' => true, 'active' => true,
@@ -128,10 +120,6 @@ if ( isset( $_GET['activated'] ) && is_admin() ) {
'url' => 'https://downloads.wordpress.org/plugin/better-search-replace.1.4.10.zip', 'url' => 'https://downloads.wordpress.org/plugin/better-search-replace.1.4.10.zip',
'active' => true, 'active' => true,
), ),
array(
'url' => 'https://downloads.wordpress.org/plugin/google-site-kit.1.153.0.zip',
'active' => false,
),
); );
// Custom log file // Custom log file
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* ACF (Advanced Custom Fields) support class & functions * ACF (Advanced Custom Fields) support class & functions
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class ACF * Class ACF
+1 -1
View File
@@ -1,5 +1,5 @@
<?php <?php
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class Breadcrumbs * Class Breadcrumbs
+10 -10
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* BasicWP Theme Enqueue Class * SoloFrameEvo Theme Enqueue Class
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class Enqueue * Class Enqueue
@@ -39,7 +39,7 @@ class Enqueue {
$css_path = '/static/dist/theme.css'; $css_path = '/static/dist/theme.css';
if ( file_exists( $theme_dir . $css_path ) ) { if ( file_exists( $theme_dir . $css_path ) ) {
$version = filemtime( $theme_dir . $css_path ); $version = filemtime( $theme_dir . $css_path );
wp_enqueue_style( 'basicwp-theme', $theme_uri . $css_path, array(), $version ); wp_enqueue_style( 'sf-evo-theme', $theme_uri . $css_path, array(), $version );
} }
$font_ver = gmdate( 'U' ); $font_ver = gmdate( 'U' );
@@ -53,8 +53,8 @@ class Enqueue {
if ( file_exists( $theme_dir . $js_path ) ) { if ( file_exists( $theme_dir . $js_path ) ) {
$version = filemtime( $theme_dir . $js_path ); $version = filemtime( $theme_dir . $js_path );
wp_enqueue_script( 'jquery' ); // Needed by downstream scripts; modules can't depend on classic scripts. wp_enqueue_script( 'jquery' ); // Needed by downstream scripts; modules can't depend on classic scripts.
wp_enqueue_script_module( 'basicwp-theme', $theme_uri . $js_path, array(), $version ); wp_enqueue_script_module( 'sf-evo-theme', $theme_uri . $js_path, array(), $version );
wp_enqueue_script_module( 'basicwp-button', $theme_uri . '/static/js/components/button.js', array( 'basicwp-theme' ), $version ); wp_enqueue_script_module( 'sf-evo-button', $theme_uri . '/static/js/components/button.js', array( 'sf-evo-theme' ), $version );
} }
} }
@@ -74,7 +74,7 @@ class Enqueue {
$admin_css_path = '/styles/backend/admin.css'; $admin_css_path = '/styles/backend/admin.css';
if ( file_exists( $theme_dir . $admin_css_path ) ) { if ( file_exists( $theme_dir . $admin_css_path ) ) {
$version = filemtime( $theme_dir . $admin_css_path ); $version = filemtime( $theme_dir . $admin_css_path );
wp_enqueue_style( 'basicwp-admin', $theme_uri . $admin_css_path, array(), $version ); wp_enqueue_style( 'sf-evo-admin', $theme_uri . $admin_css_path, array(), $version );
} }
/** /**
@@ -84,8 +84,8 @@ class Enqueue {
if ( file_exists( $theme_dir . $admin_js_path ) ) { if ( file_exists( $theme_dir . $admin_js_path ) ) {
$version = filemtime( $theme_dir . $admin_js_path ); $version = filemtime( $theme_dir . $admin_js_path );
wp_enqueue_script( 'jquery' ); // Needed by downstream scripts; modules can't depend on classic scripts. wp_enqueue_script( 'jquery' ); // Needed by downstream scripts; modules can't depend on classic scripts.
wp_enqueue_script_module( 'basicwp-admin', $theme_uri . $admin_js_path, array(), $version ); wp_enqueue_script_module( 'sf-evo-admin', $theme_uri . $admin_js_path, array(), $version );
wp_enqueue_script_module( 'basicwp-button', $theme_uri . '/static/js/components/button.js', array( 'basicwp-admin' ), $version ); wp_enqueue_script_module( 'sf-evo-button', $theme_uri . '/static/js/components/button.js', array( 'sf-evo-admin' ), $version );
} }
} }
@@ -103,7 +103,7 @@ class Enqueue {
if ( file_exists( $theme_dir . $editor_css_path ) ) { if ( file_exists( $theme_dir . $editor_css_path ) ) {
$version = filemtime( $theme_dir . $editor_css_path ); $version = filemtime( $theme_dir . $editor_css_path );
wp_enqueue_style( 'basicwp-editor', $theme_uri . $editor_css_path, array(), $version ); wp_enqueue_style( 'sf-evo-editor', $theme_uri . $editor_css_path, array(), $version );
} }
} }
} }
+3 -3
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* BasicWP MenuItems Class * SoloFrameEvo MenuItems Class
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class MenuItems * Class MenuItems
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Resources custom post type & taxonomies * Resources custom post type & taxonomies
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class Resources * Class Resources
+3 -3
View File
@@ -2,11 +2,11 @@
/** /**
* Filters. etc * Filters. etc
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** Get child pages of the current page, sorted by menu order. /** Get child pages of the current page, sorted by menu order.
* *
@@ -154,7 +154,7 @@ function getTheTitle() {
} elseif ( is_search() ) { } elseif ( is_search() ) {
$title = sprintf( $title = sprintf(
/* translators: %s is replaced with the search query */ /* translators: %s is replaced with the search query */
__( 'Search Results for "%s"', 'basicwp' ), __( 'Search Results for "%s"', 'sf-evo' ),
get_search_query() get_search_query()
); );
} elseif ( is_404() ) { } elseif ( is_404() ) {
+5 -5
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* BasicWP Theme Helpers * SoloFrameEvo Theme Helpers
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Define global variables for theme and views folder paths. // Define global variables for theme and views folder paths.
global $theme, $views; global $theme, $views;
@@ -122,8 +122,8 @@ add_filter( 'menu_order', __NAMESPACE__ . '\\customMenuOrder', 10, 1 );
*/ */
function blockCategories( $categories ) { function blockCategories( $categories ) {
$vdi_cat = array( $vdi_cat = array(
'slug' => 'vdi-blocks', 'slug' => 'sf-blocks',
'title' => 'VDI Custom Blocks', 'title' => 'SoloFrame Custom Blocks',
'icon' => 'dashicons-admin-customizer', 'icon' => 'dashicons-admin-customizer',
); );
+3 -3
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* BasicWP Theme Hooks * SoloFrameEvo Theme Hooks
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Add preconnect for Google fonts to head * Add preconnect for Google fonts to head
+3 -3
View File
@@ -1,12 +1,12 @@
<?php <?php
/** /**
* Search features for BasicWP theme. * Search features for SoloFrameEvo theme.
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Modifies the WordPress query object for page search functionality. * Modifies the WordPress query object for page search functionality.
+3 -3
View File
@@ -2,11 +2,11 @@
/** /**
* Add a comment to show which template is being used on the current page. * Add a comment to show which template is being used on the current page.
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
/** /**
* Class ShowTemplate * Class ShowTemplate
@@ -14,7 +14,7 @@ namespace BasicWP;
* Displays the active WordPress template in the footer for debugging purposes. * Displays the active WordPress template in the footer for debugging purposes.
* Determines which template WordPress has chosen to use and outputs it as an HTML comment. * Determines which template WordPress has chosen to use and outputs it as an HTML comment.
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
class ShowTemplate { class ShowTemplate {
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "vdi-starter-v5", "name": "soloframe-evo",
"version": "5.0", "version": "5.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "vdi-starter-v5", "name": "soloframe-evo",
"version": "5.0", "version": "5.0",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
+5 -5
View File
@@ -1,7 +1,7 @@
{ {
"name": "vdi-starter-v5", "name": "soloframe-evo",
"version": "5.0", "version": "5.0",
"description": "VDI-Starter-v5 is a minimal WordPress theme designed as a starting point for custom theme development. It focuses on modern development approaches with a lean architecture that avoids the overhead of theme frameworks.", "description": "SoloFrame Evo is a minimal WordPress theme designed as a starting point for custom theme development. It focuses on modern development approaches with a lean architecture that avoids the overhead of theme frameworks.",
"scripts": { "scripts": {
"start": "npm run watch", "start": "npm run watch",
"watch": "node bin/.watch.js", "watch": "node bin/.watch.js",
@@ -9,7 +9,7 @@
}, },
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://github.com/Vincent-Design-Inc/VDI-Starter-v5.git" "url": "git+https://github.com/ksolomon/SoloFrame Evo.git"
}, },
"keywords": [ "keywords": [
"wordpress", "wordpress",
@@ -21,9 +21,9 @@
"author": "Keith Solomon <keith@vincentdesign.ca>", "author": "Keith Solomon <keith@vincentdesign.ca>",
"license": "MIT", "license": "MIT",
"bugs": { "bugs": {
"url": "https://github.com/Vincent-Design-Inc/VDI-Starter-v5/issues" "url": "https://github.com/ksolomon/SoloFrame Evo/issues"
}, },
"homepage": "https://github.com/Vincent-Design-Inc/VDI-Starter-v5#readme", "homepage": "https://github.com/ksolomon/SoloFrame Evo#readme",
"devDependencies": { "devDependencies": {
"@axe-core/playwright": "^4.10.1", "@axe-core/playwright": "^4.10.1",
"@playwright/test": "^1.52.0", "@playwright/test": "^1.52.0",
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Single Pages * Single Pages
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
get_header(); get_header();
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Blog search template * Blog search template
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Determine classes based on sidebar presence // Determine classes based on sidebar presence
if ( hasSidebar() ) { if ( hasSidebar() ) {
+3 -3
View File
@@ -2,14 +2,14 @@
/** /**
* Page Sidebar * Page Sidebar
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
?> ?>
<aside class="sidebar sidebar-page"> <aside class="sidebar sidebar-page">
<h2><?php esc_html_e( 'Page Sidebar', 'basicwp' ); ?></h2> <h2><?php esc_html_e( 'Page Sidebar', 'sf-evo' ); ?></h2>
<?php dynamic_sidebar( 'sidebar-page' ); ?> <?php dynamic_sidebar( 'sidebar-page' ); ?>
</aside> </aside>
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Sidebar * Sidebar
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
?> ?>
+2 -2
View File
@@ -2,11 +2,11 @@
/** /**
* Single Posts * Single Posts
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
get_header(); get_header();
+1 -1
View File
@@ -3,5 +3,5 @@
* Description: Custom WordPress theme starter for VDI Projects * Description: Custom WordPress theme starter for VDI Projects
* Version: 5.0 * Version: 5.0
* Author: Vincent Design Inc. * Author: Vincent Design Inc.
* Text Domain: basicwp * Text Domain: sf-evo
*/ */
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that renders the Accordion block. * This is the template that renders the Accordion block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$open = get_field( 'open' ); $open = get_field( 'open' );
$group = get_field( 'group_items' ); $group = get_field( 'group_items' );
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./boilerplate.css" "file:./boilerplate.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "block-default", "icon": "block-default",
"keywords": [ "keywords": [
"boilerplate" "boilerplate"
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template for building your own custom blocks. * This is the template for building your own custom blocks.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$classes = 'boilerplate'; $classes = 'boilerplate';
+2 -2
View File
@@ -1,8 +1,8 @@
{ {
"name": "acf/button", "name": "acf/button",
"title": "Button (VDI)", "title": "Button (SFE)",
"description": "A button.", "description": "A button.",
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "button", "icon": "button",
"keywords": [ "keywords": [
"button" "button"
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Button block * Button block
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve ACF fields // Retrieve ACF fields
$element = get_field( 'element' ) ? get_field( 'element' ) : 'a'; $element = get_field( 'element' ) ? get_field( 'element' ) : 'a';
+2 -2
View File
@@ -1,9 +1,9 @@
{ {
"name": "acf/buttons", "name": "acf/buttons",
"title": "Buttons (VDI)", "title": "Buttons (SFE)",
"description": "A button or group of buttons.", "description": "A button or group of buttons.",
"allowedBlocks": [ "acf/button" ], "allowedBlocks": [ "acf/button" ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "button", "icon": "button",
"keywords": [ "keywords": [
"buttons" "buttons"
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that renders the Buttons block. * This is the template that renders the Buttons block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$ibClasses = 'flex flex-wrap gap-4 w-full justify-center sm:justify-start'; $ibClasses = 'flex flex-wrap gap-4 w-full justify-center sm:justify-start';
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./contact-info.css" "file:./contact-info.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "feedback", "icon": "feedback",
"keywords": [ "keywords": [
"contact info", "contact info",
+5 -5
View File
@@ -4,10 +4,10 @@
* *
* Display contact information from global fields with icons and optional form. * Display contact information from global fields with icons and optional form.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$classes = 'contact-info'; $classes = 'contact-info';
$wrapper = blockWrapperAttributes( $classes, $is_preview ); $wrapper = blockWrapperAttributes( $classes, $is_preview );
@@ -19,13 +19,13 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
<h2 class="text-2xl font-bold mb-4">Contact Information</h2> <h2 class="text-2xl font-bold mb-4">Contact Information</h2>
<div class="not-prose text-black my-4"> <div class="not-prose text-black my-4">
<h3 class="mb-0"><?php echo esc_html__( 'Mailing Address', 'basicwp' ); ?></h3> <h3 class="mb-0"><?php echo esc_html__( 'Mailing Address', 'sf-evo' ); ?></h3>
<p class="my-0.5"><?php echo wp_kses_post( get_field( 'contact_info', 'option' )['address'] ); ?></p> <p class="my-0.5"><?php echo wp_kses_post( get_field( 'contact_info', 'option' )['address'] ); ?></p>
<h3 class="mb-0"><?php echo esc_html__( 'Email', 'basicwp' ); ?></h3> <h3 class="mb-0"><?php echo esc_html__( 'Email', 'sf-evo' ); ?></h3>
<p class="my-0.5"><a class="hover:opacity-80 transition-colors duration-100" href="mailto:<?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?>"><?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?></a></p> <p class="my-0.5"><a class="hover:opacity-80 transition-colors duration-100" href="mailto:<?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?>"><?php echo esc_html( get_field( 'contact_info', 'option' )['email'] ); ?></a></p>
<h3 class="mb-0"><?php echo esc_html__( 'Phone', 'basicwp' ); ?></h3> <h3 class="mb-0"><?php echo esc_html__( 'Phone', 'sf-evo' ); ?></h3>
<p class="my-0.5"><a class="hover:opacity-80 transition-colors duration-100" href="tel:<?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?>"><?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?></a></p> <p class="my-0.5"><a class="hover:opacity-80 transition-colors duration-100" href="tel:<?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?>"><?php echo esc_html( get_field( 'contact_info', 'option' )['phone'] ); ?></a></p>
</div> </div>
</div> </div>
+2 -2
View File
@@ -1,11 +1,11 @@
{ {
"name": "acf/grid-cell", "name": "acf/grid-cell",
"title": "Grid Cell (VDI)", "title": "Grid Cell (SFE)",
"description": "Custom grid cell block.", "description": "Custom grid cell block.",
"style": [ "style": [
"file:./grid-cell.css" "file:./grid-cell.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "grid-view", "icon": "grid-view",
"keywords": [ "keywords": [
"grid" "grid"
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that displays the Grid Cell block. * This is the template that displays the Grid Cell block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Initialize variables // Initialize variables
$className = ! empty( $block['className'] ) ? $block['className'] : ''; $className = ! empty( $block['className'] ) ? $block['className'] : '';
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "acf/grid", "name": "acf/grid",
"title": "Grid Block (VDI)", "title": "Grid Block (SFE)",
"description": "Custom grid block.", "description": "Custom grid block.",
"style": [ "style": [
"file:./grid.css" "file:./grid.css"
], ],
"allowedBlocks": [ "acf/grid-cell" ], "allowedBlocks": [ "acf/grid-cell" ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "grid-view", "icon": "grid-view",
"keywords": [ "keywords": [
"grid" "grid"
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that displays the grid block. * This is the template that displays the grid block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$allowedBlocks = array( 'acf/grid-cell' ); $allowedBlocks = array( 'acf/grid-cell' );
$default_blocks = array( $default_blocks = array(
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./homepage-hero.css" "file:./homepage-hero.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "block-default", "icon": "block-default",
"keywords": [ "keywords": [
"homepage-hero", "homepage-hero",
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Block Name: Homepage Hero * Block Name: Homepage Hero
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve ACF fields // Retrieve ACF fields
$heading = get_field( 'heading' ); $heading = get_field( 'heading' );
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./media-text-innerblocks.css" "file:./media-text-innerblocks.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "screenoptions", "icon": "screenoptions",
"keywords": [ "keywords": [
"media", "media",
@@ -4,10 +4,10 @@
* *
* This is the template that displays the media text inner blocks. * This is the template that displays the media text inner blocks.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve ACF fields // Retrieve ACF fields
$bgColor = get_field( 'background_color' ) ? get_field( 'background_color' ) : '#c5c5c5'; $bgColor = get_field( 'background_color' ) ? get_field( 'background_color' ) : '#c5c5c5';
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./media-text.css" "file:./media-text.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "screenoptions", "icon": "screenoptions",
"keywords": [ "keywords": [
"media", "media",
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that displays the Media With Text block. * This is the template that displays the Media With Text block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve ACF fields // Retrieve ACF fields
$bgColor = get_field( 'background_color' ) ? get_field( 'background_color' ) : '#c5c5c5'; $bgColor = get_field( 'background_color' ) ? get_field( 'background_color' ) : '#c5c5c5';
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./page-children.css" "file:./page-children.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "block-default", "icon": "block-default",
"keywords": [ "keywords": [
"page-children" "page-children"
+3 -3
View File
@@ -2,10 +2,10 @@
/** /**
* Page Children block * Page Children block
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve the current page ID and its children // Retrieve the current page ID and its children
$parentId = get_queried_object_id(); $parentId = get_queried_object_id();
@@ -89,7 +89,7 @@ $wrapper = blockWrapperAttributes( $classes, $is_preview );
</h3> </h3>
</div> </div>
<div class="my-0 grow-1 text-18px text-gray-600 <?php echo esc_attr( $gcPad ); ?>"> <div class="my-0 grow text-18px text-gray-600 <?php echo esc_attr( $gcPad ); ?>">
<?php <?php
if ( ! empty( $grandchildren ) ) { if ( ! empty( $grandchildren ) ) {
?> ?>
+1 -1
View File
@@ -5,7 +5,7 @@
"style": [ "style": [
"file:./section.css" "file:./section.css"
], ],
"category": "vdi-blocks", "category": "sf-blocks",
"icon": "align-wide", "icon": "align-wide",
"keywords": [ "keywords": [
"setion", "setion",
+2 -2
View File
@@ -4,10 +4,10 @@
* *
* This is the template that displays the section block. * This is the template that displays the section block.
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Retrieve ACF fields // Retrieve ACF fields
$contentWidth = get_field( 'content_width' ); $contentWidth = get_field( 'content_width' );
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/ * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Variables available: // Variables available:
// $item from parent template // $item from parent template
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/ * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Variables available from MenuItems component: // Variables available from MenuItems component:
// $topLevelNavItems, $hasChildren, $nestedNavItems, $currentPage, $location // $topLevelNavItems, $hasChildren, $nestedNavItems, $currentPage, $location
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/ * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Variables available: // Variables available:
// $item from parent template // $item from parent template
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation-aux.html * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation-aux.html
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Init Variables // Init Variables
global $wp, $views; global $wp, $views;
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/ * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/
*/ */
namespace BasicWP; namespace SoloFrameEvo;
global $views; global $views;
?> ?>
+1 -1
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/ * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/navigation/
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Init Variables // Init Variables
$navIcon = isset( get_field( 'header', 'option' )['nav_icon'] ) ? get_field( 'header', 'option' )['nav_icon'] : ''; $navIcon = isset( get_field( 'header', 'option' )['nav_icon'] ) ? get_field( 'header', 'option' )['nav_icon'] : '';
+5 -5
View File
@@ -6,7 +6,7 @@
* https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/search-global.html * https://docs.vincentdevelopment.ca/docs/starter-v3-enhancements/search-global.html
*/ */
namespace BasicWP; namespace SoloFrameEvo;
?> ?>
@@ -14,16 +14,16 @@ namespace BasicWP;
<form method="get" action="<?php echo esc_url( home_url( '/' ) ); ?>" class="global-search-form relative flex justify-start max-w-full w-full"> <form method="get" action="<?php echo esc_url( home_url( '/' ) ); ?>" class="global-search-form relative flex justify-start max-w-full w-full">
<label for="globalSearch"> <label for="globalSearch">
<svg role="img" aria-labelledby="globalSearchLabel" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="absolute w-4 top-2 left-2 fill-primary-700"> <svg role="img" aria-labelledby="globalSearchLabel" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="absolute w-4 top-2 left-2 fill-primary-700">
<title id="globalSearchLabel"><?php echo esc_attr_x( 'Search', 'search-label', 'basicwp' ); ?></title> <title id="globalSearchLabel"><?php echo esc_attr_x( 'Search', 'search-label', 'sf-evo' ); ?></title>
<path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"/> <path d="M416 208c0 45.9-14.9 88.3-40 122.7L502.6 457.4c12.5 12.5 12.5 32.8 0 45.3s-32.8 12.5-45.3 0L330.7 376c-34.4 25.2-76.8 40-122.7 40C93.1 416 0 322.9 0 208S93.1 0 208 0S416 93.1 416 208zM208 352a144 144 0 1 0 0-288 144 144 0 1 0 0 288z"/>
</svg> </svg>
</label> </label>
<input id="globalSearch" type="search" placeholder="" value="<?php echo esc_attr( get_search_query() ); ?>" name="s" class="md:min-w-[25ch] w-full md:w-[18em] max-w-full text-sm p-1 pl-7 border-2 border-primary-700 rounded-l focus-visible:ring-2 ring-primary-700 !outline-default"> <input id="globalSearch" type="search" placeholder="" value="<?php echo esc_attr( get_search_query() ); ?>" name="s" class="md:min-w-[25ch] w-full md:w-[18em] max-w-full text-sm p-1 pl-7 border-2 border-primary-700 rounded-l focus-visible:ring-2 ring-primary-700 outline-default!">
<button type="submit" class="bg-primary rounded-r py-0 px-3 height-full text-sm text-white focus-visible:ring-2 ring-primary-700 !outline-default cursor-default"> <button type="submit" class="bg-primary rounded-r py-0 px-3 height-full text-sm text-white focus-visible:ring-2 ring-primary-700 outline-default! cursor-default">
<?php echo esc_attr_x( 'Search', 'search-submit', 'basicwp' ); ?> <?php echo esc_attr_x( 'Search', 'search-submit', 'sf-evo' ); ?>
</button> </button>
</form> </form>
</search> </search>
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Page Hero Partial * Page Hero Partial
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
// Set variables // Set variables
$bgColor = get_field( 'background_color' ); $bgColor = get_field( 'background_color' );
+2 -2
View File
@@ -2,10 +2,10 @@
/** /**
* Social Media Links Partial * Social Media Links Partial
* *
* @package BasicWP * @package SoloFrameEvo
*/ */
namespace BasicWP; namespace SoloFrameEvo;
$classes = $args['classes'] ?? ''; $classes = $args['classes'] ?? '';
$circle = $args['circle'] ?? ''; $circle = $args['circle'] ?? '';
+2 -2
View File
@@ -6,11 +6,11 @@
* These are for use in the editor and do not appear in the theme codebase, so * These are for use in the editor and do not appear in the theme codebase, so
* Tailwind does not know to include them without this list. * Tailwind does not know to include them without this list.
* *
* @package BasicWP * @package SoloFrameEvo
* @since 1.0.0 * @since 1.0.0
*/ */
namespace BasicWP; namespace SoloFrameEvo;
?> ?>