/fire-contact

This repository sends me your lovely messages from my website. Try it now at https://me.anweshan.online 😊.

Primary LanguageJavaScriptMIT LicenseMIT

πŸ”₯ Fire Contact πŸ“§

🀝🏻 Sometimes the perfect person for you is who you least expected to be.

Table of Contents

Introduction

Fire Contact is built to get messages from you. My website is hosted on GitHub, which is basically a static site hosting, with no backend. But a website devoid of a contact form is really in-efficient. Again it is arguably easy to shift to a hosting provider in less than a minute. They provide me with a SQL database, a backend to host my files, a custom dashboard so on and forth. But I really like to stick on to GitHub Pages.

Enter Firebase by Google a product which basically is a backend jamstack only better. It can be accessed from the front-end, is lightweight, easy to learn, and packed with a lot of features other than a database. Most importantly it is built by Google, so it must be good right. You may want to argue that, most (if not all) my projects are open source and I am an open-source fan. So why not use Supabase or any other alternatives. Honestly, I find this product of Google like many other best suited and quick to learn.

My client side code is bootstraped & built by Vite.js with the Vanilla JS flavour.

Proprietary Third Party Stuff

  • πŸ”₯ Google Firebase (code for this is open-source & I have used the firebase/js-sdk)
    • πŸ”’ Authentication ~ Firebase Anonymous Authentication for tracking
    • πŸ—Ί Google Analytics
    • πŸ—„ Cloud Firestore
    • βœ” App Check
    • ☁ Cloud Functions (Soon to be implemented)
  • Google reCAPTCHA
    • Version 2 (v2) ➑ "βœ… I am not a robot"
    • Version 3 (v3) ➑ "πŸ™ˆ Invisible for App Check"

Open Source Stuff

Killer features

  • πŸ”₯ Blazingly fast
  • βš– Extremely Lightweight
  • ⏳ Realtime features
  • πŸ” Standard Verification & Security
  • 🀺 Battle tested

Other features

  • πŸ” Idempotent Messages (No replay attacks)
  • πŸ›‘ Messages sent only by humans
  • 🚦 Protected backend by security rules.
    • πŸ“ Easily scaleable
  • β›” No read access
  • πŸ’³|πŸ”» Low writes & reads keeping cost low
  • ⏳ Scheduled auto-reply

NOTE: You will find a βš™ .env.production file with all the VALUES filled in & then uploaded to the repository. Be assured these values are public facing values and no matter who sees them πŸ‘€, just cannot tamper with these.

Workflow

Client Side workflow

⌨ | 🧼 ➑ πŸ–± ➑ πŸ’ͺ🏻 ➑ πŸ–± ➑ πŸ›‘ ➑ πŸ”₯|πŸ—„ ➑ ⏳ ➑ πŸ“©

πŸ‘†πŸ» The above emojis summarize the workflow. It starts with the user typing ⌨ a message. They intially try to check πŸ•΅πŸ»β€β™‚οΈ & filter 🧼 any profanity from the message, while validating the name, email and the subject. After that it challenges πŸ’ͺ🏻 the user πŸ‘€ to solve the same. The user then submites the solved challenge, which gets verified πŸ›‘ and at the end a document is written to the Cloud Firestore πŸ—„ under the collections "messages" (by default). I deviced a plan to make the message idempotent (no recording/writting more than once), by making the document id (which is basically a PRIMARY KEY in a RELATIONAL DATABASE) the "hash of the token" solved by the user.

The following is the structure of the document written:

{
  "name": "name",
  "email": "example@example.com",
  "subject": "The subject",
  "message": "Your message",
  "replied": false,
  "sentAt": "The general timestamp of your device",
  "token": "The challenge πŸ’ͺ🏻 solved by the user πŸ‘€, now tokenized"
  "uid": "The user id, generated by the anonymous sign in provider"
}

πŸ‘†πŸ» If you look closely replied field is a boolean which is significant for the scheduler, details of which are given below ⬇.

Server Side

The server side is kept very simple. It is an Express.js application having an endpoint /verify. My backend is hosted on Heroku and you will find the code at the server folder in this repository.

Please remeber to setup the required secrets in a βš™ .env file using the example .env.example file. It requires the SITE KEY & SECRET KEY bought found on the dashboard of your reCAPTCHA project. It also requires a PORT (default 3000) which is generally at the dev mode [at production this is proxied to port 443] . You can specify MODE=development to ease in the CORS. To associate these variables (or constants) with your process.env we require the dotenv package.

πŸ“Please remeber that .env file cannot be uploaded to the Heroku instance or any repository unless otherwise it is specifically not exposed to the public. Heroku does not allow .env files to be parsed, so you need to set up an app and goto https://dashboard.heroku.com/apps/[REPLACE App name]/settings and click REVEAL CONFIG VARS and manully set the secrets 🀫.

Speaking of CORS, I have a whitelist of domains which can send requests to the backend for verification. This is done by the CORS Middleware.

πŸ“¦ You can clone the server stuff seperately from fire-contact-server.git.

πŸ‘‡πŸ» One click install:

Deploy

Scheduling ⏳

πŸ’° Please note if use Cloud Functions, you need to have a billing account with Google Cloud.

If you are willing to pay πŸ’³, please check out Cloud Firestore triggers on Cloud Function, which is very efficient.

I have been setting up the Pipedream Scheduling Workflow to go over the task. The scheduling will not immediately trigger a reply-back, but will definitely do it work in 1 - 1.5 hours. Being the server side, the normal Firebase JS SDK won't work. For this we need Firebase Admin SDK for Node.js or any other language.

To prove your identity, generally we would use the OAuth Protocol to authenticate where a access token & refresh token is involved. This is highly realiable on the event the corresponding REST API for Firebase are used. However we authenticate through a service Service Account which can be setup at Service Account on your Firebase Project. Some basic examples to use the same are on this blog post, while the rest is on the docs.

Note: You are not at all required to use the Node.js SDK version for Firebase Admin. Check out other supporting languages & their corresponding libraries.

Conclusion

Thats it 🍻. I am ready to get your messages πŸ’­ and make some new friends πŸ‘₯ while have a nice talk 🦜. Send messages @ https://me.anweshan.online now ...

Built with care, Anweshan Roy Chowdhury (@formula21)