Hozokit gives you the power to create unique WordPress themes without the WordPress hassle.
By combining modern web technologies and a component based architecture, Hozokit is a theme building framework structured clearly for both, long-time WordPress developers and beginners.
With Gulp built-in, theme development is streamlined from the off, freeing you from arduous project setup by handling configuration and automation tasks for you. Meaning you can dive straight in to your next project. Hozokit automatically bundles styles, transpiles scripts, watches for changes and handles component files. Meaning you can get right to coding.
Hozokit uses Timber which keeps your PHP theme code clean so you can focus on supplying the data and logic, while Twig is used for your HTML output. For styling, SCSS is used in favour of others.
The component based approach helps to streamline development with markup and styling mostly scoped to their own components. Components are scoped to their respective files and can be used on demand by higher order pages such as 'index'
, 'pages'
and other.
Hozokit can also make use of Advanced Custom Fields if you choose. This combination enables the creation of custom Gutenberg blocks without the need to introduce React in the codebase, this can be useful if you would like to stick mostly with HTML, CSS, Javascript and PHP.
This is not a library but can rather be seen as an initial setup to jumpstart the development of custom themes for WordPress.
- WordPress
5.0
- MySQL
8.0.19
- PHP
7.2.32
- Node
14.15.1
One way to create a new project is to use the Hozokit Generator powered by Yeoman.
The generator creates a project folder with a Hozokit theme with the option to install WordPress as well.
Having a PHP server setup and a database to configure WordPress is still required.
npm install -g yo
npm install -g generator-hozokit
Then generate your new project:
yo hozokit
Twig components can also be generated by changing directory into the project:
yo hozokit:component
Once the generator has finished running, the following steps might be required if not done already:
-
Setup a webserver capable of running PHP and create a mySQL database for WordPress. Read how to install WordPress to learn more.
-
If dependencies fail to install: Manually install Hozokit Node dependencies for your theme.
- Change directory to
your-project-name/wp-content/themes/your-project-name
- Check you are using Node version 14.15.1 by running
node --version
- Run
npm install
to install dependencies
- Change directory to
-
To start development run
npm start
Download WordPress and copy the template folder to wp-content/themes
folder.
Rename the template folder to match your chosen theme name.
Create a database and either add the details to a wp-config.php
file or setup using the WordPress onboarding.
A webserver with PHP and mySQL installed is required in order to follow these steps.
Navigate to the theme directory and set the Node version to the one available in .nvmrc
. In this example the Node Version Manager is used, but other methods of setting the version can be used.
Given that nvm
is installed:
# Please check the included .nvmrc to get the correct version number.
nvm install 14.15.1
# Will make use of .nvmrc to set the version.
# There might be a prompt to install the requested Node version if it's not present already.
nvm
Running npm scripts on WSL2 ⚠️
This is required for Windows users who have a WSL2 setup.
There is an issue (described here and here) where Windows Subsystem Linux 2 won't listen to any changes made via a text editor running on Windows.
If you're a WSL2 user, these are the steps we took to solve the issue temporarily until a patch is released:
- Install Node for Windows
- Install nvm for Windows
- Open a Powershell window as an Administrator
- On the Powershell, navigate to the theme directory. e.g wp-content/themes/hozokit
- Run nvm use 14.15.1 (in this case .nvmrc seems to be ignored so it needs to be specific)
- npm install (if not already done)
- npm start (to watch changes)
Any other tasks can still run on WSL2, however any Node tasks should be run from the Powershell to avoid issues.
Download and install dependencies (requires Node
):
npm install
When changing scripts and styling run the following commands (might require gulp-cli
installed globally):
npm start
# or
npm run watch
In order to build without watching for changes:
npm run build
See
gulpfile.js
for all tasks.
Create an .env
file in the theme folder directory. An .env.example
file is provided as a starting point. See related documentation for details.
Hot Reloading can be enabled once the steps above have been followed.
- Make sure you have Docker installed and running on your machine.
- Using the terminal
cd
into the theme folder directory (e.gwp-content/themes/hozokit
) wheredocker-compose.yml
is located. - Run
docker compose up --detach
in order to get the project running. - Export the production database into an SQL dump with a method of your choice. (This requires access to the server and cPanel) (optional)
- Import database using a software of your choice (e.g MySQL Workbench or Table Plus), use the credentials below to connect to the database container. (optional)
- Once imported add any plugins to
docker/volumes/wordpress/plugins
. These can be downloaded from the cPanel file manager. (optional) - Add the uploads folder to
docker/volumes/wordpress/uploads
. Can also be downloaded from the cPanel file manager. (optional) - Access
localhost:8080
via the browser and sign in with one of the users available in the production version of the site. - Make changes in the files and develop your theme.
IP: 127.0.0.1
PORT: 3307
DATABASE NAME: wordpress
USER: wordpress
PASSWORD: password
ROOT PASSWORD: password
⚠️ These credentials are generated when the container is created and are meant to be used in development only.
- Run
docker compose up --detach
. - Access the project in the browser via
localhost:8080
. - Make any changes in the files.
- Run
docker compose down
to stop the containers.
Why don't I have to run
npm run watch
or install Node dependencies? That's because one of the Docker containers has taken care of that for you. Seewp-content/themes/hozokit/docker/node.dockerfile
to learn more.
A starting point is to set the theme name and other information at hozokit/styles/base.scss
. A custom screenshot.png
can also be added later on to better identify the theme.
This implementation uses Timber and most of the markup will be written in Twig, a template engine for PHP that allows you to separate logic markup.
This means that the HTML
can include values that come from PHP
scrips. Using Timber also abstracts some of the WordPress API in order to make it friendlier to use.
A component will usually live in /templates/components
unless it is a part of the WordPress' template page system. Each component is composed of a index.twig
and a styles.scss
.
For instance a navigation
component could be created by adding the two files mentioned before to templates/components/navigation
. Then it can be included in pages, become part of other components and be reused as needed.
The idea behind this pattern is to separate markup from PHP logic. To achieve this we use $context
, a PHP associative array that holds the data to be used in templates.
The data available to these templates can be scoped to a WordPress view (index.php
, single.php
, page.php
and so on) or globaly meaning they can be accessed from any template at any time.
To define context for a specific view, we first get the current Timber context and add to it just like adding to any other associative array. Here's an index.php
as an example:
<?php
// Get Timber's context.
$context = Timber::get_context();
// Add new data to this specific view.
// In this case the current instance of the post (userful to get the title of the page for example)
// and an array with all posts
$context['post'] = new Timber\Post();
$context['posts'] = Timber::get_posts();
// Then the Twig template that should be rendered is specified
// and the $context with the new added values is passed to it.
Timber::render( 'index.twig', $context);
?>
Now all values currently present in $context
are available to index.twig
alongside the new post
and posts
values we've added in. Here's how to access these values in index.twig
:
{% block content %}
{# Using the post data added to context #}
<h2>{{post.title}}</h2>
<p>{{post.content}}</p>
<h3>Posts:</h3>
<ol>
{# Using the posts data added to context #}
{% for post in posts %}
<li><a href="{{post.link}}">{{post.title}}</a></li>
{% endfor %}
</ol>
{% endblock %}
Now the values can be accessed through a variable using dot notation, nice!
However, post
and posts
won't be available outside index.twig
. Sometimes it is useful to have values in $context
that can be accessed in any template.
This is useful when, for example, it is needed to display dynamic information on a footer, or perhaps there's a menu that shows in all pages, or the user avatar.
To add data to $context
that can be accessed in any template (globally) we need to make use of a filter. Here's an example in functions.php
:
// Adds additional data to the site context.
// This makes it available in the templates.
// The filter is required so the data is added at the correct stage.
add_filter( 'timber/context', function( $context ) {
# Add the new data here.
$global_context = array(
'example' => 'add new entries to this array to make them available anywhere in any Twig template.',
'user_is_admin' => current_user_can('administrator')
);
# Merges your additions with the current context.
$context = $context + $global_context;
return $context;
} );
To use it, we can reference it in our templates the same way as before. Here's an updated example of index.twig
, notice how example
is used but it was not added to context via index.php
but via functions.php
:
{% block content %}
{# Added via index.php #}
<h2>{{post.title}}</h2>
<p>{{post.content}}</p>
<h3>Posts:</h3>
<ol>
{# Added via index.php #}
{% for post in posts %}
<li><a href="{{post.link}}">{{post.title}}</a></li>
{% endfor %}
</ol>
{# Added via functions.php and can be accessed in other templates #}
<blockquote>{{example}}</blockquote>
{% endblock %}
Styles are written in SCSS files and are then merged and converted into a style.css
for the browser to understand. There are two strands of files, base files that live in /styles
such as base.scss
or palette.scss
which hold rules that multiple elements and components make use of.
Then there are more indivual files that define styling for a single component. Each component has a styles.scss
file attached to it and styles from components can make use of what is defined in base.scss
.
When styling components it is important that they have their own class
in order to avoid unexpected results in styling as all the rules will be merged into a single file.
When styling components make sure to run npm run watch
or npm start
from the terminal in order to update styles.
To enable Hot Reloading follow this link for more information.
Scripts should be imported into /scripts/index.js
, ECMAScript 2015+ (ES6) is supported as similar to the styling, scripts are transpiled and then bundled into a single file at assets/scripts/bundle.js
.
Scripts can be split into multiple files and imported as needed.
Please feel free to ask any questions, add suggestions or point out bugs by creating an issue. Pull requests are welcome as well! Thank you 🙇🏻