Skip to content

Latest commit

Β 

History

32 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

WM WordPress Base Theme

A production-ready WordPress base theme built for modern development workflows. Ships with a Vite build pipeline, TypeScript, Tailwind CSS, GSAP, React islands (Shadcn UI), full Block Editor support, ACF page builder, WooCommerce templates, Schema.org structured data, and a one-command setup script.

Developed by Working Model Inc


Requirements

  • WordPress 6.0+
  • PHP 8.0+
  • Node.js 18+

Quick Start

npm run setup

This single command will:

  • Prompt for a project name and rename the theme slug + text domain throughout
  • Copy .env.example β†’ .env
  • Install all Node dependencies
  • Run the first production build

Then copy the theme folder to wp-content/themes/ and activate it in WordPress.


Scripts

Command Description
npm run setup First-time project setup (rename, install, build)
npm run dev Start Vite dev server with HMR
npm run build Production build to dist/
npm run test Run Vitest unit tests
npm run test:watch Run tests in watch mode
npm run test:coverage Run tests with coverage report
npm run lint Lint TypeScript
npm run lint:fix Lint and auto-fix
npm run format Format with Prettier
npm run type-check TypeScript type check

Project Structure

β”œβ”€β”€ bin/
β”‚   └── setup.sh                  # One-command setup script
β”œβ”€β”€ patterns/                     # Block Editor patterns (auto-registered)
β”‚   β”œβ”€β”€ hero.php
β”‚   β”œβ”€β”€ cards.php
β”‚   β”œβ”€β”€ cta-banner.php
β”‚   β”œβ”€β”€ testimonial.php
β”‚   β”œβ”€β”€ text-image.php
β”‚   └── section-divider.php
β”œβ”€β”€ woocommerce/                  # WooCommerce template overrides
β”‚   β”œβ”€β”€ archive-product.php
β”‚   β”œβ”€β”€ single-product.php
β”‚   β”œβ”€β”€ cart/cart.php
β”‚   └── checkout/form-checkout.php
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ acf-json/                 # ACF field group JSON (version-controlled)
β”‚   β”œβ”€β”€ assets/
β”‚   β”‚   β”œβ”€β”€ scripts/
β”‚   β”‚   β”‚   β”œβ”€β”€ main.ts           # Main JS entry point
β”‚   β”‚   β”‚   β”œβ”€β”€ admin.ts          # Admin JS entry point
β”‚   β”‚   β”‚   β”œβ”€β”€ islands.ts        # React island hydration entry
β”‚   β”‚   β”‚   β”œβ”€β”€ animations/       # GSAP scroll animations
β”‚   β”‚   β”‚   β”œβ”€β”€ components/       # Interactive components (forms, nav, dark mode)
β”‚   β”‚   β”‚   └── gsap/             # GSAP setup and utilities
β”‚   β”‚   └── styles/
β”‚   β”‚       β”œβ”€β”€ main.scss         # Main stylesheet entry
β”‚   β”‚       β”œβ”€β”€ config/           # Variables and mixins
β”‚   β”‚       β”œβ”€β”€ base/             # Reset, typography, utilities
β”‚   β”‚       β”œβ”€β”€ components/       # Component styles
β”‚   β”‚       β”œβ”€β”€ layout/           # Header, footer, content
β”‚   β”‚       └── wordpress/        # Block editor styles
β”‚   β”œβ”€β”€ components/
β”‚   β”‚   └── ui/                   # Pre-installed Shadcn components
β”‚   β”‚       β”œβ”€β”€ button.tsx
β”‚   β”‚       β”œβ”€β”€ card.tsx
β”‚   β”‚       β”œβ”€β”€ badge.tsx
β”‚   β”‚       β”œβ”€β”€ input.tsx
β”‚   β”‚       └── dialog.tsx
β”‚   β”œβ”€β”€ inc/
β”‚   β”‚   β”œβ”€β”€ theme-functions.php   # Helper functions
β”‚   β”‚   β”œβ”€β”€ acf-setup.php         # ACF options page + JSON sync
β”‚   β”‚   β”œβ”€β”€ block-setup.php       # Block categories and styles
β”‚   β”‚   β”œβ”€β”€ cpt-setup.php         # Custom post type helpers
β”‚   β”‚   β”œβ”€β”€ woocommerce-setup.php # WooCommerce support
β”‚   β”‚   β”œβ”€β”€ schema.php            # Schema.org / JSON-LD output
β”‚   β”‚   β”œβ”€β”€ react-islands.php     # React island PHP helper
β”‚   β”‚   β”œβ”€β”€ performance.php       # Core Web Vitals defaults
β”‚   β”‚   β”œβ”€β”€ breadcrumbs.php       # Native PHP breadcrumbs
β”‚   β”‚   └── customizer.php        # WordPress Customizer options
β”‚   β”œβ”€β”€ lib/
β”‚   β”‚   └── utils.ts              # cn(), debounce(), formatDate()
β”‚   β”œβ”€β”€ templates/
β”‚   β”‚   β”œβ”€β”€ acf-layouts/          # ACF flexible content layouts
β”‚   β”‚   └── content-*.php         # Template parts
β”‚   └── types/                    # TypeScript definitions
β”œβ”€β”€ tests/                        # Vitest unit tests
β”œβ”€β”€ theme.json                    # Block Editor design tokens
β”œβ”€β”€ functions.php
β”œβ”€β”€ style.css
β”œβ”€β”€ page.php                      # Page template with ACF page builder loop
β”œβ”€β”€ CHANGELOG.md                  # Version history
β”œβ”€β”€ .wp-env.json                  # Docker-based local WordPress config
└── .env.example                  # Environment variable reference

Features

Block Editor

theme.json exposes WM design tokens directly in the editor β€” color palette, font families, font sizes, and spacing scale. Six block patterns are auto-registered from the patterns/ directory:

  • Hero β€” full-width heading + copy + dual CTA buttons
  • Three Column Cards β€” bordered feature grid
  • CTA Banner β€” dark background with yellow accent button
  • Testimonial β€” centered quote with rule framing
  • Text + Image β€” 50/50 two-column with CTA
  • Section Divider β€” ornamental dot separator

Three block styles are registered: core/button outline, core/separator thick, core/quote plain.

ACF Page Builder

page.php checks for a page_builder flexible content field and renders layouts from src/templates/acf-layouts/. Falls back to the_content() when ACF is inactive.

Field group JSON lives in src/acf-json/ and syncs automatically via the ACF sync screen.

Included layouts: hero, text_columns, image_text, cta_banner

Custom Post Types

src/inc/cpt-setup.php provides two helpers:

// Register a CPT
wm_register_cpt( 'project', 'Project', 'Projects' );

// Register a taxonomy
wm_register_taxonomy( 'project_type', 'Type', 'Types', ['project'] );

Both generate a full label set and sensible defaults. Pass an optional $args array to override anything. Add registrations to wm_register_post_types() in the same file.

WooCommerce

Add WooCommerce and the theme is ready. Template overrides in woocommerce/ cover the shop archive, single product, cart, and checkout β€” all with WC hooks intact. Styles are disabled by default so the theme's CSS takes full control.

Mobile Navigation

The header includes a fully-accessible mobile drawer built with GSAP:

  • Hamburger button (nav-toggle) with animated β†’ Γ— transition via CSS
  • Drawer slides in from the right (x: '100%' β†’ '0%', 0.35s power3.out)
  • Focus trap cycles through all focusable elements within the open drawer
  • Closes on Escape, overlay click, or any nav link click; returns focus to the trigger
  • aria-expanded / aria-hidden / aria-controls wired throughout

Dark Mode

A dark mode toggle is included in the header. It reads prefers-color-scheme on first visit, then persists to localStorage. All CSS custom properties support both modes via the .dark class on <html>.

Toggle additional buttons anywhere by adding data-dark-toggle to any element.

WordPress Customizer

Theme options live under Appearance β†’ Customize β†’ Theme Options:

Section Settings
Brand Accent colour (live preview via postMessage)
Contact Phone, email, address
Social Links Instagram, LinkedIn, X/Twitter, Facebook, YouTube
Footer Copyright text

Helper functions for templates:

wm_get_contact( 'phone' );          // β†’ escaped phone string
wm_get_social( 'instagram' );       // β†’ escaped URL
wm_get_footer_text();               // β†’ wp_kses_post'd copyright text

React Islands

Render a React component from PHP:

wm_render_react_component( 'MyComponent', [ 'label' => 'Hello' ] );

Register the component in src/assets/scripts/islands.ts, call wm_enqueue_islands() in your template, and the island hydrates client-side with the provided props.

Pre-installed Shadcn components in src/components/ui/:

import { Button } from '@/components/ui/button';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Input } from '@/components/ui/input';
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from '@/components/ui/dialog';

Schema.org / JSON-LD

Structured data is injected automatically in wp_head:

Context Schema types
Every page WebSite
Front page Organization (with logo if set)
Singular / archive / search BreadcrumbList
Single posts Article (headline, dates, author, image)

Breadcrumbs

Call wm_breadcrumbs() anywhere in a template. Outputs an accessible <nav> with Schema.org itemListElement microdata. Handles posts (with category ancestors), pages (with parent pages), CPT archives, taxonomy/tag/author/date archives, search, and 404.

wm_breadcrumbs(); // defaults
wm_breadcrumbs(['sep' => '/', 'class' => 'my-breadcrumbs']); // custom

Core Web Vitals

  • loading="lazy" and decoding="async" added automatically to archive thumbnails and the_content() images
  • Hero / LCP image gets fetchpriority="high" instead
  • wm_preconnect_origins filter lets you add <link rel="preconnect"> hints for third-party domains

GSAP Animations

ScrollTrigger is registered once in src/assets/scripts/gsap/init.ts. All animations respect prefers-reduced-motion.

import { animateOnScroll } from '@/assets/scripts/animations';

animateOnScroll('.my-element', { opacity: 1, y: 0, duration: 0.8 });

Configuration

Local Development with wp-env

The theme ships with a .wp-env.json for zero-dependency local WordPress via Docker:

npm run env:start   # start WordPress at http://localhost:8888
npm run env:stop    # stop containers
npm run env:clean   # clean environment (resets DB)

Requires Docker Desktop and @wordpress/env (npm i -g @wordpress/env or use npx). WordPress runs PHP 8.2 with WP_DEBUG enabled and the theme pre-mapped to wp-content/themes/wm-base-theme.

Environment Variables

Copy .env.example to .env:

VITE_PORT=3000
VITE_HMR_HOST=localhost   # Set to your local domain if using Valet/DDEV/Lando

Fonts

The theme defaults to Stack Sans Text / Stack Sans Headline (WM's internal typeface) with system-ui as fallback. Replace with your own fonts in src/assets/styles/config/_variables.scss:

Option A β€” Self-hosted (add to src/assets/styles/base/_typography.scss):

@font-face {
  font-family: 'My Font';
  src: url('../fonts/my-font.woff2') format('woff2');
  font-weight: 100 900;
  font-display: swap;
}

Option B β€” Google Fonts (enqueue in functions.php):

wp_enqueue_style('google-fonts', 'https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap', [], null);

Then update $font-stack-text and $font-stack-headline in _variables.scss, and the fontFamilies array in theme.json.

Design Tokens

Edit tokens in two places β€” they're kept in sync:

  • SCSS variables: src/assets/styles/config/_variables.scss
  • Block Editor: theme.json (palette, spacing, font sizes)

Adding a Block Pattern

Create a PHP file in patterns/ with the standard header:

<?php
/**
 * Title: My Pattern
 * Slug: wm-base-theme/my-pattern
 * Categories: wm-blocks
 */
?>
<!-- wp:paragraph -->
<p>Pattern content here.</p>
<!-- /wp:paragraph -->

WordPress 6.0+ registers it automatically.

Adding an ACF Layout

  1. Add a layout to src/acf-json/group_wm_page_builder.json (or use the ACF UI and sync)
  2. Create src/templates/acf-layouts/your_layout.php
  3. Use wm_get_field() to fetch field values inside the template

Preconnect Hints

add_filter( 'wm_preconnect_origins', function ( array $origins ): array {
  $origins[] = 'https://fonts.googleapis.com';
  $origins[] = 'https://fonts.gstatic.com';
  return $origins;
} );

Testing

npm run test

Vitest runs 18 unit tests covering cn(), debounce(), form validation behaviour, dark mode toggle, and the wmTheme nonce guard. Tests use jsdom β€” no browser required.


Browser Support

Modern browsers (last 2 versions). IE 11 polyfills provided via @vitejs/plugin-legacy β€” remove from vite.config.ts if not needed.


License

MIT β€” see LICENSE for details.


Working Model Inc Β· workingmodel.co

About

A production-ready WordPress base theme built for modern development workflows. Ships with a Vite build pipeline, TypeScript, Tailwind CSS, GSAP, React islands (Shadcn UI), full Block Editor support, ACF page builder, WooCommerce templates, Schema.org structured data, and a one-command setup script. Developed by Working Model Inc

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages