Contact
The contact page allows your users to contact you in case they have any general enquiries. For feature requests and bug reports, your users should ideally use the Feedback widget on your website. For more information about the feedback widget we added in an earlier section of this guide, see the Feedback Widget section on the User Feedback page of this guide.
Channels
On Epic Fantasy Forge, users can directly contact the developer via messenger and email. Older generations may prefer to contact you via email whereas younger generations may prefer instant messaging. So it makes sense to offer both contact options.
Tip
Some websites offer users to contact them via a form. In my opinion forms can make sense in scenarios where it makes sense to gather additional information related to the enquiry, e.g. including a field on the form about the budget when a user requests a project to be completed by you, assuming you are a freelancer or similar.
However for websites like Epic Fantasy Forge where a feedback widget exists and the contact details are only used for general enquiries, a form does not make sense in my opinion.
Messenger
The messenger recommended by this guide is Signal. This messenger does not require you to reveal your phone number to users who wish to get in touch with you. Instead you can generate a username for your account and share this publicly whilst keeping your phone number private.
If you do not have a Signal account yet, start by creating a Signal account and setting it up on your phone. Once your account is ready, proceed with this guide.
Privacy Settings
To ensure your phone number remains private even to your contacts, click on your user icon on the top left corner of the main Signal screen. You should now see the Settings screen. On the Settings screen tap on "Privacy":
Tap on "Phone number":
Ensure the "Nobody" checkbox for the "Who can see my number" section is checked:
Username
Back on the Settings screen, tap on your profile image to get to the Profile page:
If you don't already have a username, create one now. Once you have one it should be visible on the Profile screen. Tap on "QR code or link":
Tap both the "Link" and "Share" icons to retrieve a direct link and an image for your QR code. Copy them to your development machine. We will need these later when creating the Contact page.
The email service recommended by this guide is Proton Mail. This services comes in multiple pricing tiers. The tier recommended by this guide is "Proton Unlimited" for €12.99 per month. Whilst there is a free tier available it does not support using a custom email domain. Using a standard email without a custom domain may appear less professional and trustworthy to users. The "Mail Plus" tier supports custom domains but it does not come with the Proton Drive and Proton Pass. Proton Pass and Proton Drive are recommended for personal use, as your cloud storage and password manager.
Start by creating an account on Proton Mail and subscribing to the "Proton Unlimited" tier. Optionally you may install the Proton Mail desktop and mobile apps.
Custom Domain
When you signed up for Proton Mail you should have already received an email address with the "pm.me" domain. We will now create an email address for our custom domain, e.g. in the case of Epic Fantasy Forge we will create the email address henrik@epicfantasyforge.com.
Start by going to your Proton Mail dashboard and clicking on the "Settings" icon:
Select "All settings":
On the left sidebar, select "Domain names" and click on the "Add domain" button:
Enter your domain name, e.g. epicfantasyforge.com and click "Next":
Enter your Proton Mail password and click "Authenticate":
You will now be presented with a TXT record that you need to add to your DNS records with your domain name registrar:
Go to your domain name registrar, e.g. Cloudflare, and create a TXT record as instructed by Proton Mail. For more information on how to add DNS records in Cloudflare, see the Custom Domain section on the User Facing Documentation page of this guide.
Once you are done creating the TXT record in Cloudflare, go back to the Proton Mail page and click "Add address":
On the page that opens click "Add address":
Enter an email address for your custom domain, e.g. henrik@epicfantasyforge.com, and enter a display name, e.g. Epic Fantasy Forge. Then click "Save address":
Your new email address should now be shown under the "My addresses" list. Next click on "Domain names":
Click "Review":
Now you are presented with a pair of MX records that you need to add to your DNS records with your domain name registrar:
Create the MX records in Cloudflare as instructed by Proton Mail:
Next you are presented with another TXT record that you need to add to your DNS records with your domain name registrar:
Also add this TXT record in Cloudflare as instructed by Proton Mail:
Now you should be presented with three CNAME records that you need to add to your DNS records with your domain name registrar:
Add these CNAME records in Cloudflare as instructed by Proton Mail. The "Proxy status" toggle switch should be off. The DNS record should not be proxied and should be "DNS only".
Now you should be presented with another TXT record that you need to add to your DNS records with your domain name registrar:
Proceed to also add this TXT record in Cloudlfare as instructed by Proton Mail:
Now that all of your DNS records are added to can verify the status of your custom domain. It may take some time for DNS records to propagate so you may have to wait for a few minutes to a few hours until all status badges except the "CATCH_ALL" badge light up green.
Whilst we are waiting for the DNS records to propagate we can configure a catch-all email, in case someone mistypes an email address bound for your domain. Open the "Review" accordion and click "Set catch-all":
Select the email address you created earlier, e.g. in the case of Epic Fantasy Forge "henrik@epicfantasyforge.com":
Enter your Proton Mail password and click "Authenticate":
Your catch-all email should now be enabled. Any emails bound for your domain but with an invalid address will be routed to your configured catch-all email address, e.g. in the case of Epic Fantasy Forge "henrik@epicfantasyforge.com":
After some time all status badges for your custom domain should light up green. Your custom domain email is now ready to be used.
On the left sidebar, click on "Identity and addresses", open the "Edit" accordion beside your custom domain email address and click "Set as default":
Your custom domain email address should now be the default email address:
You can now verify whether sending and receiving emails to/form your custom domain email address is working.
Tests
E2E Test
Before implementing the contact page we will create an E2E test in Qase. Add a new test case to the "Web Exclusive" suite named "Contact":
Integration Tests
There is nothing for us to test at the integration level as the contact page has no logic or any kind of code.
Unit Tests
There is nothing for us to test at the unit level since the contact page has no logic or any kind of code.
Production Code
HTML
The full source code of the Epic Fantasy Forge contact page can be found in the file contact.html.heex.
Contact
Start by creating a new directory named contact
inside the existing directory priv/static/images
. Now copy the Signal QR code you got from the Username section above into the new contact
directory you just created and name the file signal.png
.
Now add the below HTML to the contact.html.heex
file located at lib/epic_fantasy_forge_web/controllers/page_html
:
<div class="relative isolate bg-gray-900">
<div class="mx-auto grid max-w-7xl grid-cols-1 lg:grid-cols-2">
<div class="relative px-6 pb-6 pt-12 sm:pt-16 lg:static lg:px-8 lg:py-24">
<div class="mx-auto max-w-xl lg:mx-0 lg:max-w-lg">
<h2 class="
text-pretty
text-4xl
font-semibold
tracking-tight
text-white
sm:text-5xl">
Get in touch
</h2>
<p class="mt-6 text-lg/8 text-gray-300">
For feature requests and bug reports please use the feedback widget
on the right side of the screen. For all other enquiries please reach
out via Signal or Email.
</p>
<dl class="mt-10 space-y-4 text-base/7 text-gray-300">
<div class="flex gap-x-3 items-center">
<dt class="flex-none">
<span class="sr-only">Location</span>
<svg
class="size-5 fill-[#6366f1]"
viewBox="0 0 384 512"
xmlns="http://www.w3.org/2000/svg"
>
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path d="M48 0C21.5 0 0 21.5 0 48V464c0 26.5 21.5 48 48 48h96V432c0-26.5 21.5-48 48-48s48 21.5 48 48v80h96c26.5 0 48-21.5 48-48V48c0-26.5-21.5-48-48-48H48zM64 240c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V240zm112-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V240c0-8.8 7.2-16 16-16zm80 16c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H272c-8.8 0-16-7.2-16-16V240zM80 96h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H80c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16zm80 16c0-8.8 7.2-16 16-16h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H176c-8.8 0-16-7.2-16-16V112zM272 96h32c8.8 0 16 7.2 16 16v32c0 8.8-7.2 16-16 16H272c-8.8 0-16-7.2-16-16V112c0-8.8 7.2-16 16-16z">
</path>
</svg>
</dt>
<dd class="inline font-semibold text-white">
Location:
<div class="inline font-normal text-gray-300">
Joensuu, Finland 🇫🇮
</div>
</dd>
</div>
<div class="flex gap-x-3 items-center">
<dt class="flex-none">
<span class="sr-only">Signal</span>
<svg
class="size-5 fill-[#6366f1]"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path d="M512 240c0 114.9-114.6 208-256 208c-37.1 0-72.3-6.4-104.1-17.9c-11.9 8.7-31.3 20.6-54.3 30.6C73.6 471.1 44.7 480 16 480c-6.5 0-12.3-3.9-14.8-9.9c-2.5-6-1.1-12.8 3.4-17.4l0 0 0 0 0 0 0 0 .3-.3c.3-.3 .7-.7 1.3-1.4c1.1-1.2 2.8-3.1 4.9-5.7c4.1-5 9.6-12.4 15.2-21.6c10-16.6 19.5-38.4 21.4-62.9C17.7 326.8 0 285.1 0 240C0 125.1 114.6 32 256 32s256 93.1 256 208z">
</path>
</svg>
</dt>
<dd class="inline font-semibold text-white">
Signal:
<a
class="text-indigo-400 hover:text-white"
href="https://signal.me/#eu/Mrx-cXAIDNT2a-LhvRmW399wLbj-OibT0zmUGZ06VGNz2hcUHyRCxpxkIab1yDDH"
>
henrik.1993
</a>
</dd>
</div>
<div class="flex gap-x-3 items-center">
<dt class="flex-none">
<span class="sr-only">Email</span>
<svg
class="size-5 fill-[#6366f1]"
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
>
<!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path d="M48 64C21.5 64 0 85.5 0 112c0 15.1 7.1 29.3 19.2 38.4L236.8 313.6c11.4 8.5 27 8.5 38.4 0L492.8 150.4c12.1-9.1 19.2-23.3 19.2-38.4c0-26.5-21.5-48-48-48H48zM0 176V384c0 35.3 28.7 64 64 64H448c35.3 0 64-28.7 64-64V176L294.4 339.2c-22.8 17.1-54 17.1-76.8 0L0 176z">
</path>
</svg>
</dt>
<dd class="inline font-semibold text-white">
Email:
<a
class="pl-1 text-indigo-400 hover:text-white"
href="mailto:henrik@epicfantasyforge.com"
>
henrik@epicfantasyforge.com
</a>
</dd>
</div>
</dl>
</div>
</div>
<div class="px-6 pt-6 lg:px-8 lg:pt-24 lg:pb-4">
<div class="mx-auto max-w-xl lg:max-w-lg">
<img
class="w-full rounded-2xl object-cover"
src={~p"/images/contact/signal.png"}
alt="Signal"
/>
</div>
</div>
</div>
</div>
Naturally replace the location and contact details with your own location and contact details. With these changes in place your contact page should now look like this:
As the page content does not fill the entire screen height the footer is not at the bottom. This looks a bit ugly. We will now fix that.
Footer
Edit root.html.heex
to include the following classes with the body:
<body class="bg-gray-900 min-h-screen flex flex-col">
Edit website.html.heex
to include the following class in the main element:
<main class="flex-grow">
Now the contact page should look like this:
The footer has moved down to the bottom of the screen.