# Formulários HTML

> Envie qualquer formulário HTML para o Ikiform sem JavaScript: redirecionamentos, campos reservados, arrays e o honeypot.

Um formulário HTML simples é toda a integração. Sem script, sem iframe e sem embed: defina o `action` como o endpoint do seu formulário e mantenha seu próprio markup e CSS. Isso também funciona em criadores de sites que deixam você colar HTML personalizado; veja [Criadores de sites](https://ikiform.com/pt-br/docs/guides/site-builders.md).

## Um formulário básico

`contact.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <label>
    Name
    <input name="name" autocomplete="name" required />
  </label>
  <label>
    Email
    <input name="email" type="email" autocomplete="email" required />
  </label>
  <label>
    Message
    <textarea name="message" rows="5"></textarea>
  </label>
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Send</button>
</form>
```

- O `method` precisa ser `post`. O navegador envia `application/x-www-form-urlencoded`, ou `multipart/form-data` se você definir `enctype`. Os dois funcionam.
- Todo controle com um `name` vira um campo. Controles sem nome, e controles desativados, não são enviados pelo navegador.
- Os valores são armazenados como texto UTF-8, normalizados para NFC, com quebras de linha CRLF convertidas em LF e caracteres de controle removidos.
- Validações do navegador como `required` e `type="email"` ajudam as pessoas, mas não são uma verificação de segurança. Defina [campos](https://ikiform.com/pt-br/docs/fields.md) para o Ikiform aplicar regras no servidor.

## Depois do envio

Um envio bem-sucedido pelo navegador recebe um redirecionamento `303`. O Ikiform escolhe o destino nesta ordem:

1. A configuração **Redirect after submit** do formulário no painel. Qualquer URL `http:` ou `https:` funciona aqui, porque só membros do workspace podem defini-la.
2. Um campo `_redirect` (ou `_next`) no envio, se ele passar pelas regras abaixo.
3. Caso contrário, a página de agradecimento hospedada do Ikiform em `/f/<formId>/thanks`. Quando o formulário tem domínios permitidos e o envio veio de uma página `https:` em um deles, a página tem um link de volta para ela.

### Regras para _redirect

Um valor de `_redirect` vem do navegador do visitante, então o Ikiform só o segue quando é uma URL `https:` sem usuário, senha ou porta personalizada, em um dos domínios permitidos do formulário ou em um subdomínio de um deles. Formulários sem domínios permitidos ignoram `_redirect` por completo. Com os domínios permitidos definidos como `example.com`:

| _redirect | Seguido | Por quê |
| --- | --- | --- |
| `https://example.com/thanks` | Sim | Domínio permitido |
| `https://app.example.com/done` | Sim | Subdomínio de um domínio permitido |
| `http://example.com/thanks` | Não | Não é `https:` |
| `https://example.com:8443/thanks` | Não | Porta personalizada |
| `https://user@example.com/` | Não | Contém um usuário |
| `https://example.com.evil.dev/` | Não | Não é o domínio nem um subdomínio dele |

Um `_redirect` que não é seguido cai na página de agradecimento hospedada; ele nunca causa erro. Requisições JSON ignoram redirecionamentos e recebem `201` com o id do envio.

### Quando um envio é rejeitado

Se um envio é rejeitado, por exemplo porque falta um campo obrigatório, o navegador vê uma página de erro hospedada com o status HTTP do erro. Ela lista os problemas pelo rótulo do campo e tem um link de volta para o formulário. Veja [Erros](https://ikiform.com/pt-br/docs/errors.md) para todos os códigos.

## Nomes de campo e arrays

Nomes repetidos e nomes terminados em `[]` viram arrays. Use `[]` em grupos de checkbox e em `<select multiple>` para que uma única escolha ainda seja armazenada como array.

`fields.html`:

```html
<fieldset>
  <legend>Topics</legend>
  <label><input type="checkbox" name="topics[]" value="billing" /> Billing</label>
  <label><input type="checkbox" name="topics[]" value="api" /> API</label>
</fieldset>

<select name="plan">
  <option value="starter">Starter</option>
  <option value="team">Team</option>
</select>

<label><input type="checkbox" name="newsletter" /> Send me product news</label>
```

Marcar os dois tópicos e a caixa da newsletter armazena:

`Campos armazenados`:

```json
{
  "topics": ["billing", "api"],
  "plan": "team",
  "newsletter": "on"
}
```

- Nomes com colchetes, como `address[city]`, são mantidos literalmente; eles não viram objetos aninhados. Envie JSON se você quiser valores aninhados.
- Um checkbox desmarcado simplesmente não é enviado. Com um [campo](https://ikiform.com/pt-br/docs/fields.md#types) `checkbox` definido, uma caixa ausente é armazenada como `false` e uma marcada como `true`.
- Um envio pode ter até 100 campos, nomes com até 128 caracteres e valores com até 16 KB. Veja [Limites](https://ikiform.com/pt-br/docs/limits.md).

> Upload de arquivos ainda não existe. Um input de arquivo vazio é ignorado; um envio que contém um arquivo de verdade é recusado com `422 files_not_supported`.

## Campos reservados

Nomes que começam com `_` são instruções para o Ikiform. Eles nunca são armazenados como respostas.

| Campo | Efeito |
| --- | --- |
| `_gotcha` | Honeypot. Deixe-o vazio e oculto; um valor preenchido soma 5 à pontuação de spam, o que basta para armazenar o envio como spam. O nome pode ser alterado por formulário. |
| `_redirect`, `_next` | Para onde mandar o navegador depois de um envio bem-sucedido. Veja [Regras para _redirect](#redirect-rules). |
| `_subject` | Assunto dos e-mails de notificação. Espaços em branco são condensados e ele é cortado em 200 caracteres. |
| `_replyto` | Endereço de reply-to dos e-mails de notificação. É ignorado, a menos que seja um único endereço de e-mail válido. |
| `_idempotency` | Chave de idempotência, igual ao header `Idempotency-Key`. Veja [Idempotência](https://ikiform.com/pt-br/docs/frameworks.md#idempotency). |
| `_ikiform_ts` | Momento de renderização assinado, definido pelo SDK e pelo componente shadcn/ui. Um envio feito menos de 2 segundos depois da renderização é pontuado como spam. |
| `cf-turnstile-response` | O token do Turnstile, adicionado pelo widget do Turnstile ou pelo SDK. |
| `_ikiform_via` | Definido pela própria página de verificação humana do Ikiform. Não envie você mesmo. |

Qualquer outro campo que começa com `_` também é descartado, então você pode usar nomes como `_source` para seus próprios marcadores ocultos sem armazená-los.

`demo.html`:

```html
<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <input type="hidden" name="_subject" value="New demo request" />
  <input type="hidden" name="_redirect" value="https://example.com/thanks" />
  <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" hidden />
  <button>Request a demo</button>
</form>
```

## O honeypot

O nome padrão do honeypot é `_gotcha`. Você pode mudá-lo por formulário em **Honeypot field**, nas configurações do formulário; qualquer nome que você escolher é tratado como reservado e nunca é armazenado. Um atributo `hidden` simples basta para a maioria dos bots. Se você notar spam passando, esconda o input fora da tela, porque alguns bots ignoram inputs marcados com `hidden`:

`honeypot.html`:

```html
<div aria-hidden="true" style="position:absolute;left:-10000px;width:1px;height:1px;overflow:hidden">
  <label>
    Leave this empty
    <input name="_gotcha" type="text" tabindex="-1" autocomplete="off" />
  </label>
</div>
```

Mantenha `tabindex="-1"` e `autocomplete="off"` para que usuários de teclado e gerenciadores de senha nunca o preencham.

## Adicionando uma verificação humana

Formulários com a verificação de spam definida como **Ikiform** não precisam de nenhuma mudança no HTML. Quando um navegador envia sem token, o Ikiform responde com uma página curta "Checking you're human" em ikiform.com. Ela roda o Cloudflare Turnstile e depois envia os campos originais de novo com o token. Seu visitante termina na mesma página de agradecimento de antes. Veja [Proteção contra spam](https://ikiform.com/pt-br/docs/spam.md#human-check) para o fluxo completo.

### Com suas próprias chaves do Turnstile

Se o formulário usa **Your own Turnstile keys**, renderize o widget você mesmo. Ele adiciona o campo `cf-turnstile-response` ao envio. Envios sem um token válido são rejeitados com `403 captcha_failed`.

`turnstile.html`:

```html
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" async defer></script>

<form action="https://ikiform.com/f/frm_xxxxxxxxxxxxxxxx" method="post">
  <input name="email" type="email" required />
  <div class="cf-turnstile" data-sitekey="YOUR_SITE_KEY"></div>
  <button>Send</button>
</form>
```
