Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 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
289 changes: 289 additions & 0 deletions themes/10up-block-theme/README.md
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 sorry, i am just not seeing this is the theme readme. I think this is going to throw people off the main path. I appreciate that some projects only use the theme, but a vast majority will use the entire scaffold. Fabian has spent a lot of time making things run from the wp-content directory link install and built and scaffold commands and now we are bypassing all of that work. I think it is fine to explain this theme, but then say to reference the main readme for scaffold and install instructions. cc @fabiankaegy

Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
# 10up Block Theme

## Overview
This is a lightweight starter theme for WordPress block themes. It provides the minimal structure to get a modern full-site editing theme up and running, while also being easy to extend.

## Goals
- Fast setup for new WordPress engineers
- Clear convention-based project structure
- Build on WordPress block theme best practices
- Keep PHP logic minimal and isolated in `src/`

## Project Structure
- `assets/`: theme asset source files (CSS, JS, fonts, images)
- `blocks/`: custom blocks
- `parts/`: reusable theme parts for header, footer, etc.
- `patterns/`: block pattern PHP registration / markup
- `src/`: PHP classes for theme setup, block registration, asset loading
- `templates/`: full-site editing template files

Comprehensive developer guide:
- Architecture
- Build tools
- WordPress connections
- Blocks
- Templates
- Runtime behavior

---

## 1. Theme overview

This is a full-site block theme built using:
- WordPress block theme system (`theme.json`, template files, template parts)
- 10up toolkit (`10up-toolkit`) for asset bundling, linting, testing
- 10up framework (`10up/wp-framework`) for modular PHP class loading
- Modern CSS and JS modules in `assets/`
- Custom blocks under `blocks/`

Main root files:
- `style.css` - WordPress theme header and bare stylesheet.
- `theme.json` - block theme settings, styles, color/spacing scales, templates.
- `functions.php` - Bootstrap: constants, composer loading, fast-refresh and theme setup.
- `composer.json` - PHP dependencies and PSR-4 autoload.
- `package.json` - JS/asset build and 10up-toolkit configuration.

---

## 2. Requirements

- PHP >= 8.2
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabiankaegy we should bump this to 8.4 IMO cc @pdavies88

- Node >= 18
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should really get this updated to 24 👀 Especially with GitHub deprecating more versions in actions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fabiankaegy we should bump this to v24 IMO cc @pdavies88

- Composer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 if we are putting versions, this should be Composer 2

- WordPress 6.8+ (implied by theme.json schema)

---

## 3. First-time setup

1. Clone the repository:
```bash
git clone <repo-url> 10up-block-theme
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 I think we are getting too specific here for a theme only setup, and not sticking to the original intent of the repo which covers a large majority of use cases. Most projects use this entire scaffold, not just the theme cc @fabiankaegy

cd 10up-block-theme
Comment on lines +61 to +62
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This here isn't accurate since the theme lives in /themes/xxx in this repo

```
2. Install dependencies:
```bash
composer install
npm install
Comment on lines +66 to +67
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have a setup command you can run in the root of the repo that installs both composer and npm in every workspace :) npm run setup:local / npm run setup

```
3. Build assets:
```bash
npm run build
```
4. Activate theme in WordPress admin: Appearance → Themes → "10up Block Theme"

---

## 4. Developer workflow

### 4.1 Quick start (repeat for copy/paste)

```bash
cd /path/to/themes/10up-block-theme
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 you should not have to do this operation. Both NPM and Composer work from the wp-content directory to install and build all assets, not just the theme

composer install
npm install
npm run build
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The build should pretty much never be run inside any individual workspace. Instead the build should always be run from the workspace root.

```

### 4.2 Local development
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 this totally ignore PHP commands in composer.json. we should treat both PHP and JS/CSS as equal partners


- `npm run watch` (or `npm start`) → 10up-toolkit watch with HMR/hot-refresh
- `composer exec phpcs -- --standard=WordPress` → PHP lint
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a composer command for this already :)

composer lint & composer lint-fix

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 should be composer run lint

- `npm run lint` → JS lint
- `npm run lint-style` → CSS lint
- `npm run test` → unit tests
- `npm run clean-dist` → remove generated assets

### 4.3 Common gotchas

- Always build `dist/` after changing source assets (`assets/`, `blocks/`, `src/`).
- If using a check-in strategy for `dist/`, ensure CI runs `npm run build` before release.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 this is very nuanced and vague. I think we remove. this assumes too much about deployment which can be varied

- `theme.json` is the source of truth for editor styles, palette, and layout. Adjust there for global styles.
- Some references may still use legacy naming in older helper docs; prefer 10up-block-theme naming in code changes.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since every consumer of the theme will have it renamed I think this last one here can get removed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 can we remove this? I though we caught all of the instances.


---

## 5. Core bootstrapping path
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 Similar to what we are finding with AGENTS.md and CLAUDE.md file, this information can go stale over time. I think all of this function reference should be removed from here in favor of docblocks on the class or methods it relates to.


### 5.1 `functions.php`

- defines constants:
- `TENUP_BLOCK_THEME_PATH`, `TENUP_BLOCK_THEME_DIST_PATH`, `TENUP_BLOCK_THEME_INC`, etc.
- points to composer/autoload (`vendor/autoload.php`)
- local fast-refresh via `dist/fast-refresh.php` when local environment
- includes helper files:
- `includes/helpers.php`
- `template-tags.php`
- creates and sets up `\TenupBlockTheme\ThemeCore`.

### 5.2 `src/ThemeCore.php`

- hooks:
- `init` → `ThemeCore::init()`
- `after_setup_theme` → `i18n()` + `theme_setup()`
- `wp_head` → `js_detection()` + `scrollbar_detection()`
- `init()` ensures `TenupFramework\ModuleInitialization` exists, admin notice on failure
- `ModuleInitialization::instance()->init_classes( TENUP_BLOCK_THEME_INC )` automatically loads modules from `src/`.

---

## 6. Module system (10up framework)

By `ThemeCore::init()`, `\TenupFramework\ModuleInitialization` scans `src/` and initializes modules that implement `ModuleInterface`.

Current modules:
- `src/Blocks.php` (block registration and enqueueing)
- `src/Overrides.php` (WP output filters such as post date text for custom post types)
- `src/TemplateTags.php` (meta tag injection on `wp_head`)

Each module uses `TenupFramework\Module` trait to register hooks easily.

---

## 6. Block registration & runtime

### 6.1 `src/Blocks.php`

- `register_theme_blocks()` scans `dist/blocks/*/block.json` and calls `register_block_type_from_metadata()` for each found block.
- `allowed_block_types_all` filter extends allowed blocks with theme blocks.
- `enqueue_theme_block_styles()` scans `dist/blocks/autoenqueue/**/*.css` and registers/enqueues style/script for each block with assets info from `GetAssetInfo`.
- includes block render filter for TenUp navigation block (removes ARIA roles for fallback markup compatibility).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what's meant by this


### 6.2 Blocks directory structure
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's mention the scaffold command here


`blocks/` contains block sources with standard WP block scaffold:
- `block.json`
- `edit.tsx`, `index.ts`, `markup.php`
- `style.css` / `editor.css` (for block styles)

`blocks/*` are transpiled and bundled by 10up-toolkit into `dist/blocks/*` (JS/CSS/asset metadata files).

---

## 7. Asset pipeline (10up-toolkit)

`package.json` includes a `10up-toolkit` config section:
- `useBlockAssets`: true (auto-handle block assets)
- `useScriptModules`: true
- `loadBlockSpecificStyles`: true
- `entry` maps compiled assets:
- `editor-style-overrides`: `assets/css/editor-style-overrides.css`
- `frontend`: `assets/js/frontend.ts`
- `block-extensions`: `assets/js/block-editor/index.ts`
- `paths.blocksDir`: `./blocks`

`npm run build` calls `10up-toolkit build` and outputs to `dist/*`.

`npm run watch` does incremental build with file watching.

### 7.1 Dist layout

- `dist/css/` (compiled styles)
- `dist/js/` (compiled scripts)
- `dist/blocks/` (compiled block assets per block)
- `dist/fast-refresh.php` (local live-reload helper)

### 7.2 Theme script inclusion

- `src/ThemeCore::theme_setup()` calls `add_theme_support('editor-styles')` and `add_editor_style('/dist/css/frontend.css')`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is only for editor stuff. From the heading I would have expected something about the Asset trait from the framework and how to enqueue things

- Additional frontend script injection is likely handled in block metadata and `10up-toolkit` output, not explicit in theme code.

---

## 8. Styles + theme.json

### `theme.json`

Defines:
- `templateParts`: `header`, `footer`
- `customTemplates` for special post types
- `settings` with custom properties (`--wp--custom--*`, width computations, spacing, color palettes, gradients, transition variables)
- `layout` with content and wide max widths.

### `assets/css/` structure

- `editor-style-overrides.css` for editor-specific style overrides
- `frontend.css` for visual styles
- subdirectories for base/blocks/components/globals/mixins/patterns/templates/utilities

### `parts/` partial PHP templates
- `parts/header.html`, `parts/footer.html`, etc.

### `patterns/` reusable partial definitions
- e.g., `base-card.php`, etc.

---

## 9. Template and content hierarchy

`templates/` uses static HTML templates for site result paths:
- `index.html`, `home.html`, `single.html`, etc.

These are block theme templates in Full Site Editing model.

---

## 10. WordPress hook behavior at runtime

- `wp_head`:
- `ThemeCore::js_detection()` toggles `no-js` to `js`
- `ThemeCore::scrollbar_detection()` sets `--wp--custom--scrollbar-width`
- `TemplateTags::add_viewport_meta_tag()` outputs viewport meta

- `after_setup_theme`: editor styles + disable core block patterns.

- `init`: loads module classes and runs block registration.

---

## 11. Debug and local enhancement

- local environment scenario (`.local`/`.test` or `local`/`development`) loads `dist/fast-refresh.php` and sets dist URL path with `TenUpToolkit\set_dist_url_path()` for hot-reload.

---

## 12. Extending the theme

1. Add block in `blocks/<block-name>/`.
2. Create `block.json`, `edit.tsx`, `index.ts`, style files as needed.
3. Run `npm run build`.
4. Block registers automatically from `dist/blocks/*` in `Blocks::register_theme_blocks()`.

---

## 13. Maintenance tasks
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 can we consolidate these commands into the earlier list at the start of this file?


- PHP lint: `composer exec phpcs -- --standard=WordPress`
- JS lint: `npm run lint` / `npm run lint-js`
- Style lint: `npm run lint-style`
- Format JS: `npm run format-js`
- Clean dist: `npm run clean-dist`

---

## 14. Key entrypoints quick map
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 do we need an entry point for CSS?


- `functions.php` → `ThemeCore` → class loader
- `src/Blocks.php` → block metadata and enqueueing
- `assets/js/frontend.ts` → frontend script implementation
- `blocks/*` + `10up-toolkit` → `dist/blocks/*`
- `theme.json` → WordPress UI/Editor settings

---

## 15. Helpful commands summary
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 I think we can remove this section. This is the third instance where we are listing the same commands.


- `composer install`
- `npm install`
- `npm run watch`
- `npm run build`
- `composer exec phpcs -- --standard=WordPress`
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- `composer exec phpcs -- --standard=WordPress`
- `composer run lint`

- `npm test`
- `npm run lint`

---

## 16. Further notes
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 I think we can remove this section. feels redundant after all that is said eariler


- This theme is designed around a 10up block theme pattern (colors, spacing, utilities, templates).
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what is meant by this

- The 10up Toolkit plus the WP framework yields a highly modular, maintainable code path and is production-ready.
19 changes: 19 additions & 0 deletions themes/10up-block-theme/assets/README.md
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 I don't agree with having smaller readme's throughout the codebase that can easily become out of date. I think this either should be a CLAUDE.md file (still run into same out of date issue) or place all of this into the root README/CLAUDE.md files.

Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# assets/

Contains static theme assets. Use this folder to keep the theme's source CSS, JavaScript, fonts, and images.

## Subfolders
- `css/`: core styles and split source files (`base`, `blocks`, `components`, `globals`, `mixins`, `templates`, `utilities`)
- `fonts/`: font files used by theme
- `images/`: image assets used in templates/patterns
- `js/`: JavaScript entrypoints and block feature extensions
- `svg/`: inline svg icons or assets

## How to use
- Keep editable CSS here.
- `js/frontend.js`: theme front-end behavior
- `js/block-*`: block variations, filters, styles, and extensions

## Notes
- Changes in this folder typically require a page refresh and sometimes rebuild.
- When adding CSS for blocks, prefer adding to `assets/css/blocks/core/` to avoid global overrides.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Big fan of making this change official in the theme here 👍

Something I always needed to do in projects though is add the following to the .eslintrc file:

{
	"parser": "@typescript-eslint/parser",
	"extends": ["@10up/eslint-config/wordpress"],
	"plugins": ["@typescript-eslint"],
	"rules": {}
}

File renamed without changes.
16 changes: 16 additions & 0 deletions themes/10up-block-theme/blocks/README.md
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you really think there is value in having the example block back in here?

Part of the reason why I removed it was that I ended up seeing it nor removed on client projects. And since we have the scaffold:block command in the theme here I always found it nicer / easier to just have that present.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 same thing here. Either a CLAUDE.md file or we consilidate into the main readme

Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# blocks/

Library of custom blocks for a theme

## Purpose
- Create custom blocks for a theme

## Example block: `example-block` (hello world)
1. Create `blocks/example-block/block.json` with metadata
2. Add `blocks/example-block/edit.tsx` and `blocks/example-block/index.ts`:
- `BlockEdit` renders editor UI
- `registerBlockType(metadata, { edit: BlockEdit, save: () => null })`
3. Add `blocks/example-block/markup.php` to output frontend markup:
- Simple output: `<div class="wp-block-tenup-block-theme-example-block">Hello world</div>`
4. Add `blocks/example-block/style.css` for block style
5. Build the block bundle with `npm run build`
17 changes: 17 additions & 0 deletions themes/10up-block-theme/blocks/example-block/block.json
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@pdavies88 I agree with @fabiankaegy that we should not provide an example block here as people do not take ownership and make sure it gets deleted. We have so many resources to scaffold this ou either with a cli or the documentation at gutenberg.10up.com

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "tenup-block-theme/example-block",
"title": "Example Block",
"category": "theme",
"icon": "smiley",
"description": "A minimal example block for new block authors that renders Hello World.",
"attributes": {},
"supports": {
"html": false
},
"textdomain": "tenup",
"editorScript": "file:./index.ts",
"style": "file:./style.css",
"render": "file:./markup.php"
}
11 changes: 11 additions & 0 deletions themes/10up-block-theme/blocks/example-block/edit.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useBlockProps } from '@wordpress/block-editor';

export const BlockEdit = () => {
const blockProps = useBlockProps();

return (
<div {...blockProps}>
<strong>Example Block:</strong> Hello world
</div>
);
};
12 changes: 12 additions & 0 deletions themes/10up-block-theme/blocks/example-block/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { registerBlockType, type BlockConfiguration } from '@wordpress/blocks';
import metadata from './block.json';
import { BlockEdit } from './edit';

const blockMeta = metadata as unknown as BlockConfiguration<Record<string, unknown>>;
const blockName = blockMeta.name as string;

registerBlockType(blockName, {
...blockMeta,
edit: BlockEdit,
save: () => null,
});
16 changes: 16 additions & 0 deletions themes/10up-block-theme/blocks/example-block/markup.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
/**
* Example block markup
*
* @package 10up-block-theme
*
* @var array $attributes Block attributes.
* @var string $content Block content.
* @var WP_Block $block Block instance.
* @var array $context Block context.
*/

?>
<div <?php echo get_block_wrapper_attributes(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
<strong>Example Block:</strong> Hello world
</div>
6 changes: 6 additions & 0 deletions themes/10up-block-theme/blocks/example-block/style.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.wp-block-tenup-block-theme-example-block {
background: #f5f5f5;
border: 1px dashed #0073aa;
font-weight: 600;
padding: 1rem;
}
Loading
Loading