FastAPI - Beginner to Pro / Project 5 - Full Stack Application

FastAPI Full Stack - JS Implementation

🚀 Adding JavaScript Functionality to Our Full-Stack FastAPI App

In this step, we are connecting our JavaScript files to the application. This allows our:

  • Register page

  • Login page

to function properly by sending data to FastAPI endpoints, handling form submissions, and managing authentication tokens (JWTs).

We’re using Jinja layout to include JavaScript files just like we included CSS files earlier.


📁 Adding JavaScript Files to layout.html

  1. Open layout.html in the templates folder.

  2. Add <script> tags just before the closing </body> tag. This ensures the scripts load after the DOM.

<!-- jQuery Slim -->
<script src="{{ url_for('static', path='js/jquery-slim.js') }}"></script>
<!-- Popper.js -->
<script src="{{ url_for('static', path='js/popper.js') }}"></script>
<!-- Bootstrap JS -->
<script src="{{ url_for('static', path='js/bootstrap.js') }}"></script>
<!-- Base JS (custom app JS) -->
<script src="{{ url_for('static', path='js/base.js') }}" defer></script>

✅ Notes:

  • defer ensures base.js runs last, after the DOM is loaded.

  • base.js relies on element IDs (like registerForm or loginForm) to exist before running.


📌 How the JavaScript Works

1. Register Form

In base.js, we have:

const registerForm = document.getElementById("registerForm");
if (registerForm) {
    registerForm.addEventListener("submit", async (e) => {
        e.preventDefault();
        // Check if passwords match
        if (password.value !== password2.value) {
            alert("Passwords do not match!");
            return;
        }

        const payload = {
            email: data.email,
            username: data.username,
            first_name: data.first_name,
            last_name: data.last_name,
            role: data.role,
            phone_number: data.phone_number,
            password: data.password
            };

        const response = await fetch("/auth/register", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload)
        });

        if (response.ok) {
            window.location.href = "/auth/login-page"; // Redirect to login page
        } else {
            alert("Registration failed!");
        }
    });
}
  • Checks passwords match before sending data.

  • Creates a JSON payload for the FastAPI /auth/register endpoint.

  • Redirects to login page on success.

2. Login Form

Similarly, for login:

const loginForm = document.getElementById("loginForm");
if (loginForm) {
    loginForm.addEventListener("submit", async (e) => {
        e.preventDefault();

        const payload = {
            username: username.value,
            password: password.value
        };

        const response = await fetch("/auth/login", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(payload)
        });

        if (response.ok) {
            const data = await response.json();
            document.cookie = `access_token=${data.access_token}; path=/`;
            window.location.href = "/todos/todo-page"; // Redirect after login
        } else {
            alert("Login failed!");
        }
    });
}
  • Receives JWT token from FastAPI.

  • Stores token in browser cookies for authenticated requests.

  • Redirects to the feature page (/todos/todo-page).


🔑 Important Notes

  1. Delete existing tokens before testing repeatedly:

    • Go to DevTools → Application → Cookies → Delete access_token

    • Prevents conflicts with old or expired tokens.

  2. The /todos/todo-page route doesn’t exist yet – this is the next step in building our full-stack app.

  3. JavaScript ensures the frontend communicates with FastAPI securely and efficiently.


✅ Summary

By adding JavaScript:

  • Forms now send data to FastAPI endpoints.

  • Password validation occurs on the client side.

  • JWT tokens are stored as cookies for authenticated API calls.

  • The layout template ensures scripts load consistently across pages.

With this setup, the login and registration pages are now fully functional on the frontend, ready to interact with the backend.

Next, we’ll implement the To-Do page, where users can add, edit, and view tasks—completing our full-stack FastAPI application.