Flask Basics: Your First Web App

· 3 min read · Updated March 16, 2026 · beginner
flask web python backend http

Flask is a lightweight Python web framework. It lets you build web applications quickly with minimal boilerplate. Flask is perfect for beginners because it is easy to learn but powerful enough for production use.

This tutorial covers installing Flask, creating your first application, defining routes, using templates, and handling forms.

Installing Flask

Flask is installed via pip. Create a virtual environment first to keep dependencies isolated.

python -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate
pip install flask

Verify the installation.

flask --version

Your First Flask Application

Create a file named app.py. This is your application entry point.

from flask import Flask

app = Flask(__name__)

@app.route("/")
def home():
    return "Hello, Flask!"

if __name__ == "__main__":
    app.run(debug=True)

Run the application.

python app.py

Open your browser and visit http://127.0.0.1:5000. You should see “Hello, Flask!”.

The @app.route("/") decorator maps the root URL to the home function. When someone visits /, Flask calls home() and returns its response.

Understanding Routes

Routes define URL patterns and which functions handle them. Flask uses decorators to define routes.

@app.route("/about")
def about():
    return "This is the about page."

@app.route("/contact")
def contact():
    return "Contact us at hello@example.com"

You can also capture variables from the URL.

@app.route("/user/<username>")
def user_profile(username):
    return f"Hello, {username}!"

@app.route("/post/<int:post_id>")
def show_post(post_id):
    return f"Showing post #{post_id}"

The <username> and <int:post_id> are dynamic segments. Flask converts int: segments to integers automatically.

Using Templates

Returning raw strings is fine for learning, but real applications use HTML templates. Flask looks for templates in a templates folder.

Create this directory structure:

project/
├── app.py
└── templates/
    └── index.html

Create templates/index.html:

<!DOCTYPE html>
<html>
<head>
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ heading }}</h1>
    <p>{{ message }}</p>
</body>
</html>

Update app.py to render the template:

from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template(
        "index.html",
        title="Welcome",
        heading="Hello, Flask!",
        message="Building web apps with Python is fun."
    )

if __name__ == "__main__":
    app.run(debug=True)

The render_template function finds the HTML file in the templates folder and substitutes the variables.

Handling Forms

Forms let users submit data to your application. Flask provides the request object to access form data.

Create templates/form.html:

<!DOCTYPE html>
<html>
<head>
    <title>Contact Form</title>
</head>
<body>
    <h1>Contact Us</h1>
    <form method="POST" action="/submit">
        <label>Name: <input type="text" name="name" required></label><br>
        <label>Email: <input type="email" name="email" required></label><br>
        <button type="submit">Send</button>
    </form>
</body>
</html>

Create templates/success.html:

<!DOCTYPE html>
<html>
<head>
    <title>Success</title>
</head>
<body>
    <h1>Thank You!</h1>
    <p>We received your message, {{ name }}.</p>
    <a href="/form">Send another</a>
</body>
</html>

Update app.py:

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route("/form")
def form():
    return render_template("form.html")

@app.route("/submit", methods=["POST"])
def submit():
    name = request.form.get("name")
    email = request.form.get("email")
    return render_template("success.html", name=name)

if __name__ == "__main__":
    app.run(debug=True)

The methods=["POST"] argument tells Flask to accept POST requests. Access form data with request.form.get().

The Request-Response Cycle

Understanding how Flask processes requests helps you debug issues.

  1. A user visits a URL
  2. Flask matches the URL to a route
  3. Flask calls the view function
  4. The view function returns a response
  5. Flask sends the response to the browser

You can inspect the request object in your views:

from flask import request

@app.route("/debug")
def debug_info():
    return {
        "method": request.method,
        "path": request.path,
        "args": request.args,
        "headers": dict(request.headers)
    }

Debug Mode

Setting debug=True enables auto-reload and the interactive debugger. Changes to your code restart the server automatically.

app.run(debug=True)

In production, always set debug=False. The debugger exposes your code to attackers.

Conclusion

Flask makes web development accessible. You installed Flask, created routes, rendered templates, and handled form submissions. These fundamentals apply to every Flask application.

The next tutorial in this series covers Django, a more feature-complete framework. For now, experiment with Flask — add more routes, create new templates, and explore Flask extensions.