Starter template for nonfiction WordPress themes using nf, Timber, Twig, Composer, and Vite.
This repository is intended to be copied for new agency WordPress theme projects. The repo-level workflow is nf first; raw Composer, npm, Docker, and WP-CLI commands are implementation details underneath that command surface.
Enter the development shell from the repository root:
nix developRefresh theme dependencies through nf:
nf theme composer
nf theme npmStart the local WordPress environment:
nf env upSeed starter content, set Post name permalinks, create the primary menu, and remove Hello Dolly:
nf theme seedShow local URLs, ports, paths, and env metadata:
nf env showWatch theme assets during development:
nf theme watchRun WP-CLI inside the local environment:
nf env wp -- plugin list
nf env wp -- post-type listnf.json is the project manifest. It records the project slug, WordPress theme path, theme slug, local env settings, configured plugins, artifact path, remotes, and theme tasks.
Useful commands:
nf theme tasks
nf theme format
nf theme lint
nf theme test
nf theme build
nf theme package
nf theme release
nf theme seedLocal environment commands:
nf env up
nf env down
nf env logs
nf env shell
nf env wp -- <args>
nf env plugins list
nf env plugins status
nf env plugins install
nf env snapshot listRemote and release commands are configured per project:
nf remote list
nf remote add production
nf theme deploy production --dry-run
nf theme deploy production
nf theme rollback production --dry-runnf theme package zips the files that already exist. It does not run Composer, npm, or the asset build first. Use nf theme release for the normal build, check, and package sequence.
Configured tasks live in nf.json.
Current tasks:
nf theme build # Build Vite assets
nf theme composer # Update Composer dependencies and optimized autoload
nf theme format # Format authored PHP files
nf theme lint # Run PHP checks and JavaScript lint
nf theme npm # Update npm development dependencies
nf theme release # Build, lint, and package the theme artifact
nf theme seed # Seed starter WordPress content
nf theme test # Alias for all theme checks
nf theme watch # Watch Vite assetsTheme source lives in theme/.
Important paths:
theme/app/ Theme application code
theme/app/views/ Global Twig templates and native post/page helpers
theme/app/blocks/ Reusable custom blocks
theme/app/<cpt>/ Custom post type modules
theme/config/ WordPress configuration hooks
theme/src/ Theme PHP classes
theme/dist/ Built Vite assets
theme/vendor/ Composer dependencies
Use theme/app/<cpt>/ for custom post types. Native WordPress post/page view helpers belong in theme/app/views/, not in theme/app/post/ or theme/app/page/.
PHP-CS-Fixer is the canonical PHP formatter for this starter. The project policy lives in theme/.php-cs-fixer.dist.php and uses PSR-12 plus agency preferences: 2-space PHP indentation, short arrays, ordered imports, unused import removal, single quotes where appropriate, trailing commas in multiline structures, readable spacing, and no Yoda-style requirement.
Format PHP:
nf theme formatCheck PHP style without modifying files:
composer --working-dir=theme check:php-styleThe fixer is scoped to authored theme PHP: app, config, src, and root theme PHP files such as functions.php and index.php. Generated and dependency directories such as vendor, node_modules, assets/dist, dist, and build artifacts are excluded.
Neovim should use the project-local binary at theme/vendor/bin/php-cs-fixer and automatically pick up theme/.php-cs-fixer.dist.php when editing files in this project. CI should run the same Composer scripts rather than using a global formatter configuration.
Run the full configured check path:
nf theme testStart or repair the local environment:
nf env upSet pretty permalinks after a fresh env, if needed:
nf theme seedThe seed task sets permalinks to Post name, removes Hello Dolly if installed, creates starter pages, creates a Primary menu with the slug primary, assigns it to the primary theme location, seeds a Block Examples page, and sets Home as the static front page.
Inspect local WordPress state:
nf env wp -- theme list
nf env wp -- post-type list
nf env wp -- plugin listConfigured plugins are listed in nf.json under wordpress.plugins. This list is bootstrap intent, not a complete plugin lifecycle manager.
Seeded QA routes:
/
/about/
/services/
/block-examples/
/resources/
/resources/resource-one/
/resources/resource-two/
/contact/
/articles/
/articles/starter-article/
/search/starter/
/not-a-real-page/
Generic reusable blocks live in theme/app/blocks/.
Current starter block set:
nf/banner: full-width page introduction with a background image, heading, and optional supporting textnf/aside: supporting callout with a heading and nested contentnf/grid: Card Grid, a responsive container for repeated contentnf/card: card intended for use insidenf/gridnf/accordion: Content Accordion, grouped expandable contentnf/accordion-item: single item insidenf/accordion
Keep this set compact. Client-specific blocks should either be deleted before starting a new project or moved under theme/app/<cpt>/blocks/ when they belong to a custom post type.
When copying this starter for a client project, update these values before doing feature work:
nf.jsonproject.slugnf.jsonwordpress.theme_slugnf.jsonartifact.paththeme/style.cssTheme Name,Text Domain,Description, andVersiontheme/package.jsonname,version, and repository URLtheme/composer.jsonnameanddescription- README title and project description
- Any block names, labels, or namespaces that should become client-specific
- Any configured plugins in
nf.jsonthat are not appropriate for the project
The theme slug matters because nf theme package uses wordpress.theme_slug as the zip root directory, even when source files live in wordpress.theme_path.
Before packaging or deploying a theme release:
nf theme releaseFor remote deploys, preview first:
nf theme deploy production --dry-runThen deploy when the plan is correct:
nf theme deploy production