Quickstart

Vendor Webform Relay into your project, deploy it to AWS, and send your first form submission — in under ten minutes.

This is the condensed path. Getting Started is the same flow with every step explained, plus CI/CD, rollback, teardown, and the flow’s known gaps. Working on webform-relay rather than with it? See the Contribution Guide.

Prerequisites

  • Docker installed and running
  • Task 3+ installed
  • v installed
  • An AWS account with an admin-level identity, used once to create the least-privilege deploy user

No host AWS CLI, SAM CLI, or ~/.aws/credentials needed — everything runs in Docker.

1. Vendor it

From your own project’s repo root:

v add https://gitlab.com/frob/webform-relay <tag>

2. Wire it into your Taskfile

In your project’s own Taskfile.yml:

version: '3'

dotenv: ['.env', '.env.project']

includes:
  relay:
    taskfile: ./vendor/gitlab.com/frob/webform-relay/taskfiles/deploy.yml
    dir: ./vendor/gitlab.com/frob/webform-relay

3. Copy the config templates out of the vendored directory

cp vendor/gitlab.com/frob/webform-relay/.env.example  .env
cp vendor/gitlab.com/frob/webform-relay/.env.project  .env.project

.env holds the AWS keys and FORM_TOKEN_SECRET and is gitignored; .env.project holds region, bucket names, and stack parameters and is committed. Fill in the ADMIN_* keys in .env, and CONFIG_BUCKET / SAM_ARTIFACTS_BUCKET in .env.project.

4. Bootstrap AWS

task relay:tools:build      # SAM/AWS CLI tools image (once)
task relay:aws:bootstrap    # deploy IAM user + both S3 buckets

Copy the printed AccessKeyId / SecretAccessKey into AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY in .env.

5. Write a config file

Save this as webform.yaml at your project root:

cache_ttl: 30s

forms:
  contact:
    fields:
      - name: name
        required: true
      - name: email
        required: true
        type: email
      - name: message
        required: true
        type: textarea
    outputs:
      - type: email
        to: you@example.com
        subject: "New contact submission"
        mapping:
          from_name: name
          from_email: email
          body: message

Upload it to the config bucket:

task relay:upload:config CONFIG=webform.yaml

6. Deploy

Fully non-interactive — every parameter comes from .env/.env.project, and no samconfig.toml is created or needed:

task relay:build:container
task relay:deploy:app

Re-run the same commands for every subsequent deploy. If you only changed the config YAML, re-run task relay:upload:config CONFIG=webform.yaml and skip the deploy — changes take effect within CACHE_TTL.

7. Get the form HTML

The deployed stack renders it for you:

curl https://<api-id>.execute-api.<region>.amazonaws.com/api/v1/form/contact

(The webform-relay form html CLI does the same offline, but it lives in cmd/cli and is built by taskfiles/dev.yml, which is not part of the vendored deploy taskfile. Build it straight from the vendored source if you want it: docker run --rm -v $PWD/vendor/gitlab.com/frob/webform-relay:/app -w /app golang:1.23 go run ./cmd/cli form html contact.)

Paste the output into your HTML page, or point an existing <form> at the endpoint:

<form method="post"
      action="https://<api-id>.execute-api.<region>.amazonaws.com/api/v1/submit/contact"
      enctype="application/x-www-form-urlencoded">
  <input name="name" type="text" required>
  <input name="email" type="email" required>
  <textarea name="message" required></textarea>
  <button type="submit">Send</button>
</form>

8. Test the endpoint

curl -X POST \
  https://<api-id>.execute-api.<region>.amazonaws.com/api/v1/submit/contact \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "name=Jane+Doe&email=jane@example.com&message=Hello"

Expected response:

{"message": "ok"}