PHPackages                             clarkwinkelmann/flarum-mithril2html - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Templating &amp; Views](/categories/templating)
4. /
5. clarkwinkelmann/flarum-mithril2html

ActiveLibrary[Templating &amp; Views](/categories/templating)

clarkwinkelmann/flarum-mithril2html
===================================

Renders Mithril components to HTML for use in blade templates

1.3.0(3y ago)399[1 issues](https://github.com/clarkwinkelmann/flarum-mithril2html/issues)MITPHPPHP ^7.4|^8.0

Since Aug 24Pushed 3y ago1 watchersCompare

[ Source](https://github.com/clarkwinkelmann/flarum-mithril2html)[ Packagist](https://packagist.org/packages/clarkwinkelmann/flarum-mithril2html)[ RSS](/packages/clarkwinkelmann-flarum-mithril2html/feed)WikiDiscussions main Synced yesterday

READMEChangelog (4)Dependencies (5)Versions (5)Used By (0)

Flarum Mithril2Html
===================

[](#flarum-mithril2html)

Uses Chrome Puppeteer via [Spatie Browsershot](https://github.com/spatie/browsershot) to render Mithril components as static HTML.

Follow Browsershot instructions to setup Node and Headless Chrome.

This is intended for use with emails or other offline content generation.

It's probably not a good idea to use this outside of a queue because of the delays it introduces.

Usage
-----

[](#usage)

In your extension's `extend.php`, call the setup extender before registering any asset:

The extender can be called by multiple extensions without issues. It won't do anything once already registered.

```
return [
    new \ClarkWinkelmann\Mithril2Html\Extend\Setup(),

    // Your other extenders
];
```

Create a new page just like you would a normal Flarum page:

```
import Page from 'flarum/common/components/Page';

class HelloWorld extends Page {
    view() {
        return Hello World;
    }
}

app.initializers.add('demo', function () {
    app.routes.helloWorld = {
        path: '/hello-world',
        component: HelloWorld,
    };
});
```

To save up space in the `forum` bundle or to prevent conflicts, you can add your page only to the `mithril2html` frontend. You will need to update your webpack config to add an additional entry file, see this package's `webpack.config.js` for an example.

If you created a separate bundle (not `forum`), register it using Flarum's `Frontend` extender:

```
    (new Frontend('mithril2html'))
        ->js(__DIR__ . '/js/dist/mithril2html.js'),
```

If you already have a forum bundle with exports, Flarum will unfortunately override all `forum` exports with `mithril2html` exports (even if you have none). To work around this, a different extender is available just for javascript:

```
    (new \ClarkWinkelmann\Mithril2Html\Extend\FrontendNoConflict('mithril2html'))
        ->js(__DIR__ . '/js/dist/mithril2html.js'),
```

You can then use the `Renderer` class to render the component:

```
$component = new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world');
echo resolve(ClarkWinkelmann\Mithril2Html\Renderer::class)->render($component);
// Hello World
```

Alternatively, you can use the blade directive directly:

```
@mithril2html(new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world'))
```

You can configure additional options using a component class. The class must implement `ClarkWinkelmann\Mithril2Html\ComponentInterface`. `AnonymousComponent` is a simple class that allows customizing all parameters without creating additional classes.

The parameters customizable through a component class are:

- `route`: The Mithril route name without leading slash.
- `preload`: An API route to preload through the API Client. With leading slash.
- `actor`: An actor to use for the request. Defaults to guest.
- `selector`: A CSS selector targeting the HTML to return. That element's innerHTML will be returned. If the selector can't be found, an exception will be thrown.

Using a custom component class helps keep things clean when preloading is necessary:

```
class InvoiceComponent implements ComponentInterface {
    protected $invoice;

    public function __construct(Invoice $invoice)
    {
        $this->invoice = $invoice;
    }

    public function route(): string
    {
        return 'invoice';
    }

    public function preload(): ?string
    {
        return '/invoices/' . $this->invoice->id;
    }

    public function actor(): ?User
    {
        return $this->invoice->user;
    }

    public function selector(): ?string
    {
        return '#content';
    }
}
```

```
Below is a summary of your invoice:

@mithril2html(new InvoiceComponent($invoice))

```

PDF and Screenshot
------------------

[](#pdf-and-screenshot)

While it was not the primary use case for this extension, the `Renderer` class also exposes a `browsershot` method that gives access to a pre-configured but unused Browsershot instance.

When using that method, the `selector` property is ignored and the entire page/viewport is used. Browsershot methods must be used to configure the output.

Example:

```
$component = new ClarkWinkelmann\Mithril2Html\AnonymousComponent('hello-world');
echo resolve(ClarkWinkelmann\Mithril2Html\Renderer::class)->browsershot($component)->landscape()->pdf();
```

The page CSS is not loaded when calling `Renderer::render` but is loaded by default when calling `Renderer::browsershot`. It can be disabled by passing `false` as the second argument like `$renderer->browsershot($component, false)`.

Known issues
------------

[](#known-issues)

At the moment, passing an actor will authenticate the base request and preloaded `apiDocument`, but not any additional API request the component will make after page load.

If you render a page with user-generated content and an XSS is possible, the attacker might be able to read any API GET endpoint as administrator by first stealing the mithril2html internal token and then using that token to preload arbitrary GET endpoints.

Tests
-----

[](#tests)

The integration tests are a bit special because they require a working webserver that can be accessed by Chrome.

Run `composer test:server` before running the tests to start the PHP development server on port `8080`. The server is configured with a router script that takes care of routing back to the integration tmp folder.

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance13

Infrequent updates — may be unmaintained

Popularity13

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity59

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~164 days

Total

4

Last Release

1226d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/0538135c1debcef5602dce7ece027909cc832b7a6284ab9189a19aa8de98d60d?d=identicon)[clarkwinkelmann](/maintainers/clarkwinkelmann)

---

Top Contributors

[![clarkwinkelmann](https://avatars.githubusercontent.com/u/5264300?v=4)](https://github.com/clarkwinkelmann "clarkwinkelmann (9 commits)")

---

Tags

htmlSSRflarummithril

### Embed Badge

![Health badge](/badges/clarkwinkelmann-flarum-mithril2html/health.svg)

```
[![Health](https://phpackages.com/badges/clarkwinkelmann-flarum-mithril2html/health.svg)](https://phpackages.com/packages/clarkwinkelmann-flarum-mithril2html)
```

###  Alternatives

[craftcms/cms

Craft CMS

3.6k3.6M2.6k](/packages/craftcms-cms)[phpoffice/phpword

PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)

7.5k34.7M183](/packages/phpoffice-phpword)[latte/latte

☕ Latte: the intuitive and fast template engine for those who want the most secure PHP sites. Introduces context-sensitive escaping.

1.3k15.7M680](/packages/latte-latte)[twig/string-extra

A Twig extension for Symfony String

21946.0M132](/packages/twig-string-extra)[exercise/htmlpurifier-bundle

HTMLPurifier integration for your Symfony project

27911.3M16](/packages/exercise-htmlpurifier-bundle)[twig/markdown-extra

A Twig extension for Markdown

12114.3M83](/packages/twig-markdown-extra)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
