{"id":25626648,"url":"https://github.com/dorianim/formrecevr","last_synced_at":"2025-04-14T12:31:29.334Z","repository":{"id":64306078,"uuid":"416647790","full_name":"dorianim/formrecevr","owner":"dorianim","description":"Formrecevr is a simple and lightweight from receiver backend primarily designed for (but not limited to) static websites.","archived":false,"fork":false,"pushed_at":"2023-09-06T13:16:24.000Z","size":127,"stargazers_count":5,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-28T01:48:12.046Z","etag":null,"topics":["backend","backend-api","forms","http","hugo","static-site"],"latest_commit_sha":null,"homepage":"https://hub.docker.com/r/dorianim/formrecevr","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dorianim.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-10-13T08:16:20.000Z","updated_at":"2025-02-06T11:32:36.000Z","dependencies_parsed_at":"2024-06-20T09:26:21.187Z","dependency_job_id":"4da316a9-2cef-44a3-9fae-c3dcf0b4b40b","html_url":"https://github.com/dorianim/formrecevr","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dorianim%2Fformrecevr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dorianim%2Fformrecevr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dorianim%2Fformrecevr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dorianim%2Fformrecevr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dorianim","download_url":"https://codeload.github.com/dorianim/formrecevr/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248881331,"owners_count":21176829,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","backend-api","forms","http","hugo","static-site"],"created_at":"2025-02-22T16:32:01.205Z","updated_at":"2025-04-14T12:31:29.287Z","avatar_url":"https://github.com/dorianim.png","language":"Go","readme":"\u003ch1 align=\"center\"\u003e\n    Formrecevr\n\u003c/h1\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003ca href=\"https://www.gnu.org/licenses/agpl-3.0\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/License-AGPL%20v3-blue.svg\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://github.com/dorianim/formrecevr/actions/workflows/tests.yml\"\u003e\n        \u003cimg src=\"https://github.com/dorianim/formrecevr/actions/workflows/tests.yml/badge.svg\" alt=\"Badge tests\"\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://hub.docker.com/r/dorianim/formrecevr\"\u003e\n        \u003cimg src=\"https://img.shields.io/docker/pulls/dorianim/formrecevr.svg\" alt=\"Docker pulls\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://goreportcard.com/report/github.com/dorianim/formrecevr\"\u003e\n        \u003cimg src=\"https://goreportcard.com/badge/github.com/dorianim/formrecevr\" alt=\"Go report\" /\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codecov.io/gh/dorianim/formrecevr\"\u003e\n        \u003cimg src=\"https://codecov.io/gh/dorianim/formrecevr/branch/main/graph/badge.svg?token=LJLPYEELOP\"/\u003e\n    \u003c/a\u003e\n    \u003ca href=\"https://codeclimate.com/github/dorianim/formrecevr/maintainability\"\u003e\n        \u003cimg src=\"https://api.codeclimate.com/v1/badges/72af8e8e7fa64952c338/maintainability\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\nFormrecevr (pronunced \"Form receiver\") is a simple and lightweight from receiver backend primarily designed for (but not limited to) static websites. It is inspired by [formspree.io](formspree.io) but it is simpler, self-hosted and doesn't have a frontend.\n\n# Features\n\n- **Easy setup:** Just create your docker-compose.yml and you're good to go!\n- **Powerful templating:** Use Go templating (just like in Hugo) to compose customized content\n- **Shoutrrr integration:** You can use a [wide variety of services](https://containrrr.dev/shoutrrr/v0.5/services/overview/) to reveive your form submissions\n- **Flexible delivery:** Thanks to the use of shoutrrr and templating, you can use data from the form as a receiver\n- **Cloudflare Turnstile:** [Couldflare Turnstile](https://developers.cloudflare.com/turnstile) is a modern and privacy preserving CAPTCHA.\n\n# Setup\n\nThe official installation method is using Docker:\n\n1. Create a folder for installation:\n   ```bash\n   mkdir /opt/formrecevr \u0026\u0026 cd /opt/formrecevr\n   ```\n2. Create the file docker-compose.yml with this content:\n   ```yaml\n   version: \"3.7\"\n   services:\n     formrecevr:\n       image: dorianim/formrecevr\n       restart: always\n       ports:\n         - 5081:8088\n       volumes:\n         - ./config:/config\n   ```\n3. Adjust the port (default `5081`) to your needs\n4. Start the formrecevr:\n   ```bash\n   docker-compose up -d\n   ```\n5. Done! You can reach your formrecevr on `localhost:80`\n6. [Adjust your `config.yml`](#configuration) in `/opt/formrecevr/config/config.yml`\n7. [OPTIONAL] Adjust your templates in `/opt/formrecevr/config/templates`\n8. [OPTIONAL] To setup ssl/https, please use a reverse proxy like nginx\n\n# Configuration\n\nThe configuration is stored in `/config/config.yml` in the container by default. It is reloaded live, so changes do not require a container restart to become effective.  \nA fully populated config could look like this:\n\n```yaml\nforms:\n  - id: \"Example\"\n    enabled: true\n    targets:\n      - enabled: true\n        template: default.html\n        shoutrrrurl: \"telegram://someToken@telegram/?channels={{ .params.someChannel }}\"\n        params:\n          someKey: someChannel\n      - enabled: false\n        template: email.html\n        shoutrrrurl: \"smtp://username:password@host:port/?from=fromAddress\u0026to=recipient1\u0026to={{ .mailFromFrom }}\"\n\n  - id: \"Example2\"\n    enabled: true\n    turnstile:\n      enabled: true\n      secretkey: \"1x0000000000000000000000000000000AA\"\n    targets:\n      - enabled: true\n        template: default.html\n        shoutrrrurl: \"slack://token:token@channel/\"\nlisten:\n  host: 0.0.0.0\n  port: 8088\n```\n\n### Fields\n\n- `listen` contains settings for the webserver\n- `forms` contains a list of [form blocks](#the-form-block)\n\n#### The form block\n\n- `id`: The ID of the form. I suggest using something like `uuidgen` to create a random ID\n- `enabled`: If the form is enabled. It will not work when this is set to false\n- `targets`: Contains a list of [target blocks](#the-target-block)\n- `turnstile`: Contains the [turnsilte-config](#the-turnstile-config)\n\n#### The target block\n\n- `enabled`: If the target is enabled. It will be skipped when set to false\n- `template`: The name of the template which is used for the body. See [templates](#templates)\n- `shoutrrrurl`: The [shoutrrr](https://containrrr.dev/shoutrrr/v0.5/) URL to use for form submissions. Additional information on how to get the URLs can be found [here](https://containrrr.dev/shoutrrr/v0.5/services/overview/)\n- `params`: Additional parameters which are also passed to the templating engine as `.params.\u003ckey\u003e`. This can be useful when using the same template for multiple targets.\n\n#### The Turnstile config\n\n- `enabled`: If Turnstile is enabled. Defaults to `flase`\n- `secretkey`: The Turnsitle sectre key.\n\n# Templates\n\nTemplates have to be stored in `/config/templates` by default.\nThe templates are processed by the go templating engine and have access to all of its functionality, like range loops and if conditions.\n\n### Variables\n\nTemplates can use all submited form fields in the root context. In addition to that, they have access to the params defined for their target inside the `.params` key.  \nFor testing, you can use `{{ . }}` to see all avaiable data.\n\n### Functions\n\nThere are two additional functions wich can be used:\n\n- `join`: Joins a list of strings with a delimiter, eg. `{{ join .someListParameter \",\" }}`\n- `print`: Prints one or more strings or string lists without any delimiter, eg. `{{ print .someString .someStringList }}`\n\n# Routes / API\n\nThere are currently two routes available\n\n- `/api/v1/healthcheck` (GET): Should return 200 if everything is OK\n- `/f/:formID` (POST): Accepts form data for configured formIDs. It currently supports `application/x-www-form-urlencoded` and `multipart/form-data`\n\n# Implementation\n\nI recommend to use the javascript [`fetch()` API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) to submit your form. An example of this can be found in [`examples/form-xhr-fetch.html`](https://github.com/dorianim/formrecevr/blob/main/examples/form-xhr-fetch.html)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdorianim%2Fformrecevr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdorianim%2Fformrecevr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdorianim%2Fformrecevr/lists"}