
Phase 1: Foundation & Setup
Tools You’ll Need:
- Local Development: WordPress Studio (free, open-source) or LocalWP
- Design: Figma for mockups and design system documentation
- Development: VS Code with WordPress-related extensions
- Essential Plugin: Create Block Theme — this is indispensable for saving Site Editor changes back to theme files
Starting Point Options:
- Twenty Twenty-Five (latest default theme) — recommended as your base
- Twenty Twenty-Four — Anders Norén’s preferred starting point
- Empty Theme — using Create Block Theme plugin to generate a blank slate
Phase 2: The Seven-Task Workflow (Adapted for Agency Use)
Task 1: Strip & Restructure
Remove everything you won’t need from your base theme:
- Delete unused templates, template parts, patterns
- Remove fonts and images you won’t use
- Rename files to match your agency branding
- Keep the folder structure:
/parts/,/patterns/,/templates/,/styles/,/assets/
Recommended Folder Structure:
your-starter-theme/
├── assets/
│ ├── fonts/
│ ├── images/
│ └── css/ # Block-specific stylesheets
├── parts/
│ ├── header.html
│ ├── footer.html
│ └── sidebar.html
├── patterns/
│ ├── hidden-header.php
│ ├── hidden-footer.php
│ └── [reusable patterns]
├── styles/
│ └── [style variations].json
├── templates/
│ ├── index.html
│ ├── single.html
│ ├── page.html
│ ├── archive.html
│ ├── 404.html
│ └── search.html
├── functions.php
├── style.css
├── theme.json
└── readme.txt
Task 2: Configure theme.json
This is your design system definition. Set up:
Spacing Scale:
json
"spacing": {
"spacingScale": { "steps": 0 },
"spacingSizes": [
{ "name": "XS", "size": "8px", "slug": "10" },
{ "name": "S", "size": "16px", "slug": "20" },
{ "name": "M", "size": "24px", "slug": "30" },
{ "name": "L", "size": "clamp(32px, 4vw, 48px)", "slug": "40" },
{ "name": "XL", "size": "clamp(48px, 6vw, 64px)", "slug": "50" }
]
}
Color Palette (use semantic names for client flexibility):
json
"color": {
"defaultPalette": false,
"palette": [
{ "color": "#FFFFFF", "name": "Base", "slug": "base" },
{ "color": "#F5F5F5", "name": "Base Alt", "slug": "base-alt" },
{ "color": "#1A1A1A", "name": "Contrast", "slug": "contrast" },
{ "color": "#666666", "name": "Contrast Muted", "slug": "contrast-muted" },
{ "color": "#0066CC", "name": "Primary", "slug": "primary" },
{ "color": "#004499", "name": "Primary Dark", "slug": "primary-dark" }
]
}
Typography — include variable fonts for performance:
json
"typography": {
"fontFamilies": [
{
"fontFace": [
{
"fontFamily": "Inter",
"fontStyle": "normal",
"fontWeight": "100 900",
"src": ["file:./assets/fonts/inter-var.woff2"]
}
],
"fontFamily": "\"Inter\", sans-serif",
"name": "Inter",
"slug": "body"
}
]
}
```
#### Task 3: Templates & Template Parts
Build your core layouts. Key principle: **templates call template parts, which call patterns**.
**Example structure:**
```
Template (index.html)
└── Template Part (header.html)
└── Pattern (hidden-header.php) ← Contains translatable strings
└── Content blocks
└── Template Part (footer.html)
└── Pattern (hidden-footer.php)
Why patterns for headers/footers? They’re PHP files, so you can use esc_html_e() for translation-ready text.
Task 4: Handle Extended Functionality
For agency work, consider:
Block Bindings API for dynamic content:
- Copyright year in footer
- Reading time
- Custom field display
Register in functions.php:
php
function starter_register_block_bindings() {
register_block_bindings_source(
'starter/copyright-year',
array(
'label' => __('Copyright Year', 'starter-theme'),
'get_value_callback' => 'starter_copyright_year_callback'
)
);
}
add_action('init', 'starter_register_block_bindings');
function starter_copyright_year_callback() {
return '© ' . date('Y');
}
Custom Block Styles:
php
register_block_style(
'core/button',
array(
'name' => 'outline-primary',
'label' => __('Outline Primary', 'starter-theme')
)
);
Task 5: Create Reusable Patterns
Build patterns your agency will use across projects:
- Hero sections (multiple variations)
- CTA blocks
- Testimonial layouts
- Team member cards
- Contact forms
- FAQ accordions
Pattern header format:
php
<?php
/**
* Title: Hero with CTA
* Slug: starter/hero-cta
* Categories: featured, starter-heroes
* Keywords: hero, banner, cta
* Viewport Width: 1400
*/
?>
Task 6: Style Variations
Create 2-3 style variations for quick client customization:
- Default (light)
- Dark mode
- Alternative color scheme
Store as JSON files in /styles/:
json
{
"title": "Dark Mode",
"settings": {
"color": {
"palette": [
{ "color": "#1A1A1A", "name": "Base", "slug": "base" },
{ "color": "#FFFFFF", "name": "Contrast", "slug": "contrast" }
]
}
}
}
Task 7: Quality Assurance
- Run Theme Check plugin
- Test accessibility (keyboard navigation, screen readers)
- Validate on multiple devices
- Check the Stylebook view for missed block styles
GitHub Setup
Initial Repository Setup
bash
# Initialize git in your theme folder
cd wp-content/themes/your-starter-theme
git init
# Create .gitignore
cat > .gitignore << EOF
.DS_Store
Thumbs.db
*.log
node_modules/
.env
*.zip
EOF
# Initial commit
git add .
git commit -m "Initial commit: Agency starter theme foundation"
# Connect to GitHub
git remote add origin https://github.com/yourusername/starter-theme.git
git branch -M main
git push -u origin main
You can also run this locally before pushing by running npx wordpress-theme-check-action inside your theme folder.
GitHub Actions for Automated Testing
Create .github/workflows/theme-check.yml:
yaml
name: Deploy to WordPress.org
on:
push:
tags:
- "*"
jobs:
tag:
name: New tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: |
npm install
npm run build
- name: WordPress Theme Deploy
uses: Codeinwp/action-wordpress-theme-deploy@primary
env:
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SLUG: your-theme-slug
Deploying to WordPress.org Theme Repository
Once your theme is approved, you can automate future releases. Create .github/workflows/deploy.yml:
yaml
name: Deploy to WordPress.org
on:
push:
tags:
- "*"
jobs:
tag:
name: New tag
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build
run: |
npm install
npm run build
- name: WordPress Theme Deploy
uses: Codeinwp/action-wordpress-theme-deploy@primary
env:
SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }}
SVN_USERNAME: ${{ secrets.SVN_USERNAME }}
SLUG: your-theme-slug
Branch Strategy for Agency Use
main— stable, production-readydevelop— active developmentfeature/*— new featuresclient/*— client-specific forks
WordPress.org Theme Repository Submission
Pre-Submission Checklist
Required Files:
style.csswith proper headerreadme.txtwith changelog and descriptionscreenshot.png(1200×900 px recommended)- Valid
theme.json
style.css Header:
css
/*
Theme Name: Your Starter Theme
Theme URI: https://yoursite.com/theme
Author: Your Agency Name
Author URI: https://yoursite.com
Description: A flexible block theme starter kit for agencies.
Version: 1.0.0
Requires at least: 6.4
Tested up to: 6.8
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: your-starter-theme
Tags: block-patterns, block-styles, full-site-editing, wide-blocks
*/
Testing Tools
Testing Tools
1. Theme Check Plugin Install from WordPress.org admin and run comprehensive checks. This is what Anders Norén used before submitting Pulitzer.
2. WordPress Theme Review Action (Local)
bash
cd your-theme-folder
npx wordpress-theme-check-action
3. PHP CodeSniffer for WordPress Coding Standards
bash
composer require --dev wp-coding-standards/wpcs dealerdirect/phpcodesniffer-composer-installer
./vendor/bin/phpcs --standard=WordPress-Theme .
Common Issues to Avoid
- No PHP errors or warnings
- Escape all output: Use
esc_html(),esc_attr(),esc_url() - Prefix everything: Functions, classes, handles with your theme slug
- No hardcoded links: Use
home_url(),get_template_directory_uri() - Include skip links for accessibility
- License compatibility: All assets (fonts, images) must be GPL-compatible
- No minified JS/CSS without source files
Submission Process
- Create account at wordpress.org/themes
- Go to Upload Your Theme
- Upload ZIP file (exclude
.git,node_modules, etc.) - Wait for review (typically 2-8 weeks)
- Respond to reviewer feedback promptly
Key Resources (Verified)
| Resource | URL |
|---|---|
| Theme Handbook | https://developer.wordpress.org/themes/ |
| theme.json Reference | https://developer.wordpress.org/themes/global-settings-and-styles/ |
| Block Bindings API | https://developer.wordpress.org/block-editor/reference-guides/block-api/block-bindings/ |
| Create Block Theme Plugin | https://wordpress.org/plugins/create-block-theme/ |
| Theme Check Plugin | https://wordpress.org/plugins/theme-check/ |
| WordPress Theme Review Action | https://github.com/WordPress/theme-review-action |
| Theme Deploy Action | https://github.com/marketplace/actions/wordpress-theme-deploy |
| Pulitzer Theme (Reference) | https://github.com/andersnoren/pulitzer |
| Submission Guidelines | https://developer.wordpress.org/themes/releasing-your-theme/submitting-your-theme-to-wordpress-org/ |
