Cannot get form to submit data to controller (on multilang site)

Good evening,

I am new with Kirby and setting up a multilangual site by converting an HTML template to Kirby (on the most current Kirby 4 Alpha). During this, I am trying to bring my designed form to life but I cannot get it to work - to me it looks like the form data is never posted to the controller and hence nothing happens.

Now I have the following nice looking form, borrowing from Kirby docs:

      <?php if($success): ?>
        <div class="alert success">
            <p><?= $success ?></p>
        <?php else: ?>
        <?php if (isset($alert['error'])): ?>
            <div><?= $alert['error'] ?></div>
        <?php endif ?>

          <div id="formcontainer">
            <form id="formcontainerinner" method="post" action="<?= $page->url() ?>">
              <div class="honeypot">
                    <label for="website">Website <abbr title="required">*</abbr></label>
                    <input type="url" id="website" name="website" tabindex="-1">
              <div id="nameemail">
                <div id="name">
                  <div class="fcf-input-group">
                      <input type="text" placeholder="<?= $site->getInTouchName() ?>" id="inputname" name="Name" minlength="3" maxlength="25" required class="required" onkeyup="enableSubmit()">
              <div id="email">
                  <div  class="fcf-input-group">
                      <input type="email" placeholder="<?= $site->getInTouchEmail() ?>" id="inputemail" name="Email" minlength="5"  required class="required" onkeyup="enableSubmit()">

                <div id="message">
                    <div id="inputmessage">
                      <textarea id="fieldformessage"  placeholder="<?= $site->getInTouchMessage() ?>" name="Message" class="fcf-form-control required" rows="6" maxlength="3000" required onkeyup="enableSubmit()"></textarea>

              <div id="agreesection">

                <div id="switchtext">

                <label class="switch">
                  <input id="checkbox" type="checkbox" unchecked required  class="required" onclick="enableSubmit()">
                  <span class="slider round"></span>

                <p id="agreetext">
                    <?= $site->getInTouchConfirmToS() ?>


                <input onclick="validateEmail()" style="cursor: pointer;" id="submit" type="submit" value="Submit" class="button buttongradientsaturated buttonsend">


            <?php endif ?>

This file is stored under site/templates/home.php. Since English is defined as my default language, when I go to www, it reroutes to www and shows me this home page.

Now in the form though, the code of the rendered site shows

<form id="formcontainerinner" method="post" action="">

(I thought this was the mistake but it is not, hardcoding in … without the /en does not change anything)

My controller lies in


and is exactly the same as the one in the docs (Email contact form | Kirby CMS ( ) except that I renamed “text” to “message” to confirm with my HTML fields.

When I fill out the form and click the send button - the website loads again but nothing happens. No e-mail, no error (debug is on), nothing.

What am I doing wrong? My eyes are blind after too much coding :slight_smile:


Hi, and welcome to the forum :wave:

Do I understand correctly that you put the PHP code from the form into the text file? But then it wouldn’t render, so maybe that’s just not well expressed.

So the form lives in the home.php template, the textfile is home.txt and the controller is in /controller/home.php.

Could you please post the controller as well?

Hi Sonja! Danke Dir :slight_smile:

Sorry I mistyped: of course the PHP code and the form is in the TEMPLATE at site/templates/home.php.

Sure, the controller which is stored in site/controllers/home.php looks like this:


return function($kirby, $pages, $page) {

    $alert = null;

    if($kirby->request()->is('POST') && get('submit')) {

        // check the honeypot
        if(empty(get('website')) === false) {

        $data = [
            'name'  => get('name'),
            'email' => get('email'),
            'message'  => get('message')

        $rules = [
            'name'  => ['required', 'minLength' => 3],
            'email' => ['required', 'email'],
            'message'  => ['required', 'minLength' => 3, 'maxLength' => 3000],

        $messages = [
            'name'  => 'Please enter a valid name',
            'email' => 'Please enter a valid email address',
            'message'  => 'Please enter a message between 3 and 3000 characters'

        // some of the data is invalid
        if($invalid = invalid($data, $rules, $messages)) {
            $alert = $invalid;

            // the data is fine, let's send the email
        } else {
            try {
                    'template' => 'email',
                    'from'     => '',
                    'replyTo'  => $data['email'],
                    'to'       => '',
                    'subject'  => esc($data['name']) . ' sent you a message from your contact form',
                    'data'     => [
                        'message'   => esc($data['message']),
                        'sender' => esc($data['name'])

            } catch (Exception $error) {
                    $alert['error'] = 'The form could not be sent: <strong>' . $error->getMessage() . '</strong>';
                    $alert['error'] = 'The form could not be sent!';

            // no exception occurred, let's send a success message
            if (empty($alert) === true) {
                $success = 'Your message has been sent, thank you. We will get back to you soon!';
                $data = [];

    return [
        'alert'   => $alert,
        'data'    => $data ?? false,
        'success' => $success ?? false


Thanks, ok, will check

Ok, first problem, your submit button doesn’t have a name of submit, so the first if statement fails.

Secondly, your field names are uppercase, while you try to fetch lowercase field names in the controller, won’t work. Stick with lower case name attributes.

On a side note, your form elements don’t have labels, which is bad for accessibility. I’d recommend to always use labels, or at least aria attributes if you don’t. But placeholders are no good replacement for labels even for sighted users…

1 Like

Oh man, thanks a lot @texnixe ! So obvious but then not if you are staring at the same screen for hours.

It works now - or to be precise: I finally get an error message I expect:

The form could not be sent: The email template "email" cannot be found



Yes, that one needs to be present in /site/templates/emails, see recipe.

Taking a break does wonders, but using a debugger also helps…

Absolutely @texnixe . If I might ask you one last question. Previously I did not create the email template so that was expected. I did create it now and I still get the same error:

The form could not be sent: The email template "contactForm" cannot be found

This is my directory structure:


And this is my code:


I even copied and pastet the filenames to be sure.

What am I doing wrong now? :slight_smile: (I might have to setup that debugger you are talking about)


Hm, that should work, but just to be on the save side, try all lowercase both for the email template name and for the template value in `$kirby->email(). I can only repeat my advice to use only lowercase for all filenames.

Hi @texnixe

you are right (again) - all in lowercase works.

Is this a bug or a feature? :slight_smile:


It’s a feature. Kirby expects a lowercase filename, this is the template constructor:

public function __construct(
		string $name,
		string $type = 'html',
		string $defaultType = 'html'
	) {
		$this->name = strtolower($name); // <= template name is lowercased here!
		$this->type = $type;
		$this->defaultType = $defaultType;

Whether uppercase characters work or not, depends on your operating system/os settings. If it is case insensitive, then your camelCase names work, if they are case sensitive, they don’t (like on my Mac, your example works).

Therefore, just stick with lowercase filenames everywhere, and you are good to go.

1 Like