Skip to content

phcdevworks/spectre-base

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

74 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

@phcdevworks/spectre-base

Repository Snapshot

Field Value
Project team project-design
Repository role Spectre WordPress theme shell
Package/artifact @phcdevworks/spectre-base
Current version/status 1.0.0

Standard Workflow

  1. Read AGENTS.md, then the agent-specific guide for the task.
  2. Check TODO.md and ROADMAP.md for current scope.
  3. Make the smallest repo-local change that satisfies the task.
  4. Run npm run check when validation is required or practical.
  5. Update docs and CHANGELOG.md only when behavior, public contracts, or release-relevant metadata changed.

Documentation Map

Guide Path
Agent rules AGENTS.md
Claude Code CLAUDE.md
Codex CODEX.md
Copilot COPILOT.md
Jules JULES.md
Roadmap ROADMAP.md
Todo TODO.md
Changelog CHANGELOG.md
Security SECURITY.md

CI License Node

@phcdevworks/spectre-base is the WordPress theme delivery layer of the Spectre system for WordPress sites that consume Spectre tokens, Spectre UI, and Spectre web components.

Maintained by PHCDevworks, it combines a standard WordPress theme directory with a Vite build pipeline, a TypeScript client entrypoint, and Tailwind CSS 4. It is for teams building custom WordPress themes that need modern frontend assets without moving design-system ownership into PHP templates.

Contributing | Code of Conduct | Changelog | Roadmap | Security Policy

Source of truth

spectre-theme/ is the deployable WordPress theme directory. src/ is the build source. Everything in spectre-theme/dist/ is generated -- never edit it directly.

Layer Path Rule
Theme JS entry src/js/main.ts Registers Spectre web components
Theme CSS entry src/styles/main.css Shell styles using var(--sp-*) only
WordPress theme spectre-theme/ Template hierarchy, asset loading, Gutenberg config
Theme metadata spectre-theme/style.css and spectre-theme/readme.txt Keep version synced with package.json
Gutenberg tokens spectre-theme/theme.json All values must come from var(--sp-*)
Build output spectre-theme/dist/ Never edit directly -- regenerated by npm run build

After any source change: run npm run build to regenerate output, then npm run check to validate.

What this package owns

  • The Vite build configuration for theme assets
  • The TypeScript entrypoint in src/js/main.ts
  • The CSS entrypoint in src/styles/main.css
  • The WordPress theme files in spectre-theme/, including asset loading in functions.php
  • The compiled output for theme-owned assets in spectre-theme/dist

The build compiles one JavaScript entry and one CSS entry. In production, the theme resolves those compiled assets from the Vite manifest and serves one JS bundle and one CSS bundle for the theme-owned frontend surface.

What this package does not own

  • Design token definitions. Those belong to @phcdevworks/spectre-tokens.
  • Reusable UI component contracts and recipes. Those belong to @phcdevworks/spectre-ui and @phcdevworks/spectre-components.
  • WordPress core installation, plugin management, or hosting concerns.
  • Application state architecture beyond the theme entrypoint.

Key capabilities

  • Ships a deployable WordPress theme directory in spectre-theme/
  • Builds theme-owned CSS and JavaScript through Vite and TypeScript
  • Switches between the Vite dev server in development and hashed assets in production
  • Consumes Spectre tokens, Spectre UI, and Spectre web components without redefining their contracts
  • Keeps PHP templates focused on WordPress structure and data delivery

When to use this package

  • You are building a WordPress site and need Spectre tokens, UI, and web components delivered through a theme
  • You want a Vite + TypeScript build pipeline for theme-owned assets without owning the design system itself
  • You need hot module replacement in development and hashed production assets without writing the plumbing yourself

When not to use this package

  • You want to define design tokens, color scales, typography, or component contracts -- those belong in @phcdevworks/spectre-tokens, @phcdevworks/spectre-ui, and @phcdevworks/spectre-components
  • You need a WordPress plugin -- plugin logic belongs in a separate plugin repository such as spectre-icons
  • You are building a non-WordPress frontend -- this package is WordPress-specific

Design system guardrail

The CMS delivers; the design system defines. This theme is the delivery layer, not a second design system. WordPress owns template structure and data delivery; Spectre packages own visual meaning, styling contracts, and components.

  • Use var(--sp-*) tokens for all CSS values -- never hardcode hex, RGB, rem, or px
  • Use <sp-button>, <sp-input>, and other <sp-*> components for controls
  • Keep PHP templates structural -- semantic shell classes and WordPress functions only

See AGENTS.md for the full shared edit boundaries and drift prevention rules that apply to all contributors and AI agents.

Installation

Prerequisites: Node.js ^22.12.0 || >=24.0.0, npm 11.14.1, PHP 8.2, and ripgrep (required for check:drift).

npm install

Quick start

  1. Start the Vite dev server.

    npm run dev
  2. Make the theme available to WordPress by symlinking or copying spectre-theme/ into your local WordPress install.

    ln -s /path/to/spectre-base/spectre-theme /path/to/wordpress/wp-content/themes/spectre-theme
  3. Set your WordPress environment to development mode so the theme loads assets from the Vite dev server instead of spectre-theme/dist.

    define('WP_ENVIRONMENT_TYPE', 'development');
  4. Build production assets when ready to deploy.

    npm run build
    npm run check:assets

Relationship to the rest of Spectre

  • @phcdevworks/spectre-tokens provides the design tokens consumed by the frontend layer
  • @phcdevworks/spectre-ui provides Spectre UI styles and primitives used by the theme layer
  • @phcdevworks/spectre-components provides the web components used directly in WordPress templates

This repository is where those frontend foundations are delivered through a WordPress theme. The theme should consume Spectre output, not redefine it.

By default, the theme stylesheet imports the Spectre UI default bundle, so a fresh install starts from Spectre UI instead of a generic Tailwind-only baseline.

Template hierarchy

The theme ships a complete WordPress template hierarchy. Each file handles a specific route:

Template file WordPress route
index.php Catch-all fallback for all unmatched routes
home.php Blog posts index (when a static front page is set)
front-page.php Static front page
single.php Single post
page.php Static page
archive.php Date, category, tag, and author archives
search.php Search results
404.php Not found
header.php Shared header -- loaded via get_header()
footer.php Shared footer -- loaded via get_footer()
sidebar.php Sidebar -- loaded via get_sidebar()
searchform.php Search form partial
comments.php Comments section

Template parts in spectre-theme/template-parts/:

Part Used by
content-card.php index.php, home.php, archive.php
content-single.php single.php
content-page.php page.php, front-page.php
content-none.php All list templates when no posts are found

Shell class reference

These CSS classes are defined in src/styles/main.css and are safe to use in any PHP template. All values come from var(--sp-*) tokens.

Class Purpose
spectre-site-container Centered, max-width container
spectre-site-header Header shell with neutral background
spectre-site-footer Footer shell with neutral background
spectre-main Main content area with grid spacing
spectre-main--spacious Variant with more block padding
spectre-panel Bordered, padded surface (pages, 404)
spectre-panel--roomy Panel with extra padding
spectre-panel--centered Center-aligned panel
spectre-panel--dashed Panel with dashed border (empty states)
spectre-card Post card with hover shadow
spectre-card__media Image area of a card
spectre-card__body Content area of a card
spectre-card__title Card headline
spectre-card__excerpt Card excerpt text
spectre-card__readmore Card "Read more" anchor
spectre-post-grid Responsive auto-fit grid for cards
spectre-section Content section with gap
spectre-content Post body content area
spectre-entry-meta Date and author metadata row
spectre-eyebrow Small uppercase label
spectre-title-lg Large heading
spectre-title-xl Extra-large heading
spectre-title-2xl 2x extra-large heading
spectre-muted Muted text color
spectre-button Base anchor-as-button shell
spectre-button--primary Primary filled button variant
spectre-widget Sidebar widget wrapper
spectre-widget-title Sidebar widget heading

Using this as a starter

Fork or clone this repository to start a new Spectre-backed WordPress site. Minimum changes for a new site:

  1. Update package.json -- set name and version for your project.
  2. Update the theme header in spectre-theme/style.css -- Theme Name, Theme URI, Author, Author URI, Description, and Text Domain.
  3. Update spectre-theme/readme.txt to match.
  4. Install dependencies: npm install.
  5. Symlink the theme and set WP_ENVIRONMENT_TYPE in wp-config.php (see Quick start above).
  6. Customize shell styles in src/styles/main.css using var(--sp-*) tokens only.
  7. Register social icons via the spectre_base_footer_social_icons filter (see Extension points below).
  8. Build for production: npm run build && npm run check:assets.

Do not rename PHP functions (spectre_base_*) without also updating template calls and the text domain throughout. A project-wide search-and-replace is the safest approach.

PHP hook API

The theme exposes a documented set of action and filter hooks so an agency can customize header, footer, navigation, and sidebar behavior from a child theme or site plugin -- without copying or overriding the parent template files. Each hook below is declared in the listed parent file; place your add_action / add_filter calls in your child theme's functions.php.

Action hooks

Hook Fires in When
spectre_base_before_header header.php Immediately before the <header> element
spectre_base_before_site_branding header.php Inside .spectre-site-branding, before the logo/site title
spectre_base_after_site_branding header.php Inside .spectre-site-branding, after the logo/site title
spectre_base_after_header header.php Immediately after the </header> element
spectre_base_before_footer footer.php Immediately before the <footer> element
spectre_base_after_footer footer.php Immediately after the </footer> element
spectre_base_before_sidebar($sidebar_id) sidebar.php Before the <aside> wrapper, only when the sidebar is active
spectre_base_after_sidebar($sidebar_id) sidebar.php After the <aside> wrapper, only when the sidebar is active
// Inject a promo banner just inside the header, in your child theme's functions.php:
add_action('spectre_base_before_site_branding', function () {
    echo '<p class="spectre-eyebrow">' . esc_html__('Now booking 2026 projects', 'your-child-theme') . '</p>';
});

These complement the core WordPress template-loading hooks that already fire around these files: get_header, get_footer, and get_sidebar (fired by get_header()/get_footer()/get_sidebar() before the file loads), plus wp_head, wp_body_open, and wp_footer inside header.php/footer.php.

Filter hooks

Hook Declared in Purpose
spectre_base_primary_nav_args header.php Filters the wp_nav_menu() args array for the primary navigation
spectre_base_footer_nav_args footer.php Filters the wp_nav_menu() args array for the footer navigation
spectre_base_footer_social_icons footer.php Filters the array of social icon entries rendered in the footer
spectre_base_sidebar_id sidebar.php Filters which registered sidebar ID sidebar.php renders (default sidebar-main)
// Swap the registered sidebar that sidebar.php renders:
add_filter('spectre_base_sidebar_id', fn () => 'sidebar-shop');

// Add a custom menu class to the primary navigation:
add_filter('spectre_base_primary_nav_args', function (array $args) {
    $args['menu_class'] .= ' my-client-nav';
    return $args;
});

Footer social icons

Add site-specific social icon links without modifying the theme directly:

// In your child theme's functions.php or a site plugin:
add_filter('spectre_base_footer_social_icons', function () {
    return [
        ['name' => 'github',   'size' => '20', 'url' => 'https://github.com/yourorg'],
        ['name' => 'linkedin', 'size' => '20', 'url' => 'https://linkedin.com/company/yourco'],
    ];
});

This requires the spectre-icons plugin to be active. If the plugin is not active the social row is not rendered regardless of the filter output.

Swapping templates entirely

For changes too large for a hook -- a fundamentally different header layout, for example -- WordPress's standard child theme lookup already covers you: any file a child theme provides under the same name (header.php, footer.php, sidebar.php, template parts in template-parts/, etc.) takes priority over the parent theme's copy. No filter is required to do this; it is core get_header() / get_footer() / get_sidebar() / get_template_part() behavior. Prefer the hooks above when possible -- they keep you on the parent theme's update path.

CSS custom property namespace

Every --sp-* custom property consumed by this theme is owned and defined by @phcdevworks/spectre-tokens (via @phcdevworks/spectre-ui). The theme itself never declares a --sp-* custom property -- it only reads them with var() in src/styles/main.css and theme.json.

Safe to consume (read-only): any --sp-* variable, in any child theme stylesheet or theme.json, via var(--sp-...). See Adding custom shell styles below.

Not safe to declare: do not define or redeclare a --sp-* custom property in a child theme, site plugin, or theme.json. The --sp-* namespace is reserved for the upstream Spectre token contract; locally redefining one of these variables creates drift between this theme and the design system and will be flagged by npm run check:drift.

To change a token's value for a client brand, do it through the upstream contract -- override the relevant entries in theme.json's settings.color, settings.typography, and settings.spacing palettes/presets (which already reference var(--sp-*)), or configure @phcdevworks/spectre-tokens upstream. Never hardcode a hex, rem, or px value in place of a token reference.

Adding custom shell styles

Add site-specific structural styles in a child theme or an additional CSS file. Always use var(--sp-*) tokens:

/* child-theme/style.css or an additional import */
@layer components {
  .my-hero {
    background-color: var(--sp-surface-alternate);
    padding-block: var(--sp-space-64);
  }
}

Child Themes

Agencies build client sites as WordPress child themes of spectre-base, inheriting the build pipeline, templates, and token contract while keeping client-specific branding isolated.

Generating a child theme

npm run create:child -- <client-name>

This scaffolds spectre-child-<client-name>/ (git-ignored) with:

  • style.css -- WordPress child theme header declaring Template: spectre-theme, GPL license, and WP.org standard tags
  • functions.php -- enqueues the child stylesheet with spectre-base-style as its dependency, so it loads after the parent bundle
  • theme.json -- minimal, inherits the full parent token set and is ready for brand-specific overrides

The Template: spectre-theme header is what tells WordPress this is a child of spectre-base -- it must match the parent theme's directory name exactly.

Overriding tokens via theme.json

Override color, typography, and spacing presets in the child theme's theme.json. Keep every value as a var(--sp-*) reference -- see CSS custom property namespace above. Do not introduce hex codes, raw px/rem values, or new custom properties.

Overriding templates and behavior

  • Full template/template-part overrides -- provide a same-named file (header.php, footer.php, template-parts/content-card.php, etc.) in the child theme directory; WordPress loads it instead of the parent's copy.
  • Targeted hook overrides -- prefer the PHP hook API for smaller customizations (injecting markup, filtering nav menu args, swapping the sidebar, registering social icons). Hooks keep the child theme on the parent theme's update path without forking template files.

Deployment

Development -- symlink spectre-theme/ into WordPress and set WP_ENVIRONMENT_TYPE=development (see Quick start). Assets stream from the Vite dev server with HMR.

Production -- run npm run build, then copy or ZIP the entire spectre-theme/ directory (including dist/) to wp-content/themes/spectre-theme/ on the server. The theme reads dist/.vite/manifest.json to enqueue hashed bundles. Set WP_ENVIRONMENT_TYPE to anything other than development in wp-config.php.

# Build and verify before deploying
npm run check

# ZIP the deployable directory
zip -r spectre-theme.zip spectre-theme/

The dist/ directory must be present in the ZIP. It is generated by the build and is not committed to the repository.

Development

Install dependencies, then run the full verification flow:

npm install
npm run check

This project expects Node.js ^22.12.0 || >=24.0.0, npm 11.14.1, and PHP 8.2.

CSS and JavaScript changes in src/ are reflected instantly in the browser via HMR without a page reload. The Vite dev server runs on http://localhost:5173 by default. To use a different port, define the server URL in wp-config.php:

define('VITE_DEV_SERVER', 'http://localhost:5174');

Common commands

Command What it does
npm run build TypeScript check + Vite production build
npm run check Full validation gate -- must pass before any handoff
npm run check:assets Validate Vite manifest and asset contract
npm run check:drift Scan for hardcoded visual values and design-system drift
npm run lint ESLint for TypeScript
npm run lint:php PHP syntax validation
npm run format Apply Prettier formatting

Key source areas

  • src/js/main.ts -- theme JavaScript entrypoint
  • src/styles/main.css -- theme CSS entrypoint
  • spectre-theme/ -- deployable WordPress theme directory
  • spectre-theme/functions.php -- asset enqueueing, theme setup, env-aware loading
  • spectre-theme/dist/ -- Vite build output (never edit directly)
  • vite.config.ts -- build and dev-server configuration

Validation and drift checks

Run the full validation suite before handing off changes:

npm run check

npm run check is an alias for npm run validate. Both run in order: TypeScript check, Vite build, asset contract, ESLint, PHP lint, and drift scan. CI runs the same command.

check:drift expected output is empty or only token-backed references such as var(--sp-shadow-*) and theme.json token presets. Any local visual value must be removed or justified before merging.

Spectre Icons integration

This theme is compatible with the spectre-icons WordPress plugin. Once the plugin is installed and activated, the [spectre-icon] shortcode is available in any template or content area.

The theme footer automatically renders icon links when the plugin is active:

[spectre-icon name="github" size="20"]
[spectre-icon name="twitter" size="20"]
[spectre-icon name="linkedin" size="20"]

To check availability before rendering icons in a custom template:

<?php if (spectre_base_has_icons()) : ?>
    <?php echo do_shortcode('[spectre-icon name="arrow-right" size="16"]'); ?>
<?php endif; ?>

This pattern works in both the classic editor and the block editor.

Troubleshooting

Failure Cause Fix
Theme loads a blank page in production Compiled manifest is missing or stale Run npm run build then npm run check:assets and confirm spectre-theme/dist/.vite/manifest.json exists and lists src/js/main.ts as an entry
Styles not updating in development Wrong environment or dev server not running Confirm WP_ENVIRONMENT_TYPE=development in wp-config.php and npm run dev is running on the expected port
check:drift reports unexpected matches Raw hex, pixel, rem, or Tailwind utility added to src/ or PHP Replace with a var(--sp-*) token or a Spectre component
PHP lint fails with syntax error PHP syntax error in a template file Fix the reported file, then rerun npm run lint:php (PHP 8.2 is the CI target)
rg not found when running check:drift ripgrep not installed Install ripgrep (brew install ripgrep on macOS, apt install ripgrep on Ubuntu)

AI and automation boundaries

Claude Code (claude-sonnet-4-6) is the primary development agent for this repository. Codex handles releases and production stabilization. Jules handles small automated fixes and dependency updates. GitHub Copilot provides development support.

Claude Code, Codex, and Copilot do not create git commits by default. Jules may commit only bounded automated maintenance when the JULES.md scope and validation gates pass. Final commit, merge, release, tag, and publishing authority remains with Bradley Potts.

Protected from automated change: the Golden Rule (CMS delivers, design system defines -- no local token overrides or hardcoded values), PHP template structure, and the starter-theme boundary (no client-specific identities or brand values in templates). See AGENTS.md for full agent governance and boundary rules.

Contributing

PHCDevworks maintains this package as part of the Spectre system.

When contributing:

  • treat spectre-theme/ template files as structural -- no visual ownership
  • keep CSS token-driven using var(--sp-*) only
  • never hand-edit spectre-theme/dist/ -- run npm run build instead
  • run npm run check as the full validation gate before opening a pull request
  • keep version metadata synchronized across package.json, spectre-theme/style.css, and spectre-theme/readme.txt

See CONTRIBUTING.md for the full workflow.

License

MIT © PHCDevworks. See LICENSE.

About

@phcdevworks/spectre-wordpress-themes is a reusable template for building modern, high-performance WordPress themes.

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

 
 
 

Contributors