Starter Theme
studiometa/foehn-starter is the minimum a new project needs: the boot, the configuration, the templates a theme cannot render without, and the front-end build. Nothing else.
That is deliberate. A starting point you delete half of is worse than one you add to, so the demonstrations live in the demo project — every attribute the framework ships, in a theme you can read and run.
Quick Start
With DDEV (Recommended)
composer create-project studiometa/foehn-starter my-project
cd my-project
ddev startThat's it! DDEV will automatically:
- Start PHP 8.5 + MariaDB + nginx
- Create
.envfrom.env.example - Run
composer install(generatesweb/, symlinks, wp-config.php) - Install WordPress with admin/admin credentials
- Activate the starter theme
Open your site:
ddev launch # Frontend
ddev launch /wp/wp-admin # Admin (admin / admin)Without DDEV
composer create-project studiometa/foehn-starter my-project
cd my-project
cp .env.example .env
# Edit .env with your database credentials
composer installThen point your web server's document root to the web/ directory.
Project Structure
my-project/
├── theme/ # WordPress theme (versioned)
│ ├── app/
│ │ ├── ContextProviders/ # GlobalContextProvider — data every template gets
│ │ ├── Controllers/ # single, archive, search, 404
│ │ ├── Hooks/ # theme supports, excerpt length
│ │ ├── Menus/ # header, footer, legal
│ │ └── foehn.config.php # Framework configuration
│ ├── assets/
│ │ ├── css/app.css # Tailwind entry point
│ │ └── js/app.js # js-toolkit entry point
│ ├── templates/ # Twig templates
│ │ ├── layouts/base.twig
│ │ ├── pages/ # single, archive, search, 404
│ │ └── components/ # header, footer, card, pagination
│ ├── functions.php # Single boot line
│ └── style.css # Theme header
│
├── web/ # Generated document root (gitignored)
│ ├── wp/ # WordPress core
│ ├── wp-content/ # Plugins, uploads
│ └── wp-config.php # Generated config
│
├── .ddev/ # DDEV configuration
├── vite.config.js # Vite, with @studiometa/foehn-vite-plugin
├── .env # Environment variables
└── composer.json # DependenciesWhat's Included
Every class in theme/app/ is one a theme needs before it renders anything:
| Class | Why it is here |
|---|---|
Controllers/ | Answer WordPress's template hierarchy — single, archive, search, 404 |
Menus/ | The three locations header.twig and footer.twig read |
ContextProviders/ | Puts current_year and is_home in every template |
Hooks/ThemeHooks | Theme supports, excerpt length and more |
foehn.config.php | The discovery cache, and the framework's cleanup and security hooks |
There are no post types, blocks, taxonomies, settings pages or bindings. Add your own with the make: commands, or copy one from the demo.
Security & Cleanup Hooks
theme/app/foehn.config.php opts into the framework's own:
return new FoehnConfig(
discoveryCacheStrategy: DiscoveryCacheStrategy::FULL,
hooks: [
CleanHeadTags::class, // Remove unnecessary <head> tags
DisableEmoji::class, // Remove emoji scripts and styles
DisableOembed::class, // Remove oEmbed discovery
DisableVersionDisclosure::class, // Hide the WordPress version
DisableXmlRpc::class, // Disable XML-RPC and pingbacks
GenericLoginErrors::class, // Hide username enumeration on login
YouTubeNoCookieHooks::class, // Use the no-cookie YouTube domain
],
);DDEV Commands
ddev start # Start the environment
ddev stop # Stop the environment
ddev restart # Restart after config changes
ddev launch # Open site in browser
ddev ssh # SSH into the container
ddev composer <cmd> # Run Composer commands
ddev wp <cmd> # Run WP-CLI commands
ddev describe # Show URLs and infoCustomizing the Starter
Rename the Theme
- Update
theme/style.csswith your theme name - Update
composer.jsonextra config:json"extra": { "foehn": { "theme-name": "your-theme-name" } } - Run
composer installto regenerate symlinks
Add Plugins
Add WordPress plugins via Composer using wpackagist:
ddev composer require wpackagist-plugin/advanced-custom-fields-proEnvironment Variables
The .env file controls database connection and environment:
DB_NAME=db
DB_USER=db
DB_PASSWORD=db
DB_HOST=db
WP_ENV=development
WP_DEBUG=true
WP_HOME=https://my-project.ddev.siteDeployment
For production:
- Set
WP_ENV=productionandWP_DEBUG=false - Discovery cache is already enabled (
DiscoveryCacheStrategy::FULL) - After deployment, warm the cache:bash
wp foehn discovery:generate
Next Steps
- Read the demo for one worked example of every attribute
- Learn about Post Types to add your first one
- Declare custom fields with #[AsPostMeta], or add ACF when you want its editing UI
- Configure Template Controllers for complex layouts
- Review Theme Conventions for best practices