Website
Documentation
Releases
Support
- Harness the power of Laravel and its available packages thanks to Acorn.
- Clean, efficient theme templating utilizing Laravel Blade.
- Lightning fast frontend development workflow powered by Bud.
- You must use
.eslintrc
rules in the app development.
Make sure all dependencies have been installed before moving on:
- Acorn v2
- WordPress >= 5.9
- WP CLI
- PHP >= 7.4.0 (with
php-mbstring
enabled) - Composer
- Node.js >= 16
- Yarn
Make sure your local DB_HOST is set to: 127.0.0.1
Install Sage in your WordPress themes directory and fire the following commands in directory:
composer install
yarn && yarn build
themes/your-theme-name/ # → Root of your Sage based theme
├── app/ # → Theme PHP
│ ├── Core/ # → Theme core files
│ ├── Providers/ # → Service providers
│ ├── View/ # → View models
│ ├── filters.php # → Theme filters
│ └── setup.php # → Theme setup
├── composer.json # → Autoloading for `app/` files
├── public/ # → Built theme assets (never edit)
├── functions.php # → Theme bootloader
├── index.php # → Theme template wrapper
├── node_modules/ # → Node.js packages (never edit)
├── package.json # → Node.js dependencies and scripts
├── resources/ # → Theme assets and templates
│ ├── fonts/ # → Theme fonts
│ ├── images/ # → Theme images
│ ├── scripts/ # → Theme javascript
│ ├── styles/ # → Theme stylesheets
│ └── views/ # → Theme templates
│ ├── components/ # → Component templates
│ ├── forms/ # → Form templates
│ ├── layouts/ # → Base templates
│ ├── partials/ # → Partial templates
└── sections/ # → Section templates
├── screenshot.png # → Theme screenshot for WP admin
├── style.css # → Theme meta information
├── vendor/ # → Composer packages (never edit)
└── bud.config.js # → Bud configuration
yarn dev
— Compile assets when file changes are made, start dev sessionyarn build
— Compile assets for production
Firestarter uses PHP types as much as possible...
Theme uses facade design pattern for managing internal dependencies, so instead of placing everything in the setup.php
or filters.php
files as Sage
recommends, we should wrap custom features in specific boundaries placed in the app
directory. Let's assume that we need to create Posts
boundary that handles custom features for Post
type.
├── app/
│ ├── Posts/
│ ├── ├── Post.php
│ ├── ├── Posts.php
App/Posts
is boundary context for Posts
with Posts.php
as fasade for internal actions. This facade should be initialized in the App\App
like the here.
namespace App;
use App\Core\Singleton;
use App\Posts\Posts;
class App extends Singleton
{
private Posts $posts;
protected function __construct()
{
$this->posts = fireclass(Posts::class); # <- Context Initialization
}
public function posts(): Posts
{
return $this->posts;
}
}
This facade might be used everywhere you need using firestarter
function. Example: firestarter()->posts()->doSth()
.
Coditive theme uses a custom way for firing the WordPress hooks in the controllers. You can use @action
, @filter
and @shortcode
in the comment block for initializing hooks in specific class.
class Example {
/**
* @action template_redirect
*/
public function sendMail(): void
{
wp_mail('[email protected]', 'Test Message', 'Test Content');
}
/**
* @filter the_title
*/
public function setTitle(string $title): string
{
return $title;
}
/**
* @shortcode title
*/
public function shortcode(): string
{
return get_the_title();
}
}
But to make it work, there is a need to initialize instance using fireclass
function: fireclass(Example::class)
. Of course you can also put all the hoods in default way (constructor).
All the app modules should be initialized as App
class attributes placed in app.js
file.
Routes module can be used for firing custom functions only on specific pages.
Create route controller in @scripts/routes
directory.
class Home {
init() {
}
finalize() {
}
};
Initialize route controller in @scripts/modules/Router
constructor.
this.routes = {
home: new Home(),
};
Router will take all <body>
classes and convert them to camelCase
that become routes keys that will be used for firing specific events. So for example if you want to fire specific functions pages that have template-home
class, create a new controller and assign it to templateHome
in the router. The system will automatically fire init
or finalize
functions.
@scripts/utils
directory can be used for creating simple functions that may be used across the application. Please try to categorize them by meaing (for example, place array utils in @scripts/utils/array.js
file).
Blocks can be used for building website content sections. The main advantage over Sage
components is that assets are loaded on demand. So when specific block is not used on the page, its assets are not loaded at all. Sage
components loads all the assets in the main script.js
and style.js
files, so assets are loaded even when not needed.
├── app/
│ ├── View/
│ ├── ├── Blocks/
│ ├── ├── ├── Testimonial.php
├── resources/
│ ├── blocks/
│ ├── ├── testomonial/
│ ├── ├── ├── scripts.js
│ ├── ├── ├── styles.scss
│ ├── ├── ├── template.blade.php
New block can be created using the following command. That's all. All the block controllers will be initialized automatically.
wp firestarter block create --name=Testimonial
{!! firestarter()->block('testimonial')->render(); !!}
It is good to treat block controler as main source of data structure. So when the block needs to use $title
in the template, this should be reflected in block data structure. Thank's to this, enyone can see what variables are available in the template and what are their default types and values.
In the example below, we need to utilize $title
data in the template. So we set title in the structure with default value set as string, and then set the final value from some function.
class estimonial extends Block
{
public function __construct()
{
$this->setId('testimonial');
$this->setName('Testimonial');
$this->setStructure([
'title' => '',
]);
}
public function parse(array $data): array
{
$data = array_replace_recursive($data, $this->getStructure());
$data = apply_filters('firestarter_block_testimonial_data', $data);
$data['title'] = get_the_title_from_somewhere();
return $data;
}
}
Firestarter implements settings page...
Firestarter contains two directories for assets:
resources/images
- directory for images that can be accessed in CSS files (for exampleurl('../../images/filename.jpg')
) and via the@asset
directive (for example@assets('images/filename.jpg')
)resources/images/svg
- directory for images that can be accessed via@svg
directive to get the full content of file, for example@svg('images.svg.filename.svg')
Theme by default uses Local JSON feature and stores fields sonfiguration in /resources/fields
directory. You can disable this feature with the following wp-config.php
entry.
define('FIRESTARTER_INTEGRATIONS_ACF_LOCAL_JSON', false);
Firestarter adds support for ACF Blocks. So you can use previously described blocks architecture with ACF without any additional work.
Firestarter implements support for ACF Options.
firestarter()->settings()->get('site_logo')
Intended for apache servers.
If you use the ACF Pro plugin you can enable the WebP functionality in the dashboard, just go to the "Firestarter -> Media Settings".
To make it works you need to update your .htaccess
files with the following rules:
# CACHING | WebP Support | https://do.co/3aIKIb8
<IfModule mod_rewrite.c>
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png)$
RewriteCond %{DOCUMENT_ROOT}%1%2.webp -f
RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1%2\.webp [L,T=image/webp]
RewriteCond %{HTTP_ACCEPT} image/webp
RewriteCond %{REQUEST_URI} (?i)(.*)(\.jpe?g|\.png)$
RewriteCond %{DOCUMENT_ROOT}%1.webp -f
RewriteRule (?i)(.*)(\.jpe?g|\.png)$ %1\.webp [L,T=image/webp]
</IfModule>
If you don't use the ACF Pro plugin and you would like to enable this functionality then you can go to the app -> Media -> WEBP.php
file and set $this->convertImages
to true
.
You can check if it works correctly by checking, for example, the network tab in the Chrome developer tools (see image type column or response headers content-type).