Skip to content
Switch branches/tags

Latest commit


Git stats


Failed to load latest commit information.
Latest commit message
Commit time


Primera is a WordPress theme with a modern development workflow.

Table of Contents


  • Laravel's Blade templating engine
  • Laravel's Mix webpack wrapper
  • Controllers for template data passing
  • Modern JavaScript via Babel.js
  • Modern CSS via Sass, Less, Stylus or PostCSS
  • Autoprefixer and Browserlist
  • Browsersync live updates
  • Composer and NPM package managers
  • Composer PSR-4 autoloader
  • Build scripts for zip and pot files
  • Single point Dotenv configuration
  • GPL Licensed


Make sure all dependencies have been installed before moving on.


Download WordPress, either manually or via the terminal using WP CLI.

$ wp core download --path=my-project

Then open the themes directory in your terminal.

$ cd my-project/wp-content/themes

If you don't have Composer installed, go ahead and do that now. Then run the following command in your terminal.

$ composer create-project gooddaywp/primera my-theme-name

Last but not least, run the following command to install all NPM packages.

$ cd my-theme-name && npm install


Quick Start

To take Primera for a spin, take the following steps after the installation is complete.

  1. Search and replace primeraTextDomain with your preferred text domain
  2. Open the .env file and adjust the values to fit your project
  3. Run npm start in the terminal (from within this folder)
  4. Visit the localhost URL displayed in the terminal

Autoprefixer & CSS

Due to the Autoprefixer PostCSS plugin, there's no need for writing vendor prefixes in CSS. Browserlist is used to let you adjust which browsers you wish to support by modifying the .browserlistrc file using this guide.

Please also remember that Autoprefixer can't help older browsers understand CSS properties which they simply do not support. For a great place to check which browser supports what, visit

Webpack & ES6

Primera enables you to use all ES6 features via Laravel Mix and Webpack. If you are new to ES6, below are helpful links to get you started.

Mix & NPM Scripts

Primera uses Laravel Mix, which is a wrapper around webpack. Mix makes it really easy to setup your module bundling and asset compilation. It's configuration file can be found at ./webpack.mix.js. The NPM command run allow you to run any of the commands that are with the "script" section of you package.json file. Use the following commands to build, translate and develop your theme.

npm start
Shortcut to run npm run watch.

dev or development
Renders all assets uncompressed and without watching for changes.

prod or production
Renders all assets compressed and without watching for changes.

Starts browsersync and renders all assets uncompressed. This task will keep watching for changes to your assets and refresh you browser window when changes are detected. The task can be exited via the keyboard shortcut ctrl+c.

Will create a .pot file with your languages directory. This file is used by WordPress to allow for translation.

Will run build before it can create a Zip file of your theme and place it within the directory you specified within the .env file.

This will first run npm prod, then npm pot and then copy the files you specified with the .env to the directory you specified within the .env file. Thereafter this task will also create a Zip file of the current build.

Folder Structure

This folder holds the template Controllers and theme helpers functions. This folder maps to the autoload PSR-4 setting within composer.

The config folder gives theme and plugin configuration examples as a staring point. Feel free to modify, remove or add as you please.

This folder holds assets such as images, fonts as well as compiled asset (CSS & JS) coming from the source folder. You can store other static assets in here as well.

The source folder holds assets that need compiling i.e. CSS, JS. The views folder holds the Blade template files which are also compiled/cached and are place in the directory specified via /config/primera.php.

This folder holds build scripts. They are placed into theme vs. an NPM package so you can modify them suit your project's needs.

The template folder holds custom WordPress page tempaltes.

App Files

Throughout the theme, "app" files are used to handle data that's ment to be applied to the theme globally.

This file supplies values globally to all Blade templates.

/source/css/app.css & /source/js/app.js
These files compile global JS & CSS.

This is the main template file that other views are extending.

Controllers, Views & View Scripts

Controller class names follow the same hierarchy as WordPress. Meaning, to create a controller for the front-page.php WordPress template, you would create a Controller with the class name FrontPage.php inside the Controllers folder. The controller will automatically be loaded for this template file.

Primera will tell WP to look for the coresponding Blade template (AKA view) inside the views directory. The template name does not need to be modified. Meaning, front-page.php or front-page.blade.php will both work.

If you prefer to use the default WordPress template, simply place it into the root level of your WP theme. However, Controllers and Blade templating won't work in this case.

Primera will also look for so called view scritps inside your public folder. Meaning, CSS or JS scritps with same name as the WP template (e.g. front-page.css) will get automatically enqueued on the front page template.

To make data available to the views, you simply create public functions within the Controllers. Each function with represent a variable that's passed to the view. All function names will be converted to snake_case. Meaning, myCoolFnName will become my_cool_fn_name. So it's probably best to write the fucntions with your Controllers in sanke case to not cause confusion later down the line.

Please have a look at the soberwp/controller documentation to fully understand how they work.

AJAX Actions & REST Routes

You are free to handle AJAX & REST any which way you like. However, Primera does offer a confient way to enqueue your REST routes and AJAX actions. In addition to lifecycle methods of the Controllers, Primera adds two more lifecycle methods (__ajax_actions & __rest_routes) to ease including REST and AJAX callbacks.

Because the Controllers are loaded via WP's init action hook, these methods are also load via this hook. The __rest_routes method is then hooked via rest_api_init. To separate asynchronous code from the rest of the Controller, an example using a PHP trait is supplied. However, you could also write the code directly into the Controller if you prefer.

Please note that all AJAX & REST callbacks are static. Controllers will not reveal static methods as data to your views. If the ajax/rest callbacks were defined as a normal public functions, their die() statements would break the page, since all public functions are automatically exposed to the respective view. Defining the function as static circumvents this, while still allowing the function to run.

Blade Templating

Laravel's Blade templating is super easy to learn. Simply have a look at the documentation and the demo files within /source/views and you will be up and running in no time.

Custom Blade Directives

Blade templating allows for the creation of custom directives, and component aliases. To see a demo on how this works, have a look at /config/primera.php.

The composer package primera-lib already adds the following directives to be used within Blade templates.

Displays the contents of the variable.

Displays the contents of the variable and exits the script via die().

Displays all Controller data on the page.

Displays all available variables wrapped with currly braces. Useful for grabbing all data supplied to your view and distributing it accross your template file.

Same as @code but with @if statements around the data.

Dotenv Configuration

In Primera the .env file works a bit differently.

Dotenv files are often used for safe keeping of sensitive informaiton like API keys and are also not commited to version control (e.g. Github). Usually, these .env files hold information specific to the environment where your app or site lives.

Within this project .env files represent a singular point to set not environment, but project specific data that can be accessed via Node.js and PHP alike. The .env file can and should therefor also be commited to your version control system.

There are a couple important things to note regarding .env files within Primera.

  • Please do not put sensitive information (e.g. API keys) into it
  • Due to the dotenv NPM package, the following does not currently work
    • Line breaks are not supported, each value must be writen in one line
    • Nesting variables is currently not possible
  • Primera converts comma separated strings to arrays in PHP (e.g. "one, two, three" becomes ["one", "two", "three"])

Config Folder & Hierarchy

Primera uses the composer package Brain\Hierarchy. This package allows you check the template hierarchy within your theme's config (/config) and load different configurations for different templates. Below is an example of how to set this up.

use Brain\Hierarchy\Hierarchy;
$templates = (new Hierarchy)->getTemplates($GLOBALS['wp_query']);
if (in_array('archive', $templates)) {
    // code for archive.php

Helper Functions

Primera comes with a couple of helper functions to make your life a bit easier. These functions can be found with the /app folder.

Most of Laravel's helpers functions are also available within Primera. To learn more about them, please visit the documentation or have a look at the source code (./vendor/illuminate/support/helpers.php).


Translateble strings need to be defined in the controllers due to how wp-pot node module works. It cannot read blade files because it doesn't recognize blade as PHP.

Still To-Do

  • Create proper comments example at /source/views/components/comments.blade.php
  • Add config code to prevent theme updates from
  • Zip task must first run build task if no build exists
  • Add composer validate --no-check-all --strict to build script to ensure composer json and lock file are identical
  • Create more useful starting setup for views
  • Find better solution for shared config file than .env, or make .env more secure
  • Add replace-in-file node module to repalce certain strings like text-domain (useful for install or build process)
  • Add notes about using WooCommerce blade templates
  • Use WP CLI command $ wp i18n make-pot instead of NPM module
  • Add to PostCSS: