Hello! Welcome back to our project.
In the last lesson, you brought the user interface to life by writing JavaScript to handle tab switching. Now, when you click between "Summarize" and "Correct Grammar," the correct content panel appears. However, the application doesn't do anything yet. The submit buttons are just for show, and the text area is not connected to our powerful backend.
Today, we're going to bridge that gap. This lesson is all about fulfilling the learning outcome: Connect the frontend controls to the different backend endpoints for each feature. We will write the JavaScript code to take the user's text, send it to the correct Flask API endpoint you built earlier, receive the response, and display the result on the page. This is where your application truly becomes functional.
The Communication Flow: From Browser to Server
Before we write any code, let's visualize the process. When a user clicks a button like "Get Summary," a few things need to happen in sequence:
- Client (Browser): Your JavaScript code grabs the text from the main input area.
- Client (Browser): It packages this text into a
POSTrequest and sends it to a specific URL on your Flask server (e.g.,/summarize). We use aPOSTrequest because we are sending data to the server for processing. - Server (Flask): Your Flask endpoint receives the request, extracts the text, and performs the requested action (like calling the Gemini API).
- Server (Flask): After getting the result, the Flask endpoint packages it into a JSON response and sends it back to the browser.
- Client (Browser): Your JavaScript receives this response, unpacks the JSON, and updates the webpage to display the result to the user.
This client-server communication is the backbone of all modern web applications. The tool we use in JavaScript to manage these network requests is the fetch API.

Sending Data with the fetch API
To send the user's text to our backend, we will listen for a 'click' on the submit button. In that event, we will construct and send our fetch request.
Let's start by focusing on the "Summarize" feature. We'll need to write JavaScript that:
- Selects the main text area, the "Summarize" button, and the result area.
- Adds a click listener to the button.
- Inside the listener, constructs and sends the
fetchrequest. - Handles the response.
The following video provides a clear walkthrough of this exact process, showing how to connect a form to a Flask backend.
Flask & the Fetch API (AJAX?) - Python on the web - Learning Flask Series Pt. 10
The video 'Flask & the Fetch API' by Julian Nash demonstrates the core mechanics of sending data from the frontend to a Flask backend. We will focus on the JavaScript part that constructs the fetch request.
Please watch from 10:23 to 13:33. Pay close attention to the structure of the fetch() call. Notice the key parts: The URL of the backend endpoint. The method: 'POST' option. The headers: { 'Content-Type': 'application/json' } which tells the server we're sending JSON data. The body: JSON.stringify(entry) which packages our JavaScript object into a JSON string to be sent.
Implementing the "Summarize" Feature
Now, let's apply those concepts to our script.js file. We will use the modern async/await syntax, which makes handling asynchronous operations like network requests cleaner and easier to read.
First, let's assume your index.html has these elements for the summary feature:
<!-- Main text input for the user -->
<textarea id="main-text-input" placeholder="Enter your text here..."></textarea>
<!-- ... your tab buttons ... -->
<!-- The content for the 'Summarize' tab -->
<div id="summary" class="tab-content active">
<h3>Summarize Text</h3>
<button id="submit-summary">Get Summary</button>
<div class="result-box" id="summary-result">
<!-- The summary from the AI will appear here -->
</div>
</div>
<!-- ... other tab content ... -->
Now, open your script.js file and add the following code inside the DOMContentLoaded event listener, right after the setupTabs() call.
document.addEventListener('DOMContentLoaded', () => {
setupTabs();
// --- NEW CODE STARTS HERE ---
// 1. Select the necessary elements
const mainTextInput = document.getElementById('main-text-input');
const submitSummaryBtn = document.getElementById('submit-summary');
const summaryResultDiv = document.getElementById('summary-result');
// 2. Add a click event listener to the summary button
submitSummaryBtn.addEventListener('click', async () => {
const textToSummarize = mainTextInput.value;
// Basic validation: Do nothing if the input is empty
if (!textToSummarize.trim()) {
summaryResultDiv.textContent = 'Please enter some text to summarize.';
return;
}
// 3. Prepare and send the fetch request
try {
const response = await fetch('/summarize', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: textToSummarize }),
});
// 4. Handle the response from the server
if (response.ok) {
const data = await response.json();
summaryResultDiv.textContent = data.summary; // Assuming the backend returns { "summary": "..." }
} else {
// Handle server errors (e.g., 500 Internal Server Error)
const errorData = await response.json();
summaryResultDiv.textContent = `Error: ${errorData.error || 'Something went wrong.'}`;
}
} catch (error) {
// Handle network errors (e.g., server is down)
console.error('Fetch error:', error);
summaryResultDiv.textContent = 'A network error occurred. Please check your connection.';
}
});
});
Let's break down this fetch call. This is what it looks like "under the hood" in your browser's developer tools:

For a handy reference, the following article provides very clear, minimal examples of fetch POST requests.
Fetch - HTTP POST Request Examples
The article 'Fetch - HTTP POST Request Examples' from Jason Watmore's Blog is a great cheatsheet for the fetch API. It shows the two main ways to write requests.
Review the first two code blocks: 'Simple POST request with a JSON body' (using .then()) and 'POST request using fetch with async/await'. Our code uses the async/await pattern, which is generally preferred for its readability.
Test your understanding!
Now it's your turn. Based on the code for the "Summarize" feature, how would you write the JavaScript to connect the "Correct Grammar" feature?
Assume your HTML for the grammar tab looks like this:
<div id="grammar" class="tab-content">
<h3>Correct Grammar</h3>
<button id="submit-grammar">Correct Grammar</button>
<div class="result-box" id="grammar-result"></div>
</div>
And your Flask endpoint is at /correct-grammar. Write the addEventListener block for the submit-grammar button.
Show answer
Your code should look very similar to the summary example, just with different element IDs and a different fetch URL.
// Select the grammar-specific elements
const submitGrammarBtn = document.getElementById('submit-grammar');
const grammarResultDiv = document.getElementById('grammar-result');
// Add a click listener to the grammar button
submitGrammarBtn.addEventListener('click', async () => {
const textToCorrect = mainTextInput.value; // Reusing the main text input
if (!textToCorrect.trim()) {
grammarResultDiv.textContent = 'Please enter some text to correct.';
return;
}
try {
const response = await fetch('/correct-grammar', { // <-- Changed URL
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ text: textToCorrect }),
});
if (response.ok) {
const data = await response.json();
grammarResultDiv.textContent = data.corrected_text; // Assuming this key from the backend
} else {
const errorData = await response.json();
grammarResultDiv.textContent = `Error: ${errorData.error || 'Something went wrong.'}`;
}
} catch (error) {
console.error('Fetch error:', error);
grammarResultDiv.textContent = 'A network error occurred. Please check your connection.';
}
});
This pattern of identifying elements, adding a listener, and making a targeted fetch call is fundamental to connecting a multi-featured frontend to its backend.
Conclusion
Excellent work today! You have successfully connected your frontend controls to your backend API endpoints. This is a massive milestone in your project. The application is no longer just a static page; it's an interactive tool that can process user input and deliver results.
Key Takeaways:
- The
fetchAPI is the standard JavaScript tool for making network requests to a server. POSTrequests are used to send data to a server for processing or creation.- The
bodyof the request must be converted to a string usingJSON.stringify(). - The
Content-Type: 'application/json'header is crucial for telling the Flask server how to interpret the body. - Using
async/awaitwith atry...catchblock provides a clean and robust way to handle both successful responses and potential network/server errors.
In our next lesson, we'll start polishing the user experience. We will add a simple but highly effective feature: a "copy to clipboard" button for the AI-generated results, making your application more convenient to use.