Next.js App Form Won't Submit

When I try to submit the form to add a book, control doesn’t reach the submission handler. I want it to submit the form so that the book would be added.

I have a Windows 10 Acer laptop, and I’m using Next.js 15 with Node.js version v22.12.0. My project configuration looks like this;
middleware.ts:

import { clerkMiddleware, ClerkMiddlewareAuth, createRouteMatcher } from "@clerk/nextjs/server";
import { NextRequest } from "next/server";

const isPublicRoute = createRouteMatcher([
  "/api/auth/sign-in(.*)",
  "/api/auth/sign-up(.*)",
  "/api/webhooks(.*)"
]);

export default clerkMiddleware(async (auth: ClerkMiddlewareAuth, req: NextRequest) => {
  if (!isPublicRoute(req)) {
    await auth.protect();
  }
});

export const config = {
  matcher: [
    // Skip Next.js internals and all static files, unless found in search params
    "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",
    // Always run for API routes
    "/(api|trpc)(.*)"
  ]
};

next.config.ts:

import type { NextConfig } from "next";

const nextConfig: NextConfig = {
  reactStrictMode: true,
  basePath: "",
  experimental: {
    turbo: {
      resolveExtensions: [
        ".tsx",
        ".ts",
        ".js",
        ".jsx",
        ".json",
        ".mdx"
      ]
    }
  }
};

export default nextConfig;

postcss.config.mjs:

/** @type {import('postcss-load-config').Config} */
const config = {
  plugins: {
    tailwindcss: {}
  }
};

export default config;

package.json:

{
  "name": "personal-library",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev --turbopack",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@clerk/nextjs": "^6.9.6",
    "@emotion/react": "^11.13.3",
    "@emotion/styled": "^11.13.0",
    "@fontsource/roboto": "^5.1.0",
    "@react-email/components": "^0.0.28",
    "@testing-library/react": "^16.2.0",
    "@types/nodemailer": "^6.4.17",
    "bcryptjs": "^2.4.3",
    "daisyui": "^4.12.23",
    "eslint-plugin-jsx-a11y": "^6.10.2",
    "formik": "^2.4.6",
    "google-books-search": "^0.3.1",
    "mysql": "^2.18.1",
    "mysql2": "^3.12.0",
    "next": "^15.1.7",
    "nodemailer": "^6.9.16",
    "react": "^18.3.1",
    "react-dom": "^18.3.1",
    "react-email": "^3.0.2",
    "react-icons": "^5.4.0",
    "svix": "^1.45.1",
    "uuid": "^11.0.3",
    "zod": "^3.23.8",
    "zod-formik-adapter": "^1.3.0"
  },
  "devDependencies": {
    "@types/bcrypt": "^5.0.2",
    "@types/bcryptjs": "^2.4.6",
    "@types/jest": "^29.5.14",
    "@types/mysql": "^2.15.26",
    "@types/node": "^20",
    "@types/react": "^18",
    "@types/react-dom": "^18",
    "@types/testing-library__jest-dom": "^5.14.9",
    "autoprefixer": "^10.4.20",
    "dotenv": "^16.4.5",
    "eslint": "^9.20.1",
    "eslint-config-next": "15.0.2",
    "eslint-plugin-next": "^0.0.0",
    "eslint-plugin-react": "^7.37.2",
    "eslint-plugin-react-hooks": "^5.0.0",
    "jest": "^29.7.0",
    "postcss": "^8",
    "tailwindcss": "^3.4.1",
    "ts-jest": "^29.2.5",
    "typescript": "^5"
  }
}

My code is on GitHub here. Take a look at the /src/app/api/books/add-book/route.ts and /src/app/books/add-book/page.tsx files.

I also have this error during deployment:

at <unknown> (.next/server/app/api/webhooks/route.js:11:1032742)
at Object.<anonymous> (.next/server/app/api/webhooks/route.js:11:1032791) {
code: 'ECONNREFUSED',
errno: -111,
sqlState: undefined
}

This is my .sql file (I’m using MySQL):

CREATE DATABASE IF NOT EXISTS library_db;
USE library_db;

CREATE TABLE IF NOT EXISTS users (
  id VARCHAR(255) NOT NULL PRIMARY KEY,
  firstName VARCHAR(255),
  lastName VARCHAR(255),
  passwordEnabled BOOLEAN,
  primaryEmailAddress VARCHAR(255),
  emailAddresses JSON,
  createdAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  updatedAt TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  libraryId VARCHAR(255),
  externalAccounts JSON,
  verifiedExternalAccounts JSON,
  web3Wallets JSON,
  primaryWeb3Wallet JSON,
  FOREIGN KEY (library_id) REFERENCES library(id)
);

CREATE TABLE IF NOT EXISTS library (
  id VARCHAR(255) NOT NULL PRIMARY KEY,
  userId VARCHAR(255),
  books JSON,
  FOREIGN KEY (user_id) REFERENCES user(id),
);

And I have this for my database configuration file:

import mysql from "mysql2/promise";

const connection = mysql.createConnection({
  host: process.env.NODE_ENV === "production" ?
    process.env.DB_HOST_PROD :
    process.env.DB_HOST_DEV
  ,
  port: Number(process.env.DB_PORT),
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
  database: process.env.DB_NAME
});

export default connection;

Any help is appreciated. Thanks in advance.

Hi, Osman! :wave:

I asked v0 for any ideas on your issue, and these are the troubleshooting steps it gave me → Next.js 15 Form Submission issue – v0 by Vercel

Let us know how you get on!

Thanks for the help so far. The Connection Refused problem seems to be because I haven’t properly deployed the MySQL database. If I Dockerize it and host the container, that’ll work, right? But I need a free hosting option. If I can’t find a good one, I’ll have to ditch SQL and switch MongoDB Atlas instead.