Express Form working in development but not in deployment. I checked all the support guides but nothing is working

Here’s my html form:

<form class="contact-form" action="/" method="POST">
                    <input type="text" id="name" name="name" placeholder="Name" required>
                    <input type="email" name="email" id="email" placeholder="Email" required>
                    <input type="text" name="subject" id="subject" placeholder="Subject" required>
                    <textarea type="textbox" name="message" id="message" placeholder="Your Message" required></textarea>
                    <button class="submit-button" type="submit">Send Message</button>

client side js:

const contactForm = document.querySelector(".contact-form");

const handleSubmit = (e) => {
    let formData = new FormData(contactForm);
    let urlEncodedFormData = new URLSearchParams(formData);

    fetch("/", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: urlEncodedFormData,
        .then((response) => {
            if (response.ok) {
                alert('Email sent');
            } else {
                throw new Error('Request failed with status: ' + response.status);
        .catch((error) => {
            alert('Something went wrong!')

contactForm.addEventListener('submit', handleSubmit);

server side js:

const express = require('express');
const nodemailer = require('nodemailer')
const app = express();

const PORT = process.env.PORT || 5000;

// Middleware
app.use(express.static(__dirname + '/public'));
app.use(express.urlencoded({ extended: true }));

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/public/index.html');

// Add a route to handle /index.html specifically
app.get('/index.html', (req, res) => {
    res.sendFile(__dirname + '/public/index.html');

app.get('/', (req, res) => {
    res.sendFile(__dirname + '/public/contact.html')
})'/', (req, res) => {

    const { name, email, subject, message } = req.body; // Destructure form fields for easier access

    console.log('Name:', name);
    console.log('Email:', email);
    console.log('Subject:', subject);
    console.log('Message:', message);

    const transporter = nodemailer.createTransport({
        service: "gmail",
        auth: {
            user: "",
            pass: 'gmail_app_pass' /*hidden*/

    const mailOptions = {
        from: email,
        to: '',
        subject: `${email}: ${subject}`,
        text: `Message from ${name}: \n ${message}`

    transporter.sendMail(mailOptions, (error, info) => {
        if (error) {
        } else {
            console.log('Email Sent: ' + info.response);

app.listen(PORT, () => {
    console.log(`Server running on port ${PORT}`);

You haven’t explained what isn’t actually working. At what point does it fail?

The contact form works perfectly with “npm run dev” on server 5000 locally. But when deployed on netlify it always throws the error. The network tab shows a 404 status.

What error? Where?

Are you aware that you can’t just run an Express server on Netlify?

If that’s what you’re doing, it’d explain why you’re seeing a 404 as there is no server to handle your request.

You’ll need to ensure that the script that catches and handles your form submission is created as a Serverless Function.

1 Like

Thank you, this helped a lot.