Skip to content

Latest commit

 

History

40 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Picowind

Note

The default Tailwind CSS WordPress theme for LiveCanvas

A modern WordPress theme for LiveCanvas with multi-engine template support (Twig, Blade, Latte, Handlebars) built on Timber and Tailwind CSS.

Requirements

  • PHP >= 8.2
  • Node.js >= 24.9.0
  • Composer
  • pnpm

Getting Started

1. Clone Repository

Clone the repository to your wp-content/themes directory:

git clone https://github.com/livecanvas-team/picowind picowind
cd picowind

2. Install Dependencies

# Install PHP dependencies
composer install

# Install Node.js dependencies
pnpm install

3. Development

# Start Vite dev server with HMR
pnpm run dev

Template Engines

Picowind supports four template engines:

Usage

PHP functions

You can use the PHP functions to render templates and strings with different engines.

  • Picowind\render($paths, $context, $engine, $print, $silent) - Render template file
  • Picowind\render_string($string, $context, $engine, $print) - Render template string

When rendering templates, Picowind will automatically detect the engine based on the file extension:

  • .twig - Twig
  • .blade.php, .php, or no extension - Blade
  • .latte - Latte
  • .hbs, .handlebars - Handlebars

Render capabilities

Picowind\render() supports mixed-engine fallback arrays out of the box. Leave $engine as null (default), pass multiple template candidates (even from different engines), and Picowind will try them in order until one renders successfully.

For extension-based fallback candidates, the default engine order is:

  1. Twig (.twig)
  2. Blade (.blade.php)
  3. Latte (.latte)
  4. Handlebars (.hbs, .handlebars)

This is the order generated by Picowind\template_fallbacks() and used by the default theme template loaders.

Picowind\render([
    'components/hero.twig',
    'components/hero.blade.php',
    'components/hero.latte',
    'components/hero.hbs',
], ['title' => 'Hello']);

You can also use the .? extension placeholder with an explicit engine to swap engines without changing template paths:

Picowind\render('components/hero.?', ['title' => 'Hello'], 'twig');
Picowind\render('components/hero.?', ['title' => 'Hello'], 'blade');
Picowind\render('components/hero.?', ['title' => 'Hello'], 'latte');
Picowind\render('components/hero.?', ['title' => 'Hello'], 'handlebars');
Twig
Picowind\render('components/card.twig', ['title' => 'Hello']);
Picowind\render_string('<div>{{ title }}</div>', ['title' => 'Hello'], 'twig');
Blade
Picowind\render('components/button', ['text' => 'Click me']);
Picowind\render_string('<div>{{ $text }}</div>', ['text' => 'Hello'], 'blade');
Latte
Picowind\render('components/header.latte', ['title' => 'Welcome']);
Picowind\render_string('<div>{$title}</div>', ['title' => 'Hello'], 'latte');
Handlebars
Picowind\render('components/card.hbs', ['title' => 'Welcome']);
Picowind\render_string('<div>{{title}}</div>', ['title' => 'Hello'], 'handlebars');

Timber-compatible function helpers (Blade + Latte + Handlebars)

Twig includes Timber helpers like get_post, get_posts, function, fn, and translation functions.

Picowind now exposes the same Timber callable map to Blade, Latte, and Handlebars:

  • Latte
    • Direct function names where Latte allows it: {get_post(123)}
    • function/fn are available as call: {call('wp_head')}
    • Universal dispatcher: {timber('get_post', 123)}
    • _-prefixed helpers are supported directly (for example {__('Text', 'picowind')}), and Picowind also supports shorthand like {_n('%s star', '%s stars', 2, 'picowind')}.
  • Blade
    • Callable variables for Timber functions: {{ $get_post(123) }}
    • function/fn call style: {{ $function('wp_head') }} and {{ $fn('wp_head') }}
    • Universal object access: {{ $timber->get_post(123) }}
  • Handlebars
    • Direct helper names where Handlebars allows it: {{get_post 123}}
    • Universal dispatcher: {{timber "get_post" 123}}
    • Raw HTML helper output should use triple braces when appropriate, for example {{{function "wp_head"}}}.

Mixing engines inside templates

Picowind lets templates call other engines directly, so you can compose Twig, Blade, Latte, and Handlebars in the same page.

  • Twig -> Blade/Latte/Handlebars
{% blade 'components/button.blade.php' with {'text': 'Click me'} %}
{% latte 'components/card.latte' with {'title': post.title} %}
{% handlebars 'components/card.hbs' with {'title': post.title} %}

{{ blade('components/button.blade.php', {'text': 'Click me'}) }}
{{ latte('components/card.latte', {'title': post.title}) }}
{{ handlebars('components/card.hbs', {'title': post.title}) }}
  • Blade -> Twig/Latte/Handlebars
@twig('components/card.twig', ['title' => $title])
@latte('components/card.latte', ['title' => $title])
@handlebars('components/card.hbs', ['title' => $title])
  • Latte -> Twig/Blade/Handlebars
{twig 'components/card.twig', ['title' => $title]}
{blade 'components/button.blade.php', ['text' => $title]}
{handlebars 'components/card.hbs', ['title' => $title]}

{twig('components/card.twig', ['title' => $title])}
{blade('components/button.blade.php', ['text' => $title])}
{handlebars('components/card.hbs', ['title' => $title])}
  • Handlebars -> Twig/Blade/Latte/Handlebars
{{{twig "components/card.twig" title=title}}}
{{{blade "components/button.blade.php" text=title}}}
{{{latte "components/card.latte" title=title}}}
{{{handlebars "components/card.hbs" title=title}}}

Shortcodes

You can also use shortcodes to render templates and strings directly in WordPress content.

Twig
[twig template="components/card.twig"]
[twig]<div>{{ site.name }}</div>[/twig]
Blade
[blade template="components/button"]
[blade]<div>{{ $user->name }}</div>[/blade]
Latte
[latte template="components/header.latte"]
[latte]<div>{$post->title}</div>[/latte]

Theme Structure

picowind/
├── blocks/                # Block editor blocks
├── child-theme/           # Bundled child themes
├── public/                # Static assets
├── src/                   # Theme functionality (PHP) (source)
├── resources/             # Admin and frontend assets (source)
└── views/                 # Theme templates (Twig, Blade, Latte, Handlebars, etc.)

views/ Directory

Templates are loaded from multiple directories in order of priority:

  1. Child theme views/, blocks/, components/ directory (if applicable)
  2. Child theme root directory (if applicable)
  3. Parent theme views/, blocks/, components/ directory
  4. Parent theme root directory

Miscellaneous

Helper Functions

Picowind provides several PHP helper functions for common tasks:

  • Picowind\context() - Get global WordPress context
  • Picowind\omni_icon($name, $attributes) - Render SVG icons via Omni Icon plugin (supports Iconify, local uploads, and bundled icons)

Hooks and Services

Picowind uses PHP attributes for auto-discovery of services and hooks.

You can simply annotate your classes and methods with #[Service] and #[Hook] attributes to register them automatically.

For example:

// src/Path/To/MyFeature.php

use Picowind\Core\Discovery\Attributes\Service;
use Picowind\Core\Discovery\Attributes\Hook;

#[Service]
class MyFeature
{
    #[Hook('init', type: 'action')]
    public function my_powerful_feature(): void
    {
        // Your code here
    }
}

This will automatically registered and hooked into WordPress without manual intervention. It is equivalent to:

// src/Path/To/MyFeature.php

class MyFeature
{
    public function __construct()
    {
        add_action('init', [$this, 'my_powerful_feature']);
    }

    public function my_powerful_feature(): void
    {
        // Your code here
    }
}
// functions.php

require_once __DIR__ . '/src/Path/To/MyFeature.php';

$my_feature = new MyFeature();

About

A modern WordPress theme for LiveCanvas with multi-engine template support (Twig, Blade, Latte)

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages