Form action not working

I am following this guide on user registration: User sign-up | Kirby CMS

The controller is working (redirect if logged in), but the form doesn’t do anything.

I have some modifications: Site is translatable (content/register/register.en.txt) and there is a honeypot field.

If I dump() before get('register') in the controller, I get an output on page load. But nothing inside the if statement (on page load or form submission).

Latest version of Kirby, PHP 8.1.20, Apache. I have tried to remove all plugins, place the form directly into the template (without snippet) and an action attribute without the language path /en/.



return [
    'debug' => true,
    'smartypants' => true,
    'languages' => true,
    'date.handler' => 'intl',
    'languages.detect' => true,
    'email' => [
        'transport' => [
            'type' => 'smtp',
            'host' => '...',
            'port' => 465,
            'security' => true,
            'auth' => true,
            'username' => '...',
            'password' => '...',
    'auth' => [
        'methods' => ['password', 'code'],
    'site' => require_once 'site.php', // Just a globally used email address (for now).


<?php snippet('header') ?>

<?php snippet('forms/register') ?>

<?php snippet('footer') ?>


<?php if (count($errors) > 0) : ?>
<ul class="alert">
    <?php foreach ($errors as $message) : ?>
        <li><?= kirbytext($message) ?></li>
    <?php endforeach ?>
<?php endif ?>

<form action="<?= $page->url() ?>" method="POST">
        <label for="name">Name</label>
        <input type="name" name="name" id="name" value="<?= isset($data['name']) ? esc($data['name'] ?? '', 'attr') : null ?>" />

        <label for="email">E-Mail <abbr title="required">*</abbr></label>
        <input type="email" id="email" name="email" value="<?= esc($data['email'] ?? '', 'attr') ?>" required />

    <input type="hidden" name="csrf" value="<?= csrf() ?>">
    <input type="submit" name="register" value="Register" />



use Kirby\Exception\PermissionException;

return function($kirby) {
    if ($kirby->user()) {

    $errors = [];

    if (get('register') && $kirby->request()->is('POST')) {
        if (csrf(get('csrf'))) {
            if (!empty(get('name'))) {
            $data = [
                'email' => get('email'),
            $rules = [
                'email' => ['required', 'email'],
            $messages = [
                'email' => 'Please enter a valid <a href="#email">email address</a>',
            if ($invalid = invalid($data, $rules, $messages)) {
                $errors = $invalid;
            } else {
                try {
                    $user = $kirby->users()->create([
                        'email' => $data['email'],
                        'role' => 'client',
                        'language' => 'en',
                    if (isset($user)) {
                        try {
                            $status = $kirby->auth()->createChallenge($user->email(), false, 'login');
                        } catch (PermissionException $e) {
                            $errors[] = $e->getMessage();
                } catch (Exception $e) {
                    $errors[] = $e->getMessage();
        } else {
            $errors[] = 'Invalid CSRF token.';

    return [
        'errors' => $errors,
        'data'  => $data ?? false,

Weird. I installed Ray and the request after submitting the form is a GET request with nothing in the request array (get() returns an empty array).

I know that form handling is working, this is not the first form I test.

I tested your code in a fresh 3.9.5 Starterkit both with single and multiple languages, and it works as expected; the only issue is the undefined variable $page when

this condition is true, because you didn’t page $page as argument in the controller’s function.

Uh, I forgot that I forced trailing slashes according to this guide: Quicktip: To slash or not to slash | Kirby CMS

Found this forum post about the issue, but there is no final solution: Custom URL function for trailing slashes

Any clean way to output page URLs with a trailing slash by default?

The easiest solution would be not to use trailing slashes in the first place. But I don’t want to start an argument here.

The other two options are in the thread you linked to: Either you modify the url component or you use a page model. But currently, we don’t have a default model yet (will be in Kirby 4), so better go for the component.