Flynt is a WordPress theme for component-based development using Timber and Advanced Custom Fields.
🚧 This repository is a WORK IN PROGRESS. It is not yet ready for use in production. Feel free to try it out and give feedback using GitHub issues.
- Clone this repo to
<your-project>/wp-content/themes
. - Change the host variable in
flynt/build-config.js
to match your host URL:const host = 'your-project.test'
- Navigate to the theme folder and run the following command in your terminal:
# wp-content/themes/flynt
composer install && npm i && npm run build
- Open the WordPress back-end and activate the Flynt theme.
- WordPress >= 5.0
- Node = 10
- Composer >= 1.8
- Advanced Custom Fields Pro >= 5.7
In your terminal, navigate to <your-project>/wp-content/themes/flynt
and run npm start
. This will start a local server at localhost:3000
.
All files in assets
, Components
and Features
will now be watched for changes and compiled to the dist
folder. Happy coding!
The ./assets
folder contains all SCSS, images, and font files for the theme. Files inside this folder are watched for changes and compile to ./dist
.
The main.scss
file is compiled to ./dist/assets/main.css
which is enqueued in the front-end.
The admin.scss
file is compiled to ./dist/assets/admin.css
which is enqueued in the administrator back-end of WordPress, so styles added to this file will take effect only in the back-end.
All PHP files from ./lib
and ./inc
are automatically required.
The ./lib
folder includes helper functions and basic setup logic. You will most likely not need to modify any files inside ./lib
.
The inc
folder is a more organised version of WordPress' functions.php
and contains all custom theme logic.
For organisation, ./inc
has three subfolders. We recommend using these three folders to keep the theme well-structured:
customPostTypes
Use this folder to register custom WordPress post types.customTaxonomies
Use this folder to register custom WordPress taxonomies.fieldGroups
Use this folder to register Advanced Custom Fields field groups. (See Field Groups for more information.)
After the files from './lib' and './inc' are loaded, all components from the ./Components
folder are loaded.
All template files can be found in the ./templates
directory. Flynt uses Timber to structure its page templates and Twig for rendering them. Timber's documentation is extensive and up to date, so be sure to get familiar with it.
There are two Twig functions added in Flynt to render components into templates:
renderComponent(componentName, data)
renders a single component. For example, in theindex.twig
template.renderFlexibleContent(flexibleContentField)
renders all components passed from an Advanced Custom Fields Flexible Content field. For example, in thesingle.twig
template.
Besides the main document structure (in ./templates/twig/_document.twig
), everything else is a component.
A component is a self-contained building-block. Each component contains its own layout, its ACF fields, PHP logic, scripts, and styles.
ExampleComponent/
├── functions.php
├── index.twig
├── README.md
├── screenshot.png
├── script.js
├── style.scss
The functions.php
file for every component in the ./Components
folder is executed during the WordPress action after_setup_theme
. This is run from the ./functions.php
file of the theme.
To render components into a template, see Page Templates.
To define Advanced Custom Fields (ACF) for a component, use Flynt\Api\registerFields
. This has 3 arguments:
Flynt\Api\registerFields($scope = 'ComponentName', $fields = [], $fieldId = null);
$scope
is the name of the component, $fields
are the ACF fields you want to register, and $fieldsId
is an optional (rarely needed) parameter for registering multiple fields for a single scope.
For example:
use Flynt\Api;
Api::registerFields('BlockWysiwyg', [
'layout' => [
'name' => 'blockWysiwyg',
'label' => 'Block: Wysiwyg',
'sub_fields' => [
[
'name' => 'contentHtml',
'label' => 'Content',
'type' => 'wysiwyg',
'required' => 1,
]
]
]
]);
In the example above, the layout
array is required in order to load this component into an Advanced Custom Fields Flexible Content field.
Field groups are needed to show registered fields in the WordPress back-end. All field groups are created in the ./inc/fieldGroups
folder. Two field groups exist by default: pageComponents.php
and postComponents.php
.
To include fields that have been registered with Flynt\Api::registerFields
, use ACFComposer::registerFieldGroup($config)
inside the Inside the Flynt/afterRegisterComponents
action.
Use Flynt\Api::loadFields($scope, $fieldPath = null)
to load groups of fields into a field group. For example:
use ACFComposer\ACFComposer;
use Flynt\Api;
add_action('Flynt/afterRegisterComponents', function () {
ACFComposer::registerFieldGroup([
'name' => 'pageComponents',
'title' => 'Page Components',
'style' => 'seamless',
'fields' => [
[
'name' => 'pageComponents',
'label' => 'Page Components',
'type' => 'flexible_content',
'button_label' => 'Add Component',
'layouts' => [
Api::loadFields('BlockWysiwyg', 'layout'),
],
],
],
'location' => [
[
[
'param' => 'post_type',
'operator' => '==',
'value' => 'page',
],
],
],
]);
});
The registerFieldGroup
function takes the same argument as Advanced Custom Fields's acf_add_local_field_group
with two exceptions:
- The fields do not require field keys but are automatically generated.
- For conditional logic, instead for specifying a field key as reference, you can specify a field path. For example:
[
'label' => 'Include Button',
'name' => 'includeButton',
'type' => 'true_false',
],
[
'label' => 'Button Text',
'name' => 'buttonText',
'type' => 'text',
'conditional_logic' => [
[
[
'fieldPath' => 'includeButton',
'operator' => '==',
'value' => 1'
]
]
]
]
Conditional logic can also target fields one level higher. This is useful when targetting fields inside of a repeater. For example:
[
'label' => 'Include Buttons',
'name' => 'includeButtons',
'type' => 'true_false',
],
[
'label' => 'Items',
'type' => 'repeater',
'name' => 'items',
'sub_fields' => [
[
'label' => 'Button Text',
'name' => 'buttonText',
'type' => 'text',
'conditional_logic' => [
[
[
'fieldPath' => '../includeButtons',
'operator' => '==',
'value' => 1
]
]
]
]
]
]
More information can be found in the ACF Field Group Composer repository.
Registered fields can also be used statically (not inside a flexible content field). To do this, we strongly suggest putting the fields for a component in an ACF group field, so that you are able to easily retrieve all the associated fields.
For Example:
use ACFComposer\ACFComposer;
use Flynt\Api;
add_action('Flynt/afterRegisterComponents', function () {
ACFComposer::registerFieldGroup([
'name' => 'pageComponents',
'title' => 'Page Components',
'style' => 'seamless',
'fields' => [
[
'name' => 'mainContent',
'label' => 'Main Content',
'type' => 'group',
'sub_fields' => [
Api::loadFields('BlockWysiwyg', 'layout.sub_fields'),
],
],
],
'location' => [
[
[
'param' => 'post_type',
'operator' => '==',
'value' => 'page',
],
],
],
]);
});
Flynt includes several utility functions for creating Advanced Custom Fields options pages. Briefly, these are:
Flynt\Utils\Options::addTranslatable
Adds fields into a new group inside the Translatable Options options page. When used with the WPML plugin, these fields will be returned in the current language.Flynt\Utils\Options::addGlobal
Adds fields into a new group inside the Global Options options page. When used with WPML, these fields will always be returned from the primary language. In this way these fields are global and cannot be translated.Flynt\Utils\Options::get
Used to retrieve options from Translatable or Global options.
If you are using Flynt and WPML, you will need to create a Must-Use (MU) Plugin in order to load Twig from Timber before the WPML code is executed. This is because WPML includes an outdated version of Twig.
To do this, create /wp-content/mu-plugins/flynt-wpml-compat.php
and add this code:
<?php
$autoloadPath = get_template_directory() . '/vendor/autoload.php';
if (file_exists($autoloadPath)) {
require_once $autoloadPath;
new \Timber\Timber();
}
This will ensure Twig is loaded from Timber, not WPML.
This project is maintained by bleech.
The main people in charge of this repo are:
To contribute, please use GitHub issues. Pull requests are accepted. Please also take a moment to read the Contributing Guidelines and Code of Conduct.
If editing the README, please conform to the standard-readme specification.
MIT © bleech