From e55d720e943e5d5cd4dda15857675c2e542582fd Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Fri, 29 Apr 2022 11:13:01 +0200 Subject: [PATCH 01/10] reorganized docs --- README.md | 186 ++++++------------------------------------------------ 1 file changed, 21 insertions(+), 165 deletions(-) diff --git a/README.md b/README.md index 2e0b9a8..d73f48c 100644 --- a/README.md +++ b/README.md @@ -2,28 +2,25 @@ [![Actions Status](https://github.com/rchakode/hugo-mx-gateway/workflows/Build/badge.svg)](https://github.com/rchakode/hugo-mx-gateway/actions) -
- -Table of Contents - +--- - [Overview](#overview) -- [Why hugo-mx-gateway](#why-hugo-mx-gateway) - - [How does it work](#how-does-it-work) - - [Prerequisites](#prerequisites) -- [Deployment](#deployment) - - [Deployment on Google App Engine](#deployment-on-google-app-engine) - - [Deployment on a Kubernetes cluster](#deployment-on-a-kubernetes-cluster) - - [Deployment on Docker](#deployment-on-docker) -- [Use the built-in form for Hugo](#use-the-built-in-form-for-hugo) -- [Configuration variables](#configuration-variables) + - [Hugo-mx-gateway in a Nutshell](#hugo-mx-gateway-in-a-nutshell) +- [Getting Started](#getting-started) - [License & Copyrights](#license--copyrights) - [Support & Contributions](#support--contributions) -
- # Overview -In a nutshell, `hugo-mx-gateway` provides a RESTful POST endpoint for static contact/demo request pages. It's a simple, yet a powerful tool built for this only-designated purpose. +Did you ever experience building a static website (e.g. using [Hugo](https://gohugo.io/) or whatever alternative), then did get stuck when coming the time to add a contact/demo request form? + +You're at the right place. + +This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that adds the dynamicity required to handle contactdemo requests for static web sites. It's a simple, yet a powerful tool built for this only-designated purpose. + +![Screenshot of a successful submission](./screenshots/form-submitted-and-processed-with-success.png) + +## Hugo-mx-gateway in a Nutshell +`hugo-mx-gateway` provides a RESTful POST endpoint for static contact/demo request pages. It's a simple, yet a powerful tool built for this only-designated purpose. > **This project is used in production for several static websites built with [Hugo](https://gohugo.io/); Contributions in any form (code/docs/ideas...) are welcomed.** @@ -31,156 +28,15 @@ Contributions in any form (code/docs/ideas...) are welcomed.** ![](hugo-mx-gateway-architecture-overview.png) -# Why hugo-mx-gateway -Did you ever experience building a static website (e.g. using [Hugo](https://gohugo.io/) or whatever alternative), then did get stuck when coming the time to add a contact/demo request form? +# Getting Started +Use the following resoures to deploy and get started with hugo-mx-gateway. -You're at the right place. - -This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that adds the dynamicity required to handle contact/demo requests for static web sites. It's a simple, yet a powerful tool built for this only-designated purpose. - -![Screenshot of a successful submission](./screenshots/form-submitted-and-processed-with-success.png) - -## How does it work -`hugo-mx-gateway` is built upon a simple request handling workflow: - -* Create an HTML form with a POST action pointing towards the `hugo-mx-gateway` service. This service enables a RESTful POST endpoint backed by an application built in Go. The application is released as container image along with manifests to ease deployment on [Google App Engine](https://cloud.google.com/appengine), Kubernetes, and Docker environments. -* For each user request, `hugo-mx-gateway` automatically retrieves information submitted by the user (email, subject, message details...), then **generates and sends** a **templated email** (based on [Go Template](https://golang.org/pkg/text/template/)) to the user-provided email address, while **bcc**ing a copy of that email to an address that you can define for internal tracking and follow up. -* Once a request is processed (upon success or failure), `hugo-mx-gateway` handles the reply back towards the calling static page by redirecting the browser to the origin page with additional URL parameters describing the completion status of the processing (e.g. `/contact.html?status=success&message=request%20submitted`). The parameters can then be easily retrieved and shown to the user, e.g. with a few lines of Javascript within the static page. -* The project is shipped with a sample HTML form intending to cover a basic use case of contact and demo requests. That said, this is a open source software, so you're free to adapt it for your specific use cases. - -## Prerequisites -`hugo-mx-gateway` is easily deployable in minutes, subject to fulfil the following requirements: - -* Deployment platform (at your choice): Google App Engine, Kubernetes, or Docker. -* An SMTP account with the server supporting TLS. - -These are basic requirements in the today's Internet world. - -> While it can be tempting to use a personal email account, it's highly recommended for security and privacy reasons to not do that. According to your needs, you may have to ask for an SMTP account to your corporate's IT staff. When applicable, you can alternatively opt for a cloud-based SMTP service like SendGrid, Mailgun or Mailjet, which typically offer free tier for small usage. - -# Deployment -Consider one of the following resources according to the selected installation platform. - -## Deployment on Google App Engine -This requires to have an active GCP account and [Google Cloud SDK](https://cloud.google.com/sdk) (gcloud) installed on your work station. - -* Create/select a GCP project to deploy `hugo-mx-gateway`. - - Note that each GCP project can hold only a single App Engine instance. Several applications can be co-hosted as services for the root App Engine instance. In this case, a new application has to be declared as `service` in the `app.yaml` file. -* Create the Google App Engine configuration file - ``` - cp app.yaml.sample app.yaml - ``` -* Open the `app.yaml` file with your favorite editor. -* Edit the configuration variables as described [here](#configuration-variables). -* Start the deployment - ``` - make deploy-gcp - ``` -* Check that `hugo-mx-gateway` is up and working - ``` - curl https://PROJECT-ID.REGION.r.appspot.com/ - ``` - Replace `PROJECT-ID` with the GCP project ID, and `REGION` with the deployment region.* - - The output in case of success shall be `{"status": "ok"}`. - -## Deployment on a Kubernetes cluster -There is a [Helm chart](./helm/) to ease the deployment on Kubernetes clusters. - -> **Important:** The chart is validated with Helm 3 and the pod is run in an unprivileged mode within a **Security Context**. - -Proceed with the deployment as follows: - -* First edit the [values.yaml](./helm/values.yaml) file to set [configuration values](#configuration-variables) appropriately. -* Choose a deployment namespace. In the sample commands provided hereafter, it's assumed that the target namespace is `hugo-mx-gateway`. If you opt for another namespace, do consider to adapt the commands accordingly. -* Apply the deployment with Helm - ``` - helm upgrade \ - --namespace hugo-mx-gateway \ - --install hugo-mx-gateway \ - helm/ - ``` - -* Check that the application is up and running. - ``` - kubectl -n hugo-mx-gateway port-forward service/hugo-mx-gateway 8080:80 - curl http://127.0.0.1:8080/ - ``` - -The output in case of success shall be `{"status": "ok"}`. - - -## Deployment on Docker -An instance of `hugo-mx-gateway` can be quickly started on any machine running Docker. - -* Please first review the [configuration variables](#configuration-variables) and adapt them appropriately. - -* Then apply the following command: - - ``` - docker run -d \ - --publish 8080:8080 \ - --name 'hugo-mx-gateway' \ - -e SMTP_SERVER_ADDR="smtp.example.com:465" \ - -e SMTP_VERITY_CERT=true \ - -e SMTP_CLIENT_USERNAME="postmaster@example.com" \ - -e SMTP_CLIENT_PASSWORD="postmasterSecretPassWord" \ - -e CONTACT_REPLY_EMAIL="noreply@example.com" \ - -e CONTACT_REPLY_BCC_EMAIL="contact@example.com" \ - -e DEMO_URL="https://demo.example.com/" \ - -e ALLOWED_ORIGINS="127.0.0.1,example.com" \ - rchakode/hugo-mx-gateway - ``` - -* Check that the container is up and functionning. - - ``` - curl http://127.0.0.1:8080/ - ``` -The output in case of success shall be `{"status": "ok"}`. - -# Use the built-in form for Hugo -The file `./samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo. It can be used for both contact and demo requests. - -Open the file in your favorite editor and review it. - -Notice that the form is configured to be rendered specifically according to a Hugo parameter named **tags**, which is actually a **list of tags**. If the parameter holds a tag named `contact` then, the form will be rendered as a contact form. Otherwise, it'll be rendered as a demo form. - -The integration works as follows: - * Copy the HTML form content in your target **Hugo HTML template**. - * Modify the `
` tag to make the **action** point to the URL of the sendmail backend deployed previously. - * On Google App Engine, the endpoint shall be: https://PROJECT-ID.REGION.r.appspot.com/sendmail. Replace `PROJECT-ID` and `REGION`, repectively, with the GCP's project ID and the deployment region. - * On Kubernetes, the in-cluster endpoint shall be: http://hugo-mx-gateway.hugo-mx-gateway.svc.cluster.local/sendmail - * On Docker, the endpoint shall be: http://DOCKER-HOST:8080/sendmail. Replace `DOCKER-HOST` with the IP address or the hostname of the Docker machine. - * Edit the **Hugo Markdown content** of the target contact/demo page to ensure that the **tags** parameter holds a appropriate value (i.e. `contact` for a contact form, or `demo` for a demo request form). - -Here is an example of header for a Hugo Markdown page. The `tags` parameter holds a tag named `contact`) meaning that the page will be rendered as a contact request form. - - ``` - --- - title: "Contact Us" - description: "Contact request page" - date: 2020-04-25T00:20:27+02:00 - tags: [contact] - --- - ``` - - -# Configuration variables -Regardless of the deployment platform (Google App Engine, Kubernetes, Docker), the following configuration parameters must be provided as environment variables: - -* `SMTP_SERVER_ADDR`: Set the address of the SMTP server in the form of `host:port`. It's required that the SMTP server being supporting TLS. -* `SMTP_VERITY_CERT`: Tell whether the SMTP certificate should be validated against top level authorities. If you're using a self-signed certificate on the SMTP server, this value must be set to `false`. -* `SMTP_CLIENT_USERNAME`: Set the username to connect to the SMTP server. -* `SMTP_CLIENT_PASSWORD`: Set the password to connect to the SMTP server. -* `CONTACT_REPLY_EMAIL`: Set an email address for the reply email. It's not necessary a valid email address; for example if don't want the user to reply the email, you can set something like `noreply@example.com`. -* `CONTACT_REPLY_BCC_EMAIL`: Sets an email address for bcc copy of the email sent to the user. This is useful for tracking and follow up. -* `DEMO_URL`: Specific for demo forms, it can be used to set the URL of the demo site that will be included to the user reply email (e.g. `https://demo.example.com/`). -* `ALLOWED_ORIGINS`: Set a list of comma-separated list of domains that the `hugo-mx-gateway` App should trust. For security reason, only requests with an `Origin` header belonging to the defined list of origins will be accepted. -* `RECAPTCHA_PRIVATE_KEY` (optional): The [reCaptcha](https://www.google.com/recaptcha/intro/v3.html) private key. -* `TEMPLATE_DEMO_REQUEST_REPLY` (optional): Specify the path of the template to reply a demo request. The default templare is `templates/template_reply_demo_request.html`. The template is based on [Go Template](https://golang.org/pkg/text/template/). -* `TEMPLATE_CONTACT_REQUEST_REPLY` (optional): Specify the path of the template to reply a contact request. The default templare is `templates/template_reply_contact_request.html`. The template is based on [Go Template](https://golang.org/pkg/text/template/). +* [Deployment on Kubenetes](./docs/deployment-on-kubernetes.md) +* [Deployment on Google Computinf Engine](./docs/deployment-on-kubernetes.md) +* [Deployment on Docker](./docs/deployment-on-kubernetes.md) +* [Deployment on Debian](./docs/deployment-on-debian.md) +* [Configuration Variables](./docs/configuration-variables.md) +* [Sample of contact form for Hugo](./docs/sample-of-hugo-dontact-form.md) # License & Copyrights This tool (code and documentation) is licensed under the terms of Apache 2.0 License. Read the [LICENSE](LICENSE) file for more details on the license terms. From 0cf8a3353d92bf4bda56f8d46a998c2af8c645b7 Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Fri, 29 Apr 2022 11:17:22 +0200 Subject: [PATCH 02/10] added missing files --- README.md | 6 ++--- docs/configuration-variables.md | 15 +++++++++++ docs/deployment-on-debian.md | 3 +++ docs/deployment-on-docker.md | 30 +++++++++++++++++++++ docs/deployment-on-google-compute-engine.md | 25 +++++++++++++++++ docs/deployment-on-kubernetes.md | 25 +++++++++++++++++ docs/design-fundamentals.md | 8 ++++++ docs/sample-of-hugo-dontact-form.md | 29 ++++++++++++++++++++ 8 files changed, 138 insertions(+), 3 deletions(-) create mode 100644 docs/configuration-variables.md create mode 100644 docs/deployment-on-debian.md create mode 100644 docs/deployment-on-docker.md create mode 100644 docs/deployment-on-google-compute-engine.md create mode 100644 docs/deployment-on-kubernetes.md create mode 100644 docs/design-fundamentals.md create mode 100644 docs/sample-of-hugo-dontact-form.md diff --git a/README.md b/README.md index d73f48c..5e30e52 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,9 @@ You're at the right place. This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that adds the dynamicity required to handle contactdemo requests for static web sites. It's a simple, yet a powerful tool built for this only-designated purpose. -![Screenshot of a successful submission](./screenshots/form-submitted-and-processed-with-success.png) + +![](hugo-mx-gateway-architecture-overview.png) + ## Hugo-mx-gateway in a Nutshell `hugo-mx-gateway` provides a RESTful POST endpoint for static contact/demo request pages. It's a simple, yet a powerful tool built for this only-designated purpose. @@ -25,8 +27,6 @@ This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that a > **This project is used in production for several static websites built with [Hugo](https://gohugo.io/); Contributions in any form (code/docs/ideas...) are welcomed.** -![](hugo-mx-gateway-architecture-overview.png) - # Getting Started Use the following resoures to deploy and get started with hugo-mx-gateway. diff --git a/docs/configuration-variables.md b/docs/configuration-variables.md new file mode 100644 index 0000000..e242ef5 --- /dev/null +++ b/docs/configuration-variables.md @@ -0,0 +1,15 @@ +# Configuration variables + +Regardless of the deployment platform (Google App Engine, Kubernetes, Docker), the following configuration parameters must be provided when deploying hugo-mx-gateway. + +* `SMTP_SERVER_ADDR`: Set the address of the SMTP server in the form of `host:port`. It's required that the SMTP server being supporting TLS. +* `SMTP_VERITY_CERT`: Tell whether the SMTP certificate should be validated against top level authorities. If you're using a self-signed certificate on the SMTP server, this value must be set to `false`. +* `SMTP_CLIENT_USERNAME`: Set the username to connect to the SMTP server. +* `SMTP_CLIENT_PASSWORD`: Set the password to connect to the SMTP server. +* `CONTACT_REPLY_EMAIL`: Set an email address for the reply email. It's not necessary a valid email address; for example if don't want the user to reply the email, you can set something like `noreply@example.com`. +* `CONTACT_REPLY_BCC_EMAIL`: Sets an email address for bcc copy of the email sent to the user. This is useful for tracking and follow up. +* `DEMO_URL`: Specific for demo forms, it can be used to set the URL of the demo site that will be included to the user reply email (e.g. `https://demo.example.com/`). +* `ALLOWED_ORIGINS`: Set a list of comma-separated list of domains that the `hugo-mx-gateway` App should trust. For security reason, only requests with an `Origin` header belonging to the defined list of origins will be accepted. +* `RECAPTCHA_PRIVATE_KEY` (optional): The [reCaptcha](https://www.google.com/recaptcha/intro/v3.html) private key. +* `TEMPLATE_DEMO_REQUEST_REPLY` (optional): Specify the path of the template to reply a demo request. The default templare is `templates/template_reply_demo_request.html`. The template is based on [Go Template](https://golang.org/pkg/text/template/). +* `TEMPLATE_CONTACT_REQUEST_REPLY` (optional): Specify the path of the template to reply a contact request. The default templare is `templates/template_reply_contact_request.html`. The template is based on [Go Template](https://golang.org/pkg/text/template/). diff --git a/docs/deployment-on-debian.md b/docs/deployment-on-debian.md new file mode 100644 index 0000000..3dbf661 --- /dev/null +++ b/docs/deployment-on-debian.md @@ -0,0 +1,3 @@ +# Deploying hugo-mx-gateway on Debian + +WIP => PR in progress \ No newline at end of file diff --git a/docs/deployment-on-docker.md b/docs/deployment-on-docker.md new file mode 100644 index 0000000..a2a9cba --- /dev/null +++ b/docs/deployment-on-docker.md @@ -0,0 +1,30 @@ +# Deploying hugo-mx-gateway on Docker + + +An instance of `hugo-mx-gateway` can be quickly started on any machine running Docker. + +* Please first review the [configuration variables](#configuration-variables) and adapt them appropriately. + +* Then apply the following command: + + ``` + docker run -d \ + --publish 8080:8080 \ + --name 'hugo-mx-gateway' \ + -e SMTP_SERVER_ADDR="smtp.example.com:465" \ + -e SMTP_VERITY_CERT=true \ + -e SMTP_CLIENT_USERNAME="postmaster@example.com" \ + -e SMTP_CLIENT_PASSWORD="postmasterSecretPassWord" \ + -e CONTACT_REPLY_EMAIL="noreply@example.com" \ + -e CONTACT_REPLY_BCC_EMAIL="contact@example.com" \ + -e DEMO_URL="https://demo.example.com/" \ + -e ALLOWED_ORIGINS="127.0.0.1,example.com" \ + rchakode/hugo-mx-gateway + ``` + +* Check that the container is up and functionning. + + ``` + curl http://127.0.0.1:8080/ + ``` +The output in case of success shall be `{"status": "ok"}`. diff --git a/docs/deployment-on-google-compute-engine.md b/docs/deployment-on-google-compute-engine.md new file mode 100644 index 0000000..9dcbe55 --- /dev/null +++ b/docs/deployment-on-google-compute-engine.md @@ -0,0 +1,25 @@ +# Deploying hugo-mx-gateway on Google App Engine + + +This requires to have an active GCP account and [Google Cloud SDK](https://cloud.google.com/sdk) (gcloud) installed on your work station. + +* Create/select a GCP project to deploy `hugo-mx-gateway`. + + Note that each GCP project can hold only a single App Engine instance. Several applications can be co-hosted as services for the root App Engine instance. In this case, a new application has to be declared as `service` in the `app.yaml` file. +* Create the Google App Engine configuration file + ``` + cp app.yaml.sample app.yaml + ``` +* Open the `app.yaml` file with your favorite editor. +* Edit the configuration variables as described [here](#configuration-variables). +* Start the deployment + ``` + make deploy-gcp + ``` +* Check that `hugo-mx-gateway` is up and working + ``` + curl https://PROJECT-ID.REGION.r.appspot.com/ + ``` + Replace `PROJECT-ID` with the GCP project ID, and `REGION` with the deployment region.* + + The output in case of success shall be `{"status": "ok"}`. diff --git a/docs/deployment-on-kubernetes.md b/docs/deployment-on-kubernetes.md new file mode 100644 index 0000000..075d285 --- /dev/null +++ b/docs/deployment-on-kubernetes.md @@ -0,0 +1,25 @@ +# Deploying hugo-mx-gateway on Kubernetes + +From the source tree, the folder `./helm/` contains Helm manifest to ease the deployment of hugo-mx-gateway on Kubernetes clusters. + +> **Important:** The chart is validated with Helm 3 and the pod is run in an unprivileged mode within a **Security Context**. + +Proceed with the deployment as follows: + +* First edit the [values.yaml](./helm/values.yaml) file to set [configuration values](#configuration-variables) appropriately. +* Choose a deployment namespace. In the sample commands provided hereafter, it's assumed that the target namespace is `hugo-mx-gateway`. If you opt for another namespace, do consider to adapt the commands accordingly. +* Apply the deployment with Helm + ``` + helm upgrade \ + --namespace hugo-mx-gateway \ + --install hugo-mx-gateway \ + helm/ + ``` + +* Check that the application is up and running. + ``` + kubectl -n hugo-mx-gateway port-forward service/hugo-mx-gateway 8080:80 + curl http://127.0.0.1:8080/ + ``` + +The output in case of success shall be `{"status": "ok"}`. diff --git a/docs/design-fundamentals.md b/docs/design-fundamentals.md new file mode 100644 index 0000000..2a47541 --- /dev/null +++ b/docs/design-fundamentals.md @@ -0,0 +1,8 @@ +# Design Fundamentals of Hugo-mx-gateway + +`hugo-mx-gateway` is built upon a simple request handling workflow: + +* Create an HTML form with a POST action pointing towards the `hugo-mx-gateway` service. This service enables a RESTful POST endpoint backed by an application built in Go. The application is released as container image along with manifests to ease deployment on [Google App Engine](https://cloud.google.com/appengine), Kubernetes, and Docker environments. +* For each user request, `hugo-mx-gateway` automatically retrieves information submitted by the user (email, subject, message details...), then **generates and sends** a **templated email** (based on [Go Template](https://golang.org/pkg/text/template/)) to the user-provided email address, while **bcc**ing a copy of that email to an address that you can define for internal tracking and follow up. +* Once a request is processed (upon success or failure), `hugo-mx-gateway` handles the reply back towards the calling static page by redirecting the browser to the origin page with additional URL parameters describing the completion status of the processing (e.g. `/contact.html?status=success&message=request%20submitted`). The parameters can then be easily retrieved and shown to the user, e.g. with a few lines of Javascript within the static page. +* The project is shipped with a sample HTML form intending to cover a basic use case of contact and demo requests. That said, this is a open source software, so you're free to adapt it for your specific use cases. diff --git a/docs/sample-of-hugo-dontact-form.md b/docs/sample-of-hugo-dontact-form.md new file mode 100644 index 0000000..e51b153 --- /dev/null +++ b/docs/sample-of-hugo-dontact-form.md @@ -0,0 +1,29 @@ + +# Sample of contact form for Hugo + +From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo. It can be used for both contact and demo requests. + +![Screenshot of a successful submission](./screenshots/form-submitted-and-processed-with-success.png) + +Open the file in your favorite editor and review it. + +Notice that the form is configured to be rendered specifically according to a Hugo parameter named **tags**, which is actually a **list of tags**. If the parameter holds a tag named `contact` then, the form will be rendered as a contact form. Otherwise, it'll be rendered as a demo form. + +The integration works as follows: + * Copy the HTML form content in your target **Hugo HTML template**. + * Modify the `` tag to make the **action** point to the URL of the sendmail backend deployed previously. + * On Google App Engine, the endpoint shall be: https://PROJECT-ID.REGION.r.appspot.com/sendmail. Replace `PROJECT-ID` and `REGION`, repectively, with the GCP's project ID and the deployment region. + * On Kubernetes, the in-cluster endpoint shall be: http://hugo-mx-gateway.hugo-mx-gateway.svc.cluster.local/sendmail + * On Docker, the endpoint shall be: http://DOCKER-HOST:8080/sendmail. Replace `DOCKER-HOST` with the IP address or the hostname of the Docker machine. + * Edit the **Hugo Markdown content** of the target contact/demo page to ensure that the **tags** parameter holds a appropriate value (i.e. `contact` for a contact form, or `demo` for a demo request form). + +Here is an example of header for a Hugo Markdown page. The `tags` parameter holds a tag named `contact`) meaning that the page will be rendered as a contact request form. + + ``` + --- + title: "Contact Us" + description: "Contact request page" + date: 2020-04-25T00:20:27+02:00 + tags: [contact] + --- + ``` \ No newline at end of file From 3222187fc479cd5b9e203e2942a4c7eb10d5cf4b Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Fri, 29 Apr 2022 11:18:35 +0200 Subject: [PATCH 03/10] cleanup readme --- README.md | 9 --------- docs/sample-of-hugo-dontact-form.md | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/README.md b/README.md index 5e30e52..01306c7 100644 --- a/README.md +++ b/README.md @@ -17,17 +17,8 @@ You're at the right place. This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that adds the dynamicity required to handle contactdemo requests for static web sites. It's a simple, yet a powerful tool built for this only-designated purpose. - ![](hugo-mx-gateway-architecture-overview.png) - -## Hugo-mx-gateway in a Nutshell -`hugo-mx-gateway` provides a RESTful POST endpoint for static contact/demo request pages. It's a simple, yet a powerful tool built for this only-designated purpose. - -> **This project is used in production for several static websites built with [Hugo](https://gohugo.io/); -Contributions in any form (code/docs/ideas...) are welcomed.** - - # Getting Started Use the following resoures to deploy and get started with hugo-mx-gateway. diff --git a/docs/sample-of-hugo-dontact-form.md b/docs/sample-of-hugo-dontact-form.md index e51b153..4cd7a87 100644 --- a/docs/sample-of-hugo-dontact-form.md +++ b/docs/sample-of-hugo-dontact-form.md @@ -3,7 +3,7 @@ From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo. It can be used for both contact and demo requests. -![Screenshot of a successful submission](./screenshots/form-submitted-and-processed-with-success.png) +![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) Open the file in your favorite editor and review it. From 5e32b17b2c43bf359044481cacf777c1cd8f1bcd Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Fri, 29 Apr 2022 11:20:09 +0200 Subject: [PATCH 04/10] updated readme --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 01306c7..fe24e1c 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ --- - [Overview](#overview) - - [Hugo-mx-gateway in a Nutshell](#hugo-mx-gateway-in-a-nutshell) - [Getting Started](#getting-started) - [License & Copyrights](#license--copyrights) - [Support & Contributions](#support--contributions) @@ -23,11 +22,12 @@ This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that a Use the following resoures to deploy and get started with hugo-mx-gateway. * [Deployment on Kubenetes](./docs/deployment-on-kubernetes.md) -* [Deployment on Google Computinf Engine](./docs/deployment-on-kubernetes.md) +* [Deployment on Google Computing Engine](./docs/deployment-on-kubernetes.md) * [Deployment on Docker](./docs/deployment-on-kubernetes.md) * [Deployment on Debian](./docs/deployment-on-debian.md) * [Configuration Variables](./docs/configuration-variables.md) * [Sample of contact form for Hugo](./docs/sample-of-hugo-dontact-form.md) +* [Design Fundamentals](./docs/design-fundamentals.md) # License & Copyrights This tool (code and documentation) is licensed under the terms of Apache 2.0 License. Read the [LICENSE](LICENSE) file for more details on the license terms. From c76adee24fe579167dd15efeed19515b0873747a Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Fri, 29 Apr 2022 11:21:33 +0200 Subject: [PATCH 05/10] upated README --- docs/sample-of-hugo-dontact-form.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/sample-of-hugo-dontact-form.md b/docs/sample-of-hugo-dontact-form.md index 4cd7a87..d52791e 100644 --- a/docs/sample-of-hugo-dontact-form.md +++ b/docs/sample-of-hugo-dontact-form.md @@ -1,9 +1,7 @@ # Sample of contact form for Hugo -From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo. It can be used for both contact and demo requests. - -![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) +From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo (see screenshot below). It can be used for both contact and demo requests. Open the file in your favorite editor and review it. @@ -26,4 +24,7 @@ Here is an example of header for a Hugo Markdown page. The `tags` parameter hold date: 2020-04-25T00:20:27+02:00 tags: [contact] --- - ``` \ No newline at end of file + ``` + + +![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) \ No newline at end of file From 0052f21f2eda712355badbdfb075ef7989c5102a Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Sat, 30 Apr 2022 11:28:26 +0200 Subject: [PATCH 06/10] review README --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fe24e1c..0634ac0 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,16 @@ - [Support & Contributions](#support--contributions) # Overview -Did you ever experience building a static website (e.g. using [Hugo](https://gohugo.io/) or whatever alternative), then did get stuck when coming the time to add a contact/demo request form? +Did you ever experience building a static website (e.g. using [Hugo](https://gohugo.io/)) then got stuck when coming the time to add a contact/demo request form? You're at the right place. -This project, namely `hugo-mx-gateway`, is meant to provide a RESTful API that adds the dynamicity required to handle contactdemo requests for static web sites. It's a simple, yet a powerful tool built for this only-designated purpose. +`hugo-mx-gateway` provides a RESTful API that adds the dynamicity required to handle contact/demo requests for your static websites. It's a simple, yet a powerful tool built for this only-designated purpose. ![](hugo-mx-gateway-architecture-overview.png) # Getting Started -Use the following resoures to deploy and get started with hugo-mx-gateway. +The following resources will enable you to deploy and get started with hugo-mx-gateway. * [Deployment on Kubenetes](./docs/deployment-on-kubernetes.md) * [Deployment on Google Computing Engine](./docs/deployment-on-kubernetes.md) From a14a38ae8979983191b5fdf2803b44d3ebde9d57 Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Sat, 30 Apr 2022 11:47:16 +0200 Subject: [PATCH 07/10] review the description of the sample Hugo form --- README.md | 2 +- docs/sample-contact-form-for-hugo.md | 24 ++++++++++++++++++++++ docs/sample-of-hugo-dontact-form.md | 30 ---------------------------- 3 files changed, 25 insertions(+), 31 deletions(-) create mode 100644 docs/sample-contact-form-for-hugo.md delete mode 100644 docs/sample-of-hugo-dontact-form.md diff --git a/README.md b/README.md index 0634ac0..214d244 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The following resources will enable you to deploy and get started with hugo-mx-g * [Deployment on Docker](./docs/deployment-on-kubernetes.md) * [Deployment on Debian](./docs/deployment-on-debian.md) * [Configuration Variables](./docs/configuration-variables.md) -* [Sample of contact form for Hugo](./docs/sample-of-hugo-dontact-form.md) +* [Sample of contact form for Hugo](./docs/sample-contact-form-for-hugo.md) * [Design Fundamentals](./docs/design-fundamentals.md) # License & Copyrights diff --git a/docs/sample-contact-form-for-hugo.md b/docs/sample-contact-form-for-hugo.md new file mode 100644 index 0000000..d48e0c6 --- /dev/null +++ b/docs/sample-contact-form-for-hugo.md @@ -0,0 +1,24 @@ + +# Sample Contact Form for Hugo + +From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo (a screenshot is provided below). + +> This form can be used for a contact or a demo form. Indeed, as shown in the procedure below, the form is configured to be rendered specifically according to a tag set in the Hugo page content. + +![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) + +## Setup Procedure + +* Copy the HTML form content in your target **Hugo HTML template**. +* Open the file in your favorite editor to update it. +* Modify the `` tag to make the **action** point it your hugo-mx-gateway sendmail backend URL (this URL depends on the deployment option: [Deployment on Kubenetes](./deployment-on-kubernetes.md), [Deployment on Google Computing Engine](./deployment-on-kubernetes.md), [Deployment on Docker](./deployment-on-kubernetes.md), [Deployment on Debian](./deployment-on-debian.md). +* Edit the **Hugo Markdown content** of the target contact/demo page to ensure that the **tags** parameter holds an appropriate value (i.e. `contact` for a contact form, or `demo` for a demo request form). + + ``` + --- + title: "Contact Us" + description: "Contact request page" + date: 2020-04-25T00:20:27+02:00 + tags: [contact] + --- + ``` \ No newline at end of file diff --git a/docs/sample-of-hugo-dontact-form.md b/docs/sample-of-hugo-dontact-form.md deleted file mode 100644 index d52791e..0000000 --- a/docs/sample-of-hugo-dontact-form.md +++ /dev/null @@ -1,30 +0,0 @@ - -# Sample of contact form for Hugo - -From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo (see screenshot below). It can be used for both contact and demo requests. - -Open the file in your favorite editor and review it. - -Notice that the form is configured to be rendered specifically according to a Hugo parameter named **tags**, which is actually a **list of tags**. If the parameter holds a tag named `contact` then, the form will be rendered as a contact form. Otherwise, it'll be rendered as a demo form. - -The integration works as follows: - * Copy the HTML form content in your target **Hugo HTML template**. - * Modify the `` tag to make the **action** point to the URL of the sendmail backend deployed previously. - * On Google App Engine, the endpoint shall be: https://PROJECT-ID.REGION.r.appspot.com/sendmail. Replace `PROJECT-ID` and `REGION`, repectively, with the GCP's project ID and the deployment region. - * On Kubernetes, the in-cluster endpoint shall be: http://hugo-mx-gateway.hugo-mx-gateway.svc.cluster.local/sendmail - * On Docker, the endpoint shall be: http://DOCKER-HOST:8080/sendmail. Replace `DOCKER-HOST` with the IP address or the hostname of the Docker machine. - * Edit the **Hugo Markdown content** of the target contact/demo page to ensure that the **tags** parameter holds a appropriate value (i.e. `contact` for a contact form, or `demo` for a demo request form). - -Here is an example of header for a Hugo Markdown page. The `tags` parameter holds a tag named `contact`) meaning that the page will be rendered as a contact request form. - - ``` - --- - title: "Contact Us" - description: "Contact request page" - date: 2020-04-25T00:20:27+02:00 - tags: [contact] - --- - ``` - - -![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) \ No newline at end of file From 117da635189114f0b5a0fb7af5425dad49cd1c8d Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Sat, 30 Apr 2022 11:52:35 +0200 Subject: [PATCH 08/10] updated sample form --- README.md | 2 +- docs/sample-contact-form-for-hugo.md | 4 ++-- screenshots/sample-hugo-contact-form.png | Bin 0 -> 31135 bytes 3 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 screenshots/sample-hugo-contact-form.png diff --git a/README.md b/README.md index 214d244..8e7aca3 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The following resources will enable you to deploy and get started with hugo-mx-g * [Deployment on Docker](./docs/deployment-on-kubernetes.md) * [Deployment on Debian](./docs/deployment-on-debian.md) * [Configuration Variables](./docs/configuration-variables.md) -* [Sample of contact form for Hugo](./docs/sample-contact-form-for-hugo.md) +* [Sample contact form for Hugo](./docs/sample-contact-form-for-hugo.md) * [Design Fundamentals](./docs/design-fundamentals.md) # License & Copyrights diff --git a/docs/sample-contact-form-for-hugo.md b/docs/sample-contact-form-for-hugo.md index d48e0c6..b31abee 100644 --- a/docs/sample-contact-form-for-hugo.md +++ b/docs/sample-contact-form-for-hugo.md @@ -1,11 +1,11 @@ -# Sample Contact Form for Hugo +# Sample contact form for Hugo From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo (a screenshot is provided below). > This form can be used for a contact or a demo form. Indeed, as shown in the procedure below, the form is configured to be rendered specifically according to a tag set in the Hugo page content. -![Screenshot of a successful submission](../screenshots/form-submitted-and-processed-with-success.png) +![Screenshot of a successful submission](../screenshots/sample-hugo-contact-form.png) ## Setup Procedure diff --git a/screenshots/sample-hugo-contact-form.png b/screenshots/sample-hugo-contact-form.png new file mode 100644 index 0000000000000000000000000000000000000000..3bccf167746ba3a358577892c7a94992f1ec252e GIT binary patch literal 31135 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 Date: Sat, 30 Apr 2022 11:54:10 +0200 Subject: [PATCH 09/10] review contact form --- docs/sample-contact-form-for-hugo.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/sample-contact-form-for-hugo.md b/docs/sample-contact-form-for-hugo.md index b31abee..996a9d4 100644 --- a/docs/sample-contact-form-for-hugo.md +++ b/docs/sample-contact-form-for-hugo.md @@ -1,6 +1,11 @@ # Sample contact form for Hugo +- [Sample contact form for Hugo](#sample-contact-form-for-hugo) + - [Overview](#overview) + - [Setup Procedure](#setup-procedure) + +## Overview From the source tree, the file `samples/hugo-partial-contact-form.html` contains a sample HTML form for Hugo (a screenshot is provided below). > This form can be used for a contact or a demo form. Indeed, as shown in the procedure below, the form is configured to be rendered specifically according to a tag set in the Hugo page content. From 1a3c267b6baebb62f006d48d4eefcfb1aac67412 Mon Sep 17 00:00:00 2001 From: Rodrigue Chakode Date: Sat, 30 Apr 2022 12:04:36 +0200 Subject: [PATCH 10/10] review all docs --- docs/deployment-on-docker.md | 9 ++++----- docs/deployment-on-google-compute-engine.md | 11 ++++++++++- docs/deployment-on-kubernetes.md | 5 +++++ docs/sample-contact-form-for-hugo.md | 1 - 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/deployment-on-docker.md b/docs/deployment-on-docker.md index a2a9cba..e859b55 100644 --- a/docs/deployment-on-docker.md +++ b/docs/deployment-on-docker.md @@ -1,11 +1,10 @@ # Deploying hugo-mx-gateway on Docker +As described in the below procedure, an instance of `hugo-mx-gateway` can be quickly started on any machine running Docker. -An instance of `hugo-mx-gateway` can be quickly started on any machine running Docker. +First review the [configuration variables](./configuration-variables.md). -* Please first review the [configuration variables](#configuration-variables) and adapt them appropriately. - -* Then apply the following command: +Then apply the following command while setting the configuration variables appropriately: ``` docker run -d \ @@ -22,7 +21,7 @@ An instance of `hugo-mx-gateway` can be quickly started on any machine running D rchakode/hugo-mx-gateway ``` -* Check that the container is up and functionning. +Check that the container is up and functionning. ``` curl http://127.0.0.1:8080/ diff --git a/docs/deployment-on-google-compute-engine.md b/docs/deployment-on-google-compute-engine.md index 9dcbe55..516cc26 100644 --- a/docs/deployment-on-google-compute-engine.md +++ b/docs/deployment-on-google-compute-engine.md @@ -1,11 +1,20 @@ # Deploying hugo-mx-gateway on Google App Engine + - [Requirements](#requirements) + - [Setup Procedure](#setup-procedure) -This requires to have an active GCP account and [Google Cloud SDK](https://cloud.google.com/sdk) (gcloud) installed on your work station. +## Requirements +This procedure requires to have: + * an active GCP account. + * [Google Cloud SDK](https://cloud.google.com/sdk) (gcloud) installed and configured on your work station. + * The credentials configured for gcloud must have sufficient permissions to create an App Engine application. + +## Setup Procedure * Create/select a GCP project to deploy `hugo-mx-gateway`. Note that each GCP project can hold only a single App Engine instance. Several applications can be co-hosted as services for the root App Engine instance. In this case, a new application has to be declared as `service` in the `app.yaml` file. + * Create the Google App Engine configuration file ``` cp app.yaml.sample app.yaml diff --git a/docs/deployment-on-kubernetes.md b/docs/deployment-on-kubernetes.md index 075d285..3c84b95 100644 --- a/docs/deployment-on-kubernetes.md +++ b/docs/deployment-on-kubernetes.md @@ -1,9 +1,14 @@ # Deploying hugo-mx-gateway on Kubernetes + - [Overview](#overview) + - [Setup Procedure](#setup-procedure) + +## Overview From the source tree, the folder `./helm/` contains Helm manifest to ease the deployment of hugo-mx-gateway on Kubernetes clusters. > **Important:** The chart is validated with Helm 3 and the pod is run in an unprivileged mode within a **Security Context**. +## Setup Procedure Proceed with the deployment as follows: * First edit the [values.yaml](./helm/values.yaml) file to set [configuration values](#configuration-variables) appropriately. diff --git a/docs/sample-contact-form-for-hugo.md b/docs/sample-contact-form-for-hugo.md index 996a9d4..0a69776 100644 --- a/docs/sample-contact-form-for-hugo.md +++ b/docs/sample-contact-form-for-hugo.md @@ -1,7 +1,6 @@ # Sample contact form for Hugo -- [Sample contact form for Hugo](#sample-contact-form-for-hugo) - [Overview](#overview) - [Setup Procedure](#setup-procedure)