2425 words
12 minutes
How i built my first full-stack app with react and flask in under 5 days

Building a Full-Stack App with React and Flask in Under 5 Days#

Developing a functional full-stack web application quickly is a common objective for developers seeking to build prototypes, Minimum Viable Products (MVPs), or learn by doing. Combining React for the frontend and Flask for the backend offers a powerful and efficient path to achieve this, even within a tight timeframe like five days. This pairing leverages React’s robust component model for dynamic user interfaces and Flask’s lightweight nature and Python’s simplicity for server-side logic.

A full-stack application involves both the frontend and the backend. The frontend is the user interface that runs in the user’s browser, handling presentation and user interactions. The backend runs on a server, managing application logic, data storage, and communication with the frontend. An API (Application Programming Interface) acts as the intermediary, allowing the frontend and backend to exchange information, typically using protocols like REST.

Essential Concepts for Rapid Development#

Successfully building an application rapidly requires a solid understanding of core concepts and a focused approach.

  • Frontend (React):
    • Components: Reusable building blocks of the UI.
    • JSX: A syntax extension for JavaScript that looks like HTML.
    • State: Data that components manage and that influences their rendering. Changes in state trigger UI updates.
    • Props: Data passed from parent components to child components.
    • Component Lifecycle/Hooks: Managing side effects and component behavior over time (e.g., useState, useEffect).
  • Backend (Flask):
    • Routes: URLs that the server responds to (e.g., /api/tasks).
    • Views (Request Handlers): Functions that execute when a route is accessed.
    • Request and Response Objects: Handling incoming data from the frontend and sending data back.
    • Templates (Optional but useful): Rendering HTML on the server side (less common when building an API for a separate React frontend).
    • Database Interaction: Storing and retrieving application data (e.g., using an ORM like SQLAlchemy with a database like SQLite).
  • API (REST):
    • Endpoints: Specific URLs that represent resources (e.g., /api/tasks).
    • HTTP Methods: Verbs like GET (retrieve data), POST (create data), PUT (update data), DELETE (remove data).
    • Data Format: Typically JSON for data exchange between frontend and backend.

Why React and Flask for Speed?#

The combination of React and Flask is well-suited for rapid prototyping due to several factors:

  • Python’s Simplicity and Flask’s Minimalism: Python is known for its clear syntax, enabling faster backend development. Flask is a microframework, providing essential tools without imposing strict structures, allowing developers to build what is needed quickly.
  • React’s Component-Based Architecture: Breaking down the UI into reusable components accelerates frontend development. The declarative nature of React makes managing complex UIs more predictable.
  • Large Ecosystems and Communities: Both technologies have extensive libraries, tools, and active communities, providing readily available solutions and support for common challenges.
  • Clear Separation of Concerns: The frontend and backend are distinct, allowing for independent development and clear boundaries defined by the API.

While five days is a tight deadline, focusing on core features and leveraging these tools makes building a functional MVP feasible. The key is strict scope management.

The 5-Day Challenge Mindset: Scope Management#

Building a full-featured, production-ready application in five days is unrealistic. The goal is a functional prototype or MVP demonstrating core functionality. This requires:

  • Defining a Narrow Scope: Identify the absolute minimum features required to solve the problem or demonstrate the concept. Avoid complex features like user authentication, elaborate styling, real-time updates, or extensive error handling initially.
  • Prioritizing Core Logic: Focus on the main data flow and interactions between the frontend and backend.
  • Leveraging Libraries: Do not reinvent the wheel. Use established libraries for tasks like database interaction, API handling, and basic UI components.
  • Accepting Imperfection: The application will likely lack polish, advanced features, and robust error handling. These can be added later.

A simple application idea suitable for a 5-day build might be a basic “To-Do List” application, a simple note-taking app, or a product catalog viewer.

Project Planning and Setup (Day 0/Preparation)#

Before coding begins, dedicate time to planning and environment setup.

  1. Define Core Features: Clearly list the essential functionalities. Example: A To-Do app needs to: view tasks, add a task, mark a task as complete, delete a task.
  2. Sketch Data Model: Outline the structure of the data to be stored. Example: A Task needs an id, title, and completed status.
  3. Design Basic API Endpoints: Define the necessary API routes and methods. Example: GET /api/tasks, POST /api/tasks, PUT /api/tasks/<id>, DELETE /api/tasks/<id>.
  4. Set Up Development Environment:
    • Install Python and Node.js.
    • Set up a virtual environment for the Python project (venv).
    • Create project directories (frontend, backend).
    • Initialize React app (npx create-react-app frontend or npm init vite frontend).
    • Install Flask and necessary libraries (pip install Flask Flask-SQLAlchemy Flask-CORS).
    • Install frontend dependencies (npm install axios or similar for API calls).

Step-by-Step Build Process (Days 1-5)#

This outlines a potential workflow for a simple application.

Day 1: Environment & Basic Structure#

  • Backend Setup:
    • Create backend/app.py.
    • Set up a basic Flask app instance.
    • Configure a simple route (e.g., / or /api/hello) to return a JSON response ({"message": "Hello from Flask!"}).
    • Run the Flask development server to verify it works.
    • Add Flask-CORS to handle cross-origin requests from the frontend during development: CORS(app).
backend/app.py
from flask import Flask, jsonify
from flask_cors import CORS
app = Flask(__name__)
CORS(app) # Enable CORS for all origins in development
@app.route('/api/hello')
def hello():
return jsonify(message="Hello from Flask!")
if __name__ == '__main__':
app.run(debug=True)
  • Frontend Setup:
    • Navigate into the frontend directory.
    • Start the React development server (npm start or npm run dev).
    • Clean up the default boilerplate in src/App.js and src/index.js to display a simple message like “React App Started.”

Day 2: Backend Logic & Data Storage#

  • Database Setup:
    • Configure Flask-SQLAlchemy to use an SQLite database (sqlite:///app.db).
    • Define the data model based on the planning phase (e.g., a Task model).
# backend/app.py (additions)
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///app.db'
db = SQLAlchemy(app)
class Task(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(80), nullable=False)
completed = db.Column(db.Boolean, default=False)
def to_dict(self):
return {
'id': self.id,
'title': self.title,
'completed': self.completed
}
# Create database tables (can be done in a separate script or interactively)
# Example:
# with app.app_context():
# db.create_all()
  • API Endpoint Implementation:
    • Implement the planned API routes (/api/tasks).
    • Write view functions to handle GET (retrieve all tasks), POST (create a new task).
    • Use Flask’s request object to get data from the frontend for POST requests.
    • Use SQLAlchemy to interact with the database (add, query).
    • Return data as JSON using jsonify.
# backend/app.py (additions)
from flask import request
@app.route('/api/tasks', methods=['GET', 'POST'])
def tasks_api():
if request.method == 'GET':
tasks = Task.query.all()
return jsonify([task.to_dict() for task in tasks])
elif request.method == 'POST':
data = request.get_json()
new_task = Task(title=data['title'])
db.session.add(new_task)
db.session.commit()
return jsonify(new_task.to_dict()), 201 # 201 Created

Day 3: Frontend UI Development#

  • Component Structure:
    • Create basic React components (e.g., TaskList.js, TaskItem.js, AddTaskForm.js) in src/components.
    • Design the structure of App.js to hold the main state (list of tasks) and render the other components.
  • Rendering and State:
    • In App.js, use useState to manage the list of tasks.
    • Render the TaskList component, passing the tasks list as props.
    • Render the AddTaskForm component.
    • In TaskList, map over the tasks list and render a TaskItem for each task.
    • In TaskItem, display the task title and completion status.
    • In AddTaskForm, use useState for input fields and handle form submission (initially just logging data).
frontend/src/App.js
import React, { useState } from 'react';
import TaskList from './components/TaskList';
import AddTaskForm from './components/AddTaskForm';
function App() {
const [tasks, setTasks] = useState([]);
const handleAddTask = (newTask) => {
// Will later involve API call
console.log("Adding task:", newTask);
// For now, simulate adding locally
setTasks([...tasks, { id: Date.now(), title: newTask.title, completed: false }]);
};
return (
<div>
<h1>Simple To-Do App</h1>
<AddTaskForm onAddTask={handleAddTask} />
<TaskList tasks={tasks} />
</div>
);
}
export default App;
// frontend/src/components/AddTaskForm.js
import React, { useState } from 'react';
function AddTaskForm({ onAddTask }) {
const [title, setTitle] = useState('');
const handleSubmit = (e) => {
e.preventDefault();
if (!title.trim()) return;
onAddTask({ title: title });
setTitle('');
};
return (
<form onSubmit={handleSubmit}>
<input
type="text"
value={title}
onChange={(e) => setTitle(e.target.value)}
placeholder="New task title"
/>
<button type="submit">Add Task</button>
</form>
);
}
export default AddTaskForm;
// frontend/src/components/TaskList.js
import React from 'react';
import TaskItem from './TaskItem';
function TaskList({ tasks }) {
return (
<ul>
{tasks.map(task => (
<TaskItem key={task.id} task={task} />
))}
</ul>
);
}
export default TaskList;
// frontend/src/components/TaskItem.js
import React from 'react';
function TaskItem({ task }) {
return (
<li>
{task.title} - {task.completed ? 'Done' : 'Pending'}
{/* Add buttons for complete/delete later */}
</li>
);
}
export default TaskItem;

Day 4: Connecting Frontend & Backend#

  • API Integration (Frontend):
    • Use fetch or axios to make HTTP requests from React components to the Flask backend.
    • In App.js, use useEffect to fetch the initial list of tasks when the component mounts.
    • Modify the handleAddTask function in App.js to send a POST request to the backend API. Update the state with the response from the backend (which should include the generated ID).
// frontend/src/App.js (modifications)
import React, { useState, useEffect } from 'react';
import axios from 'axios'; // or use fetch
import TaskList from './components/TaskList';
import AddTaskForm from './components/AddTaskForm';
const API_URL = 'http://127.0.0.1:5000/api/tasks'; // Assuming Flask runs on 5000
function App() {
const [tasks, setTasks] = useState([]);
useEffect(() => {
// Fetch tasks from backend on component mount
axios.get(API_URL)
.then(response => {
setTasks(response.data);
})
.catch(error => {
console.error("Error fetching tasks:", error);
});
}, []); // Empty dependency array means this runs once on mount
const handleAddTask = (newTask) => {
axios.post(API_URL, newTask)
.then(response => {
// Add the new task (with ID from backend) to state
setTasks([...tasks, response.data]);
})
.catch(error => {
console.error("Error adding task:", error);
});
};
// Add handlers for completing/deleting tasks later
const handleCompleteTask = (id) => { /* ... API call to PUT /api/tasks/<id> ... */ };
const handleDeleteTask = (id) => { /* ... API call to DELETE /api/tasks/<id> ... */ };
return (
<div>
<h1>Simple To-Do App</h1>
<AddTaskForm onAddTask={handleAddTask} />
{/* Pass handlers down to TaskList/TaskItem */}
<TaskList tasks={tasks} onCompleteTask={handleCompleteTask} onDeleteTask={handleDeleteTask} />
</div>
);
}
export default App;
  • Implement Additional Backend Endpoints:
    • Add routes for PUT (update task) and DELETE (delete task) with dynamic URL parameters (<int:id>).
    • Implement the view functions to find the task by ID, update/delete it using SQLAlchemy, and commit changes. Return appropriate responses (e.g., updated task data, success message, error).
# backend/app.py (additions)
@app.route('/api/tasks/<int:task_id>', methods=['PUT', 'DELETE'])
def task_detail_api(task_id):
task = Task.query.get_or_404(task_id)
if request.method == 'PUT':
data = request.get_json()
if 'title' in data:
task.title = data['title']
if 'completed' in data:
task.completed = data['completed']
db.session.commit()
return jsonify(task.to_dict())
elif request.method == 'DELETE':
db.session.delete(task)
db.session.commit()
return jsonify(message="Task deleted successfully")
  • Implement Update/Delete Logic (Frontend):
    • Add buttons/interaction elements to TaskItem for completing/deleting.
    • Pass the corresponding handler functions (handleCompleteTask, handleDeleteTask) down from App.js through TaskList to TaskItem.
    • In TaskItem, call these handlers when buttons are clicked, passing the task’s ID.
    • In App.js, implement handleCompleteTask and handleDeleteTask to make PUT and DELETE API calls respectively and update the frontend state (setTasks) based on the backend response.

Day 5: Polishing, Testing, & Deployment Prep#

  • Basic Styling: Add minimal CSS to make the application presentable. Use inline styles, a CSS file, or a simple library like Bootstrap or Tailwind CSS if time permits (but keep it basic).
  • Basic Error Handling: Add simple .catch() blocks to API calls on the frontend to log errors to the console. Add basic validation on the backend (e.g., checking if required fields are present in incoming JSON).
  • Testing: Manually test all core functionalities: adding, viewing, marking complete, deleting. Check browser developer tools for any frontend or backend errors.
  • Code Cleanup: Remove unused code, add comments where necessary.
  • Deployment Preparation:
    • Build the React frontend for production (npm run build). This creates static files in a build directory.
    • Decide on a deployment strategy. Options include:
      • Deploying Flask and serving the React build directory from Flask.
      • Deploying Flask as an API service and deploying the React build to a static hosting service (like Netlify, Vercel, GitHub Pages).
    • Ensure necessary configuration for production (e.g., environment variables for database connection strings, potentially disabling debug mode). For simple apps, an SQLite database might be sufficient initially.

Challenges and Solutions#

Building quickly inevitably introduces challenges:

  • CORS Issues: Frontend and backend running on different ports/domains during development can cause security errors. Solution: Use Flask-CORS on the backend during development.
  • Asynchronous Data Handling: Managing state updates in React based on asynchronous API calls requires careful use of useEffect, useState, and promise handling (.then(), .catch(), async/await). Solution: Practice with async patterns, use browser developer tools (Network tab) to inspect API calls.
  • State Management Complexity: As the app grows, managing state across many components can become difficult. Solution: For a 5-day app, keep state management simple, primarily in the top-level App component, passing data and functions via props. Avoid complex state management libraries unless absolutely necessary.
  • Debugging: Pinpointing errors between the frontend and backend requires checking both sides. Solution: Use browser developer tools (Console, Network, Components tabs) for the frontend and server logs/print statements for the backend.
  • Scope Creep: The desire to add “just one more feature.” Solution: Stick ruthlessly to the initial defined core features. Defer all non-essential ideas.

Case Study: Simple Task Manager#

Consider the example of building a simple task manager application:

  • Goal: Allow users to view, add, and delete tasks.
  • Day 0: Defined scope (view, add, delete), sketched Task model (id, title, completed), planned API endpoints (GET /api/tasks, POST /api/tasks, DELETE /api/tasks/<id>). Set up project directories and virtual environments.
  • Day 1: Installed dependencies, created basic app.py and App.js with “Hello” messages, configured CORS.
  • Day 2: Added SQLAlchemy, defined Task model, created tasks_api route for GET and POST, implemented logic to fetch tasks and create new ones, saving to app.db.
  • Day 3: Created TaskList, TaskItem, and AddTaskForm components in React, structured App.js to hold task state and render components. Tasks were initially hardcoded or simulated.
  • Day 4: Integrated axios. useEffect was added to fetch tasks on load. handleAddTask was updated to send POST requests. task_detail_api route was added in Flask for DELETE. handleDeleteTask was implemented in React to send DELETE requests and update state. (Adding ‘complete’ functionality might be deferred if time is extremely tight, or added as a stretch goal).
  • Day 5: Added minimal CSS for list items and form. Added basic validation for task title in the backend POST request. Tested add and delete functionality. Built the React app and considered deployment options.

This focused approach allowed the core functionality to be implemented within the timeframe, resulting in a working application, albeit basic.

Key Takeaways and Actionable Insights#

  • Prioritize Scope: Ruthlessly define and stick to the absolute minimum core features required for an MVP or prototype.
  • Plan Ahead: Spend a few hours planning the data model and API endpoints before writing code.
  • Leverage Frameworks and Libraries: React and Flask provide structure and tools; SQLAlchemy, Flask-CORS, and Axios/Fetch handle common tasks efficiently.
  • Understand Data Flow: Be clear on how data moves between the frontend (React state, user input), through API calls, to the backend (Flask routes, database interaction), and back again.
  • Iterate Quickly: Build one feature at a time, testing as you go.
  • Don’t Aim for Perfection: A functional, albeit unpolished, application is the goal within a 5-day timeframe. Refinement comes later.
  • Master Debugging Tools: Proficiency with browser developer tools and server logs is crucial for identifying and fixing issues rapidly.

Building a full-stack application with React and Flask in under five days is an ambitious but achievable goal with strict focus and efficient use of tools. It demonstrates core web development concepts and provides a solid foundation for future development and learning.

How i built my first full-stack app with react and flask in under 5 days
https://dev-resources.site/posts/how-i-built-my-first-fullstack-app-with-react-and-flask-in-under-5-days/
Author
Dev-Resources
Published at
2025-06-26
License
CC BY-NC-SA 4.0