Skip to main content
View as Markdown

Form Availability

Registration opens Monday. The workshop seats forty. The survey closes at the end of the quarter. Each of those is a rule about when a form accepts answers, and each one otherwise becomes a calendar reminder to go and edit the config by hand.

availability states the rule once and lets the server enforce it:

forms:
  - id: 1
    name: workshop-signup
    title: Spring Workshop
    submitTo: { table: registrations }
    availability:
      opensAt: '2026-03-01T09:00:00Z'
      closesAt: '2026-03-20T23:59:59Z'
      maxSubmissions: 40
    fields:
      - { kind: table-field, column: email, required: true }

Availability Properties

Every property is optional. Omit the block and the form is open, forever, with no cap.

Property Description Default
opensAt ISO 8601 timestamp at which the form starts accepting submissions. Open immediately.
closesAt ISO 8601 timestamp at which it stops. Never closes.
maxSubmissions Positive integer cap. The submission after the cap is refused. Unlimited.
closedPage Custom page shown while the form is closed, for any of the three reasons. Title + boilerplate copy.

When both timestamps are set, opensAt must be strictly before closesAt. A window that closes before it opens accepts nothing and is almost always a typo, so it fails when the config is decoded, naming the form and both timestamps.

What a Closed Form Answers

Opening a closed form is not an error — the visitor gets a page explaining the situation. Posting to one is refused with a structured body so a programmatic client can tell the three cases apart.

State GET /forms/{name} POST status Error body
Before opensAt Closed page 403 { error: 'form not yet open', opensAt }
After closesAt Closed page 403 { error: 'form closed', closedAt }
At maxSubmissions Form still renders 403 { error: 'submission limit reached', maxSubmissions, currentCount }

A refused submission writes nothing — no ledger row, no table row, no automation run.

The Closed Page

Left unconfigured, the closed page shows the form's own title and a sentence explaining that it is not yet open (quoting opensAt) or no longer accepting answers. closedPage replaces that with your own copy and, optionally, a way forward:

availability:
  closesAt: '2026-03-20T23:59:59Z'
  closedPage:
    title: Registration has closed
    message: Spring places are full. The autumn cohort opens in July.
    cta:
      label: Join the waiting list
      href: /waiting-list
Property Description Default
title Page heading. The form's title.
message Body copy. Default explanation for the reason.
cta.label Link text. Requires cta.href. No link.
cta.href Link target. Requires cta.label. No link.
type Reserved discriminator; only page is accepted. page

The same page serves all three closed states, so write copy that reads sensibly whether the form has not opened yet or has filled up.

Last updated July 27, 2026

This documentation was written with AI, so errors or outdated content are possible. Sovrium is in beta — contributions and corrections are welcome.

Built with Sovrium