lazysite forms are defined inline in page content using :::form blocks.
The processor generates an HTML form with built-in anti-spam protection.
Submissions are handled by a CGI script that validates and dispatches
to named handlers defined in lazysite/forms/handlers.conf.
Three config files work together:
lazysite/forms/FORMNAME.conflazysite/forms/handlers.confid, type, and type-specific settings.
lazysite/forms/smtp.confA form targets one or more handlers by ID. Multiple forms can share the same handler, and a form can dispatch to multiple handlers at once.
form: formname to the page's front matter:::form block with field definitionslazysite/forms/formname.conf pointing at a handler IDlazysite/forms/handlers.conflazysite/forms/smtp.confThe form: key enables form processing for the page and names the form.
The name must be alphanumeric with hyphens and underscores only:
---
title: Contact
form: contact
---
Without form: in front matter, :::form blocks render as an HTML
comment and a warning is logged.
<!-- lazysite: form: key required in front matter -->
Each line defines a field. Fields are separated by pipe characters:
name attribute (alphanumeric, hyphens, underscores)The submit keyword as field name renders a submit button with the
label as button text.
requiredrequired attribute and shows
an asterisk after the label.
optionalemailtype="email" input with browser validation.
textarea<textarea> instead of a single-line input.
select:opt1,opt2,opt3<select> dropdown with the given options.
max:Nmaxlength attribute. Default is 1000 if not specified.
---
title: Contact
form: contact
---
## Get in touch
<!-- lazysite: form: key required in front matter -->
lazysite/forms/FORMNAME.conf lists the handlers that receive
submissions:
targets:
- handler: email-delivery
- handler: local-storage
Each entry references a handler by id. All listed handlers are
dispatched on each submission. If one handler fails, the others still
run.
lazysite/forms/handlers.conf defines the handlers:
handlers:
- id: email-delivery
type: smtp
name: Email delivery
enabled: true
from: webforms@example.com
to: admin@example.com
subject_prefix: "[Contact] "
- id: local-storage
type: file
name: Local file storage
enabled: true
path: lazysite/forms/submissions
- id: slack-notify
type: webhook
name: Slack notification
enabled: false
url: https://hooks.slack.com/services/XXX
format: slack
Handlers with enabled: false are skipped.
smtpfrom, to, and
subject_prefix. Connection settings come from
lazysite/forms/smtp.conf. See Forms SMTP.
filepath. Useful for logging,
offline processing, or testing without email infrastructure.
webhookformat: json for a plain JSON
body, or format: slack for Slack-compatible {"text": "..."}.
Forms submit via fetch() (AJAX). On success, the form is replaced
with a success message. On error, an error message appears below the
submit button. The page does not reload.
The form status area uses aria-live="polite" for screen reader
accessibility.
All security measures are automatic - no configuration needed:
Honeypot field - a hidden field (_hp) that must be empty.
Bots that fill all fields are rejected.
HMAC timestamp token - submissions must arrive between 3 seconds and 2 hours after the form was rendered. Prevents replay attacks.
Rate limiting - maximum 5 submissions per IP per hour. Uses
DB_File for persistence.
Header injection prevention - CR/LF characters stripped from all fields.
The HMAC secret is auto-generated and stored at
lazysite/forms/.secret (chmod 0660 - owner + group, never world,
so both the site user's tools and the web-server CGI can use it
whichever minted it first).
The installer places both plugins under {docroot}/../plugins/
and symlinks form-handler.pl into cgi-bin/ so Apache can route
/cgi-bin/form-handler.pl at it. form-smtp.pl does not need
cgi-bin/ presence - it is invoked as a subprocess by
form-handler.pl.
For manual installation:
mkdir -p /path/to/plugins
cp plugins/form-handler.pl plugins/form-smtp.pl /path/to/plugins/
chmod 755 /path/to/plugins/form-handler.pl /path/to/plugins/form-smtp.pl
ln -s /path/to/plugins/form-handler.pl /path/to/cgi-bin/form-handler.pl