PHV demo

Live demo

Hello, world!

This site is written in PHV, a language for the web that keeps the feel of PHP while the compiler guarantees type safety and safe output. Every page runs on the server as you load it, and shows its own source at the bottom.

Escaping

Type <script> anywhere: output is escaped for where it lands — text, attribute, URL or script — and the unsafe spots do not compile.

Message board

SQLite with sql"..." literals, automatic CSRF checks, sessions, flash messages and rate limiting.

Two-factor codes

TOTP secrets, a QR code for your authenticator app and replay-safe verification, all built in.

JSON API

Endpoints that return JSON, called from a script that gets its CSP nonce automatically.

Source of this page

Read from disk by lib/source.phv as the page is served.

public/index.phv
<?phv
import std.http.request;
import lib.source.sources;

$name = (request()->query("name") ?? "")->trim();
if ($name->isEmpty() || $name->len() > 40) {
    $name = "world";
}

$body = render("views/home.phv.html", name: $name);
echo render(
    "views/layout.phv.html",
    title: "Live demo",
    path: "/",
    body: $body,
    files: sources(["public/index.phv", "views/home.phv.html"]),
);
views/home.phv.html
<?phv params(string $name) ?>
<section class="hero">
  <p class="eyebrow">Live demo</p>
  <h1>Hello, <?= $name ?>!</h1>
  <p class="lead">This site is written in <a href="https://phv-lang.org">PHV</a>, a language for the web that keeps
  the feel of PHP while the compiler guarantees type safety and safe output. Every page runs on the server as you
  load it, and shows its own source at the bottom.</p>
  <form method="get" action="/" class="inline">
    <label for="name">Your name</label>
    <input id="name" name="name" value="<?= $name == "world" ? "" : $name ?>" maxlength="40" autocomplete="off"
      placeholder="Try &lt;b&gt;you&lt;/b&gt;">
    <button>Greet me</button>
  </form>
</section>

<div class="grid">
  <a class="card" href="/escape">
    <h2>Escaping</h2>
    <p>Type <code>&lt;script&gt;</code> anywhere: output is escaped for where it lands — text, attribute, URL or
    script — and the unsafe spots do not compile.</p>
  </a>
  <a class="card" href="/board">
    <h2>Message board</h2>
    <p>SQLite with <code>sql"..."</code> literals, automatic CSRF checks, sessions, flash messages and rate
    limiting.</p>
  </a>
  <a class="card" href="/totp">
    <h2>Two-factor codes</h2>
    <p>TOTP secrets, a QR code for your authenticator app and replay-safe verification, all built in.</p>
  </a>
  <a class="card" href="/api">
    <h2>JSON API</h2>
    <p>Endpoints that return JSON, called from a script that gets its CSP nonce automatically.</p>
  </a>
</div>