GVLab

Log Entry

How to start a free backend functions with vercel app and Firebase FunctionsCover

How to start a free backend functions with vercel app and Firebase Functions

Building a static site with Astro and hosting it on Vercel is a dream for performance. It’s fast, lightweight, and costs nothing. But the moment you need a "Contact Us" form, the dream hits a wall. You have no server. You have no backend.

Published

Do you spin up a $5/month DigitalOcean droplet just to send an email? No.

Today, we are going to wire up a Serverless architecture using a Vercel frontend and Firebase Functions backend to handle a contact form with Gmail dispatch and reCAPTCHA security—all for (virtually) free.

The Stack

  • Frontend: Astro (HTML/JS/CSS) hosted on Vercel.

  • Backend: Firebase Cloud Functions (Node.js).

  • Security: Google reCAPTCHA v3.

  • Email: Nodemailer with Gmail App Passwords.


Phase 1: The Firebase Setup (Backend)

First, we need a place to run our logic.

  1. Go to the Firebase Console and create a new project.

  2. Upgrade your project to the Blaze Plan (Pay as you go).

    • Note: Sending emails requires outbound networking, which is locked on the free "Spark" plan. However, the Blaze plan has a massive free tier. Unless you are sending millions of emails, you won't be charged.

  3. Install the Firebase CLI tools locally:

    codeBash

    npm install -g firebase-tools
  4. Initialize your project in a new folder:

    codeBash

    mkdir backend-functions
    cd backend-functions
    firebase login
    firebase init functions

    Select JavaScript when asked.

Phase 2: Coding the Mailer

Navigate to your functions folder. We need a few tools:

codeBash

npm install nodemailer cors axios

Open index.js. We will create a function that validates the reCAPTCHA token and sends the email via Gmail.

Important: You cannot use your standard Gmail password. Go to your Google Account -> Security -> 2-Step Verification -> App Passwords and generate one.

codeJavaScript

const functions = require("firebase-functions");
const nodemailer = require("nodemailer");
const cors = require("cors")({ origin: true });
const axios = require("axios");

// Configure your Gmail transporter
const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: "your-email@gmail.com",
    pass: "your-generated-app-password", // NOT your real password
  },
});

exports.sendContactEmail = functions.https.onRequest((req, res) => {
  cors(req, res, async () => {
    if (req.method !== "POST") {
      return res.status(405).send("Method Not Allowed");
    }

    const { name, email, message, captchaToken } = req.body;

    // 1. Verify reCAPTCHA
    const secretKey = "YOUR_RECAPTCHA_SECRET_KEY";
    const verifyUrl = `https://www.google.com/recaptcha/api/siteverify?secret=${secretKey}&response=${captchaToken}`;

    try {
      const captchaResponse = await axios.post(verifyUrl);
      if (!captchaResponse.data.success) {
        return res.status(400).json({ error: "Bot detected." });
      }

      // 2. Send Email
      const mailOptions = {
        from: "Your Website <your-email@gmail.com>",
        to: "admin@gvlab.com", // Where you want to receive the mail
        subject: `New Message from ${name}`,
        text: `From: ${email}\n\nMessage:\n${message}`,
      };

      await transporter.sendMail(mailOptions);
      return res.status(200).json({ success: true });

    } catch (error) {
      console.error(error);
      return res.status(500).json({ error: "Internal Server Error" });
    }
  });
});

Deploy it:

codeBash

firebase deploy --only functions

Copy the Function URL provided in the terminal.


Phase 3: The Frontend (Astro/Vercel)

Now, let's build the UI. We need to register for Google reCAPTCHA v3 to get a Site Key.

In your Astro project (e.g., src/pages/contact.astro):

codeHtml

---
// src/pages/contact.astro
---
<html lang="en">
<head>
    <title>Contact Us</title>
    <!-- Load reCAPTCHA API -->
    <script src="https://www.google.com/recaptcha/api.js?render=YOUR_SITE_KEY"></script>
</head>
<body>

    <form id="contact-form">
        <input type="text" id="name" placeholder="Name" required />
        <input type="email" id="email" placeholder="Email" required />
        <textarea id="message" placeholder="Message" required></textarea>
        <button type="submit">Send Transmission</button>
    </form>

    <script>
        const form = document.getElementById('contact-form');
        
        form.addEventListener('submit', async (e) => {
            e.preventDefault();
            
            // Execute reCAPTCHA
            grecaptcha.ready(function() {
                grecaptcha.execute('YOUR_SITE_KEY', {action: 'submit'}).then(async function(token) {
                    
                    const data = {
                        name: document.getElementById('name').value,
                        email: document.getElementById('email').value,
                        message: document.getElementById('message').value,
                        captchaToken: token
                    };

                    // Call Firebase Function
                    const response = await fetch('YOUR_FIREBASE_FUNCTION_URL', {
                        method: 'POST',
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(data)
                    });

                    if (response.ok) {
                        alert("Message received.");
                        form.reset();
                    } else {
                        alert("Transmission failed.");
                    }
                });
            });
        });
    </script>
</body>
</html>

Phase 4: Deployment

  1. Push your Astro code to GitHub.

  2. Import the repo into Vercel.

  3. Deploy.

You now have a completely serverless, secured contact form. The Vercel app serves the static assets instantly, and Firebase wakes up only when someone hits "Send," costing you zero server maintenance and practically zero dollars.


Initiate Contact Protocol

Tell us about your idea. GV Lab will respond with a plan.