Skip to content
Home Theme Gallery

PHP

Home-UI is server-rendered HTML plus two static files, so it fits Laravel or plain PHP with no client build: a layout loads the pair, the template writes the elements, and the request handler reads their values.

A Laravel Blade layout:

<!doctype html>
<html lang="en" class="{{ $theme ?? 'light' }}">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://home-ui.harriverse.com/dist/latest/home-ui.css" />
<script type="module" src="https://home-ui.harriverse.com/dist/latest/home-ui.js"></script>
</head>
<body class="hui-surface">
@yield('content')
</body>
</html>

Plain PHP is the same idea with <?= $theme ?>. class="light" or class="dark" is read server-side so there is no flash of the wrong theme; hui-surface opts the page into the tokens (see Dark mode).

Those URLs load the current build from this site. For something you ship, download the files and serve them yourself - see Getting the files.

A component is configured entirely by attributes, so Blade or PHP writes them like any other tag:

<hui-field>
<span data-label>Project name</span>
<hui-input data-control name="project"
value="{{ old('project', $project->name) }}"
@error('project') aria-invalid="true" @enderror></hui-input>
@error('project')<span data-error>{{ $message }}</span>@enderror
</hui-field>

old('project', ...) re-fills the field after a failed POST; the @error directive marks it invalid and supplies the message that hui-field wires to the control.

Every form-associated control submits under its name, so the handler reads it like any native field:

// Laravel
$project = $request->input('project');
$volume = $request->input('volume'); // from hui-slider, a string
// Plain PHP
$project = $_POST['project'];
$volume = $_POST['volume'];

Business validation is the server’s. On a failed POST, re-render the form with the submitted values and an error per field; the template above marks the control aria-invalid and wires the message to it. The client does not reconstruct that.

<form method="post">
@csrf
<!-- hui-field, hui-input and the rest -->
<hui-button type="submit">Save</hui-button>
</form>

hui-button type="submit" drives the ancestor form, so it can replace <button type="submit"> wherever you want the component’s styling.

To update part of the page, render a partial and swap it in. Any technique works - fetch, HTMX, or Livewire’s own diffing; the element is created from the new markup and re-associates with its form. Keep endpoints, tokens and record ids on the server: there is no attribute for them, deliberately. The full model is in server-side mechanics.