Project Structure
A high-level map of what lives where and why.
Directorylumbermill/
Directoryacf-php/ ACF field group definitions (PHP)
- …
Directoryapp/ Theme PHP application code
- …
Directoryassets/src/ Frontend source files (JS, SCSS, fonts, images)
- …
Directoryconfig/ Developer-facing configuration
- …
Directorytemplates/ WordPress page templates (selectable in admin)
- …
Directorytranslations/ JSON translation files (one per locale)
- …
Directoryviews/ Twig templates
- …
- functions.php Theme bootstrap
- front-page.php Front page WordPress template
- page.php Default page WordPress template
- single.php Single post WordPress template
acf-php/
Section titled “acf-php/”All ACF field groups are defined in PHP here. Organise by context — each subfolder maps to a part of WordPress.
Directoryacf-php/
Directoryglobal/ Fields attached to all post types (e.g. featured image)
- …
Directorypages/ Fields for specific WordPress pages (e.g. front-page)
- …
Directorypost-types/ Fields for custom post types
- …
Directorytemplates/ Fields for page templates
- …
Directoryoption-pages/ Fields for ACF options pages
- …
Directoryflex/ Flexible content layout definitions
- …
Directoryhelpers/ Shared utilities (loadFieldGroup, advanced-link, etc.)
- …
- index.php Entry point — autoloads every nested index.php
See the ACF guide for how to create field groups.
PHP application code. Everything here is autoloaded under the App\ namespace.
Directoryapp/
DirectoryCache/ Cache driver implementations
- …
DirectoryClassmap/ Timber class extensions (Post, Term, Menu, MenuItem)
- …
DirectoryConstant/ String constants — PostTypeConstant, TaxonomyConstant, etc.
- …
DirectoryEnum/ PHP enums
- …
DirectoryHook/ WordPress hooks and filters
- …
DirectoryLib/ Framework internals — do not modify
- …
DirectoryUtil/ Reusable utility classes
- …
Where does new code go?
| What you’re building | Folder |
|---|---|
| WordPress hook / filter | app/Hook/ |
| Extending a Timber post/term/menu | app/Classmap/ |
| A reusable helper | app/Util/ |
| A post type or taxonomy slug | app/Constant/ |
| An AJAX action | app/Ajax/Action/ (see Ajax) |
| A REST endpoint | app/RestAPI/ (see REST API) |
assets/src/
Section titled “assets/src/”Frontend source files processed by Vite.
Directoryassets/src/
Directoryjs/
Directorylib/ Shared JS utilities and helpers
- …
Directorymodules/ Feature-specific JS modules
- …
Directoryvendor/ Third-party scripts not managed by npm
- …
- site.js Main entrypoint
Directoryscss/
Directoryabstracts/ Variables, mixins, functions
- …
Directorybase/ Reset, typography, global styles
- …
Directorylayout/ Grid, containers, structural styles
- …
Directorypages/ Page-specific styles
- …
Directorypartials/ Component styles
- …
Directoryvendor/ Third-party CSS overrides
- …
config/
Section titled “config/”Plain PHP arrays that control theme behaviour. Every file has a corresponding provider that acts on it at boot time. See the Config section for a full reference of each file.
templates/
Section titled “templates/”WordPress page templates — selectable from the WordPress admin when editing a page. Each file here passes data to a Twig template in views/templates/.
See Page Templates for the full workflow.
views/
Section titled “views/”All Twig templates. Never called directly — always rendered via Timber::render() in a PHP template.
Directoryviews/
Directorylayouts/ Base HTML layouts (base.twig)
- …
Directorypartials/ Reusable includes (header, footer, head, buttons, images)
- …
Directorytemplates/ Page-level templates, one per PHP template
- …
functions.php
Section titled “functions.php”The theme bootstrap. Loads config files and boots providers. The only things that belong here are:
- Custom providers:
$config->addProvider(new MyProvider); - Custom provider overrides:
$config->replaceProvider(ThemeProvider::class, new MyThemeProvider);
Everything else should live in a provider or a hook class.

