https://github.com/atomicptr/berry
Berry is a zero-dependency, type-safe toolkit for building HTML structures using pure PHP.
https://github.com/atomicptr/berry
berry berry-html php template-engine
Last synced: 19 days ago
JSON representation
Berry is a zero-dependency, type-safe toolkit for building HTML structures using pure PHP.
- Host: GitHub
- URL: https://github.com/atomicptr/berry
- Owner: atomicptr
- License: mit
- Created: 2025-12-27T11:32:25.000Z (about 1 month ago)
- Default Branch: master
- Last Pushed: 2026-01-11T17:31:30.000Z (21 days ago)
- Last Synced: 2026-01-11T20:24:46.862Z (21 days ago)
- Topics: berry, berry-html, php, template-engine
- Language: PHP
- Homepage:
- Size: 162 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 5
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Berry
Berry is a zero-dependency, type-safe toolkit for building HTML structures using pure PHP.
## Features
- **Pure PHP eDSL**: Define HTML structures using a fluent API, no new template syntax to learn just pure PHP
- **Type Safety**: Designed with PHPStan in mind, benefit from static analysis to catch bugs before they hit production
- **Built-in inspector**: Berry includes a visual debugging tool that renders a tree of your components and stack traces directly in the browser
- **Extensible**: Extend Berry with custom attributes using the integrated extension method functionality
## Usage
Install via composer
```bash
$ composer req berry/html
```
```php
attr('hx-target', 'this')
->child(
button()
->id('counter-button')
->attr('hx-post', "$current?counter=$nextValue")
->attr('hx-swap', 'outerHTML')
->text("+ $value")
)
->child(hr())
->dump(true);
}
// our website layout to wrap around the content
// includes picocss and htmx
function layout(Element $content): Element
{
return html()
->child(head()
->child(title()->text('Hello, Berry!'))
->child(link()
->rel(Rel::Stylesheet)
->href('https://cdn.jsdelivr.net/npm/@picocss/pico@2/css/pico.min.css')))
->child(body()
->child(header())
->child(div()
->class('container')
->child($content))
->child(script()->src('https://cdnjs.cloudflare.com/ajax/libs/htmx/2.0.7/htmx.min.js')));
}
// if we get a POST render only the counter button and stop
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$value = $_GET['counter'] ?? '1';
assert(is_string($value));
$value = intval($value);
echo counterButton($value)->toString();
die();
}
// and lastly render the normal page template
echo layout(
main()
->class('container')
->child(h1()->text('Hello, Berry!'))
->child(p()->text('This is an example page rendering HTML using Berry'))
->child(counterButton(1))
)->toString();
```

## Ecosystem
Some other related packages:
- [berry/symfony](https://github.com/atomicptr/berry-symfony) - Symfony integration
- [berry/htmx](https://github.com/atomicptr/berry-symfony) - HTMX integration
## License
MIT