Gate forms are ordinary same-origin HTML forms. POST /notify records coming-soon signup; POST /password (alias /unlock) verifies storefront access. Neither is a registered Vascula {% form %} kind. They return redirects or rendered HTML, not the hosted-action JSON envelope. Use the Gate pages guide for complete Vascula examples.
POST /notify#
Field |
Meaning |
|---|---|
Required valid email address. |
|
consent |
Required nonempty value from an unchecked consent checkbox the visitor selects. |
locale |
Active locale from settings.locale. |
_csrf |
Render the available csrf_token; do not invent a token. |
website |
Optional empty honeypot; real visitors leave it empty. |
The server resolves collect_emails from the published coming-soon composition and section schema defaults. Explicit false wins over a true default. The result is a 303 redirect with a one-shot HTTP-only flash; settings.notify_state carries its stable outcome code when the coming-soon gate renders; the GET renders the localized outcome into the required gate section’s settings. It is not a query-string API or a client-readable cookie API.
Outcome |
Meaning |
Theme value |
|---|---|---|
ok |
Accepted; new, duplicate and resubscribed addresses share the same success. A filled honeypot also returns uniform success without enrolling. |
settings.notify_success |
invalid_email |
The address is invalid or missing. |
settings.notify_error |
consent_required |
Explicit consent was not submitted. |
settings.notify_error |
retry_later |
Too many attempts; let the visitor retry later. |
settings.notify_error |
unavailable |
Collection is disabled, the storefront is no longer coming soon, or the server could not save the request. |
settings.notify_error when a coming-soon gate is rendered |
If storefront status changes between GET and POST, the redirected destination can be a different page. Never announce signup success without the returned success message. The outcome is consumed by one GET. Read it from the returned HTML when enhancing the form with fetch; a second navigation may no longer have the notice.
POST /password or /unlock#
Field |
Meaning |
|---|---|
password |
Required storefront password, unchanged. |
locale |
settings.locale, preserving the active language. |
return_to |
settings.return_to; the server validates the local destination. |
_csrf |
Include the rendered token when available; the pre-session unlock route uses rate limiting. |
Result |
Response and presentation |
|---|---|
Valid password |
Sets the secure HTTP-only unlock cookie; HTTP 302 to the validated return_to. |
Missing or incorrect password |
Password HTML with settings.password_error. |
Verification unavailable |
Password HTML with settings.password_error. |
Too many attempts |
HTTP 429 and password HTML with settings.password_error. |
Do not infer success from HTTP 200. An enhanced form should inspect the returned password-error node and the final known storefront destination. Preserve errors and any refreshed form token from non-2xx HTML. Leave plain POST working without JavaScript. Storefront passwords newly set or changed require at least 8 characters; this does not require client-side minlength validation on the unlock form.
Rendering outcomes#
{% if settings.notify_success != blank %}
<p role="status">{{ settings.notify_success }}</p>
{% endif %}
{% if settings.notify_error != blank %}
<p role="alert">{{ settings.notify_error }}</p>
{% endif %}
{% if settings.password_error != blank %}
<p role="alert">{{ settings.password_error }}</p>
{% endif %}
Render these values as escaped text. The success/error values are platform-localized display messages. Read settings.notify_state for the stable notify outcome code; do not infer it from the message wording. Do not use form_notice, form_error, or a made-up ctx.notify field as the gate outcome contract. Maintenance has no submit action: use a normal GET and the document/status rules in Gate pages.