Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,16 @@ dist/
# Remove this line if you want to version client sites inside this monorepo.
sites/

# Per-client design sources and gate configs (same rule as sites/).
design-src/
scripts/visual-check/*.json
!scripts/visual-check/example.json
!scripts/visual-check/package.json
!scripts/visual-check/package-lock.json

# Local Claude Code settings
.claude/settings.local.json

# OS noise
.DS_Store

Expand Down
386 changes: 157 additions & 229 deletions CLAUDE.md

Large diffs are not rendered by default.

424 changes: 218 additions & 206 deletions README.md

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions base-theme/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# WordPress coding standards editor defaults.
root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab

[*.{yml,yaml}]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false
indent_style = space
indent_size = 2

[*.txt]
indent_style = space
10 changes: 10 additions & 0 deletions base-theme/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules/
vendor/
build/
dist/
artifacts/
.cache/
*.zip
.DS_Store
phpcs.xml
.wp-env.override.json
6 changes: 6 additions & 0 deletions base-theme/.stylelintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"extends": "@wordpress/stylelint-config",
"rules": {
"no-descending-specificity": null
}
}
15 changes: 15 additions & 0 deletions base-theme/.wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"phpVersion": "8.1",
"plugins": [
"https://downloads.wordpress.org/plugin/woocommerce.latest-stable.zip",
"https://downloads.wordpress.org/plugin/wordpress-importer.latest-stable.zip",
"https://downloads.wordpress.org/plugin/theme-check.latest-stable.zip"
],
"themes": [ ".", "./examples/tbt-child" ],
"config": {
"WP_DEBUG": true,
"WP_DEBUG_DISPLAY": true,
"WP_DEBUG_LOG": true,
"SCRIPT_DEBUG": true
}
}
25 changes: 25 additions & 0 deletions base-theme/404.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php
/**
* 404 template.
*
* @package Total_Business_Theme
*/

get_header();

tbt_hook( 'content_start' );
?>
<section class="error-404 not-found">
<header class="page-header">
<h1 class="page-title"><?php esc_html_e( 'Page not found', 'tbt' ); ?></h1>
</header>

<div class="page-content">
<p><?php esc_html_e( 'The page you are looking for no longer exists or never did. Try a search instead.', 'tbt' ); ?></p>
<?php get_search_form(); ?>
</div>
</section>
<?php
tbt_hook( 'content_end' );

get_footer();
103 changes: 103 additions & 0 deletions base-theme/CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Total Business Theme — standing rules (distilled from SPEC.md; SPEC.md wins on conflict)

Production-grade WordPress **hybrid classic parent theme** (NOT a block theme,
NOT headless). Target WP 7.0, floor 6.6, PHP 8.1+. Must pass PHPCS
(WordPress-Extra + Docs + WPThemeReview + PHPCompatibilityWP) and Theme Check
with 0 errors / 0 warnings. wp.org-directory eligible. Text domain: `tbt`.

## Operating protocol

- Work in SPEC.md §12 phases, in order. End of each phase: run verification,
fix everything, commit `phase-N: <summary>`, print verification output,
**stop for approval**.
- When the spec is silent: decide like a senior WP theme reviewer, log one
line in `DECISIONS.md` (decision, alternative rejected, why), continue.
- Never claim something works without command output. If a check can't run
here, mark it `UNVERIFIED` explicitly.
- No `TODO`, no commented-out dead code, no lorem ipsum outside `patterns/`,
no empty files.
- Copy **no code** from GeneratePress/Kadence/Blocksy — re-implement patterns.

## Verification commands

- `composer run lint` — PHPCS, must be 0/0. Runs via `bin/phpcs.sh`, which
needs a PHP 8.1–8.3 binary (WPThemeReview → WPCS 2.x breaks on PHP 8.4+).
- `npm run lint:js` / `npm run lint:css` — @wordpress configs, clean.
- `npm run build` — wp-scripts; must emit `build/**/ *.asset.php`.
- `npm run verify` — `bin/verify.sh`: lint → build → wp-env + test data →
curl smoke (home, post w/ comments, archive, search, 404, shop, product,
cart, checkout; expected status, zero `Fatal|Warning|Notice|Deprecated`)
→ `wp i18n make-pot` → Theme Check (step 7) against the packaged tree.
- `bin/package.sh` — clean wp.org-distributable `dist/tbt` zip (excludes all
dev files, sources, examples). Theme Check runs against this, not the repo.
- Theme Check reports ONE expected REQUIRED (`register_block_type`, SPEC
§2.2/§8 — blocks stay in the theme by user decision); the harness passes iff
that is the only required item. See DECISIONS.md / RUBRIC.md.

## PHP standards

- Escape **late on output**: `esc_html`, `esc_attr`, `esc_url`,
`wp_kses_post`. Sanitize **early on input**: `sanitize_text_field`,
`absint`, `sanitize_key`, `wp_unslash`. Nonces + capability checks on any
action. No raw superglobals, no direct DB access.
- i18n: every user-facing string wrapped; literal `'tbt'` domain; a
`translators:` comment on every placeholder string; `_n()` for plurals;
escape translated output (`esc_html__`, never raw `__` echoed).
- Prefix everything global: `tbt_` / `Tbt_` / `TBT_`. `ABSPATH` guard in
every PHP file. Zero notices with WP_DEBUG on, PHP 8.1–8.3.
- Parent theme: **always** `get_template_directory{_uri}()` for own assets —
never `get_stylesheet_*` (points at child theme).

## Assets / JS / CSS

- Everything via `wp_enqueue_*`, versioned `TBT_VERSION`, footer where
possible, conditionally loaded (Woo CSS only on Woo pages; block CSS via
`block.json` `style`/`viewStyle`). No `@import`, no CDNs, fonts local in
`/assets/fonts`. `comment-reply` only when needed. No jQuery.
- `theme.json` v3 is the single design source; consume `--wp--preset--*`
vars; no hard-coded values where a token exists.
- CSS logical properties (`margin-inline-start`, not `margin-left`).
- Blocks: `block.json` apiVersion 3 + React `edit` + server `render.php`;
front-end interactivity via Interactivity API (`viewScriptModule`,
`data-wp-*`) with `"supports": { "interactivity": true }`. Register from
`TBT_DIR . '/build/blocks/...'` — never from `/blocks` source. Defaults
live in `block.json` only (edit component must match schema exactly).
Never hand-write dependency arrays — use generated `*.asset.php`.

## Template exemplar rules (SPEC §6a/6b)

- Hooks fired inside real markup: `tbt_hook( 'entry_header' )` →
`do_action( 'tbt_entry_header' )`.
- `get_block_wrapper_attributes()` is core-escaped — don't double-escape.
- Woo price/image HTML through `wp_kses_post`; sanitize every block
attribute before use; graceful empty states.

## Known failure modes (each is a build failure — SPEC §7)

1. `get_stylesheet_*` for parent assets.
2. Registering blocks from `/blocks` source instead of `/build`.
3. ServerSideRender attribute drift vs `block.json` schema.
4. `viewScriptModule` without `supports.interactivity`.
5. Missing `wp_head()` / `wp_footer()` / `wp_body_open()` /
`add_theme_support( 'title-tag' )`; hard-coded `<title>`.
6. Removing `woocommerce_output_content_wrapper` without priority 10;
gallery supports outside `after_setup_theme`.
7. Variable text domains; concatenation inside i18n; missing `translators:`.
8. `wp_nav_menu` without `'fallback_cb' => false` (or real callable).
9. Woo conditional tags before `wp` / without `function_exists` guards.
10. Theme Check tripwires: `error_log`/`var_dump`, hidden files in zip,
missing `.map` targets, screenshot not 1200×900, invalid tags,
minified-only sources.

## Accessibility (target: `accessibility-ready` tag)

Semantic landmarks; single `<main id="content">`; correct heading order;
skip link visible on focus; keyboard-operable nav incl. submenus; visible
focus styles; `prefers-reduced-motion`; WCAG-AA palette; labeled search
form; nav `aria-label`s. Editor styles loaded via `add_editor_style()`.

## Scope

Presentation only: no CPTs, shortcodes-as-features, SEO/analytics, or form
handling. Naming: blocks `tbt/{kebab}`, patterns `tbt/{kebab}`, CSS props
`--tbt-*`. Child themes override `theme.json`, never CSS (SPEC §11 table).
Loading
Loading