# Flynt: a WordPress theme where every block is a component

> Flynt is a WordPress starter theme for component-based development, using Timber and Twig for templates and ACF Pro for content, with each component owning its layout, fields, PHP logic, script and styles. The load behaviour is per component, so a block can wait until it is visible or until the browser is idle, and the whole theme builds with Vite.

**flyntwp/flynt** — Component based WordPress starter theme, powered by ACF Pro and Timber, optimized for performance and a11y.

- Repository: https://github.com/flyntwp/flynt
- Website: https://flyntwp.com
- Stars: 810 · Forks: 90
- Language: PHP
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/flyntwp-flynt

## A theme for developers, not for page builders

Flynt is described as a lightning-fast WordPress starter theme for component-based development with ACF Pro, and the site describes it as a starter theme for developers. The repository description is blunter, calling it a component-based WordPress starter theme powered by ACF Pro and Timber, optimized for performance and accessibility.

That is a fairly specific position, and the technology choices explain it. Tim Timber structures the page templates and Twig renders them, so the template layer is not WordPress's own loop and its own template hierarchy. Advanced Custom Fields Pro holds the content, which means the fields are structured data rather than the free-form editor content that a conventional WordPress theme renders.

The result is that everything on a page is a component. Apart from the main document structure, which lives in the _document.twig template, everything else is a component, and the theme provides a Twig function, renderComponent(componentName, data), to put a component into a template.

The project is PHP, MIT licensed, on the master branch, with the site at flyntwp.com and the author given as Bleech. The last push was on 2026-09-22, and the releases are v2.1.0 in March 2024, v2.1.1 in May 2024 and v2.1.2 in April 2026, so the 2.1 line is still being maintained at a slow pace.

## Four dependencies, and one of them is paid

The dependency list is short and worth reading in order, because one entry has a commercial consequence.

WordPress 6.1 or newer, Node exactly version 20, Composer 2.4 or newer, and Advanced Custom Fields Pro 6.0 or newer.

ACF Pro is the paid edition of a plugin that also has a free version, so this is not a theme you can drop into a site without a licence decision. The rest are ordinary. The Node pin is exact rather than a range, which tells you the toolchain is tested against one version, and the package.json reflects that with a check-node-version script that runs before the development and build scripts.

The install is four steps. Clone the repository into your project's wp-content/themes directory. Change the domain variable in the Vite config so the development server knows which WordPress instance to talk to:

```js
const wordpressHost = 'http://your-project.test'
```

Then, in the theme folder, install both dependency sets and build:

```bash
# wp-content/themes/flynt
composer install
npm install
npm run build
```

Finally, open the WordPress backend and activate the Flynt theme. The last two steps of that sequence, changing the host variable and running a build, are what stand between a clone and a working site, and the README is clear about both.

## The folder layout and the order things load in

The theme's directories map to how WordPress loads a theme, and the README walks through them one at a time.

The lib folder holds helper functions and basic setup logic, with the note that you will most likely not need to modify anything inside it, and all of it is autoloaded through PSR-4. The inc folder is a more organised version of WordPress's functions.php and contains all the custom theme logic, and its files are required automatically. It has three subfolders that the README recommends you use to keep the theme well structured: customPostTypes for registering custom post types, customTaxonomies for registering custom taxonomies, and fieldGroups for registering ACF field groups.

After the files from lib and inc have loaded, all the components from the Components folder are loaded.

The assets folder holds all the global JavaScript, SCSS, images and font files for the theme, and those files are watched for changes and compiled into the dist folder. The main.scss file compiles to dist/assets/main.css and is enqueued in the front end, while admin.scss compiles to dist/assets/admin.css and is enqueued in the administrator back end, so styles added there take effect only in the back end.

The split between those two stylesheets is a small thing that saves a common confusion, which is why a style that you have written appears not to work until you realise you put it in the wrong file.

## A component is a directory with everything in it

The definition is short and strict. A component is a self-contained building block, and each component contains its own layout, its ACF fields, PHP logic, scripts and styles.

The directory makes that concrete:

```
  ExampleComponent/
  ├── _style.scss
  ├── functions.php
  ├── index.twig
  ├── README.md
  ├── screenshot.png
  ├── script.js
```

Six files, and the names say what each is for. The Twig file is the markup, the SCSS is the styling, the JavaScript is the behaviour, the README is the documentation, and the screenshot is the preview the component shows in the WordPress admin.

The PHP file has a specific moment of execution. The functions.php file for every component in the Components folder is executed during the WordPress action after_setup_theme, and that action is run from the theme's own functions.php.

So a component registers itself with the theme at the moment the theme sets itself up, which is why a component can ship its own field group and its own logic without anyone editing a central file. The README points at the components section for how to render a component into a template, and the rendering side is the renderComponent function, which takes a component name and the data for it.

## Loading strategies, and why they are per component

Most components are based on an autonomous custom element called flynt-component, which is a web component, and the README explains the reason for the model as providing a standard component model for encapsulation and interoperability in HTML elements.

The name attribute defines which component it is, and it should match the component's folder name, to make sure that its JavaScript is loaded as specified:

```twig
<flynt-component name="BlockWysiwyg" …></flynt-component>
```

The interesting part is that each component can choose when it initialises. There are four strategies. load:on="idle" initialises after the full page load, when the browser enters an idle state, for elements that do not need to be interactive immediately. load:on="visible" initialises after the element becomes visible in the viewport, for elements that go below the fold or that should load when the user sees them. load:on="load" is the default and initialises immediately when the page loads, for elements that need to be interactive as soon as possible. And load:on:media="(min-width: 1024px)" initialises when the specified media query matches, for elements that may only be visible on certain screen sizes.

```twig
<flynt-component name="BlockWysiwyg" load:on="visible"></flynt-component>
```

The strategies can be combined, for example a navigation that loads on idle but only above a certain width, and with nested components the loading strategy is waiting for parents, so a child does not initialise before the component around it has.

This is where the performance claim in the project description comes from. On a page with many blocks, the default of loading everything immediately is the wrong choice, and making the strategy a per-component attribute is what turns the performance claim into something a developer can act on.

## Vite, npm-run-all and three linters

The build tooling is visible in the package scripts, and it is a more elaborate setup than a typical WordPress theme.

The central utility is npm-run-all. The start script runs the dev script, which checks the Node version, cleans the dist folder with rimraf and recreates it, and then serves with vite dev. The build script checks the version, runs the linters and then the production build, and the production build sets NODE_ENV and runs vite build. There is a separate watch script that runs the build in watch mode, and a lint script that runs three linters in parallel: standard for the scripts, stylelint over the SCSS files, and phpcs from the vendor directory for the PHP.

The fix script mirrors the lint script with the fixing variants, standard with the fix flag, stylelint with the fix flag, and phpcbf for PHP. The clean step is deliberately separate, since the development script always cleans first, which is how the dist folder ends up with no stale assets after a rename.

The version handling is the part worth copying. There is a checkVersion step that runs before anything else, a release script that uses standard-version, and a set of replaceVersion scripts that write the version into the theme. The style.css file gets its version line rewritten with a regular expression, and the JavaScript and PHP files have a %%NEXT_VERSION%% placeholder that is replaced with the package version, with the dist, node_modules and vendor directories excluded.

So the version in the theme header, the version constant in the scripts and the version in the package manifest cannot drift, and the release script is the only thing you have to run.

## The repository and how it is checked

The top-level listing is a WordPress theme with a modern front-end toolchain layered on, and the entries that are not the standard WordPress files are the interesting ones.

Besides the usual index.php, page.php, single.php, search.php, 404.php, style.css, functions.php and screenshot.php, there is a theme.json, which is the block editor theme configuration, a basestyle.php, and the flynt-specific directories Components/, inc/, lib/, assets/ and templates/.

The build tooling has its own entries: vite.config.js and a local vite-plugin-flynt.js, which is a Vite plugin written for this project, a package.json and package-lock.json for the JavaScript, a composer.json and composer.lock for PHP, and phpcs.xml.dist for the PHP coding standard. There is an .editorconfig, an .eslintignore, a .scrutinizr.yml for the hosted code quality service, a .travis.yml for continuous integration, and a .github/ directory for the current workflows.

The badges in the README show the mix, with a Travis build status, a Scrutinizer code quality badge and a standard-readme compliance badge, alongside the GitHub Actions build workflow that the project uses now.

On maintenance, the picture is a stable 2.1 line with a long gap, v2.1.1 in May 2024 and v2.1.2 in April 2026, and a last push on 2026-09-22. The theme is not abandoned, but the release cadence is slow, so a project that plans to stay on Flynt for years should expect to track the 2.1 line rather than to expect frequent upgrades.

## Conclusion

Adopt Flynt if you build WordPress sites with a design system and want the content model, the templates and the front end to live in one place, because the component model and the per-component loading strategies are what it is for, and the bundler is Vite rather than a WordPress asset pipeline. Do not adopt it without checking two things: it needs Advanced Custom Fields Pro, which is a paid plugin, and it pins Node to exactly version 20, so your build environment has to match. Before you start, set the wordpressHost variable in the Vite config, because the development server talks to your local WordPress instance through it, and read the loading strategy section, since the default of loading immediately is rarely what you want for a page of thirty blocks.

## FAQ

### What is the Flynt WordPress theme?

A component-based WordPress starter theme for developers, using Timber to structure page templates, Twig to render them and Advanced Custom Fields Pro for content. Apart from the main document structure, everything on a page is a component, and a Twig function, renderComponent, renders a component into a template.

### What does a Flynt component contain?

Its own layout, ACF fields, PHP logic, scripts and styles, in a directory with a Twig file, a SCSS file, a JavaScript file, a functions.php file, a README and a screenshot. The functions.php of every component runs during the WordPress after_setup_theme action, which is how a component registers itself without anyone editing a central file.

### How does Flynt decide when a component loads?

Each component chooses a strategy through the load:on attribute on the flynt-component custom element. load:on="idle" waits for the browser to be idle, load:on="visible" waits for the element to enter the viewport, load:on="load" is the default and initialises immediately, and a media query variant initialises when the query matches. With nested components, the child waits for its parents.

### What does Flynt need before you can install it?

WordPress 6.1 or newer, Node exactly version 20, Composer 2.4 or newer, and Advanced Custom Fields Pro 6.0 or newer, which is a paid plugin. You then clone the repository into wp-content/themes, set the wordpressHost variable in the Vite config, run composer install, npm install and npm run build, and activate the theme in the WordPress backend.

## Sources

- [flyntwp/flynt on GitHub](https://github.com/flyntwp/flynt)
- [License: MIT](https://github.com/flyntwp/flynt/blob/master/LICENSE)
- [Project website](https://flyntwp.com)
- [README](https://github.com/flyntwp/flynt/blob/master/README.md)
- [Releases](https://github.com/flyntwp/flynt/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/flyntwp-flynt
