Backend Step 2: Hello Flask
Now you'll create your first Flask web server and understand how routes work.
What You'll Learn
- Running a Flask server
- Defining routes with
@app.route() - Returning JSON with
jsonify() - The request-response cycle
Step 1: Create the Basic Flask App
Edit backend/app/__init__.py:
from flask import Flask, jsonify
def create_app():
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Hello Flask!"})
return app
if __name__ == "__main__":
app = create_app()
app.run(debug=True, port=5000)
Step 2: Run the Server
Choose the method that matches your setup from Step 1:
Option A — Virtual Environment:
cd aiproject/backend
source venv/bin/activate
python app/__init__.py
Option B — Docker:
cd aiproject/backend
docker compose up
You should see:
* Serving Flask app 'app'
* Debug mode: on
* Running on http://127.0.0.1:5000
Step 3: Test It
Open a new terminal and run:
curl http://127.0.0.1:5000/
Expected output:
{"message":"Hello Flask!"}
Or open http://127.0.0.1:5000/ in your browser.
Step 4: Add a Status Route
Let's add a health check endpoint. Update __init__.py:
from flask import Flask, jsonify
def create_app():
app = Flask(__name__)
@app.route("/")
def home():
return jsonify({"message": "Hello Flask!"})
@app.route("/api/status")
def status():
return jsonify({"status": "ok", "version": "1.0"})
return app
if __name__ == "__main__":
app = create_app()
app.run(debug=True, port=5000)
Test it:
curl http://127.0.0.1:5000/api/status
# → {"status":"ok","version":"1.0"}
Step 5: Understanding Routes
A route is a URL pattern. When a request comes in, Flask matches the URL to the correct function:
@app.route("/") # GET / → calls home()
@app.route("/api/status") # GET /api/status → calls status()
The function returns data, and jsonify() converts it to JSON.
How Flask Works
- You start the server with
app.run() - Flask listens on port 5000 for incoming HTTP requests
- When a request arrives, Flask matches the URL to a route
- Flask calls the matching function
- The function returns a response (JSON)
- Flask sends the response back to the client
Step 6: Lint Your Code (Catch Errors Early)
Now run ruff to check your code for issues:
cd aiproject/backend
ruff check app/
If everything is clean, you'll see no output. That's good — it means no issues found.
Try making a mistake on purpose — add an unused import, then run ruff again:
import os # ← This line is never used
ruff check app/
# → app/__init__.py:1:1: F401 `os` imported but unused
Ruff caught the unused import. Remove it and run ruff again — clean.
Why this matters: Linting catches bugs before you even run the code. A missing import, a typo in a variable name, an unused function — ruff finds them all. Professional developers run linters before every commit.
Step 7: Write Your First Automated Test
So far you've been testing with curl — typing commands manually. That works, but it's slow and easy to forget.
Instead, write an automated test that checks the same thing:
Create backend/tests/test_status.py:
def test_status_returns_ok(client):
response = client.get("/api/status")
assert response.status_code == 200
assert response.get_json() == {"status": "ok"}
This test:
1. Sends a GET to /api/status
2. Checks the status code is 200 (success)
3. Checks the JSON body is {"status": "ok"}
Run it:
cd aiproject/backend
pip install pytest
python -m pytest tests/ -v
Expected output:
tests/test_status.py::test_status_returns_ok PASSED
One test passed. You now have an automated test that you can run in 1 second instead of manually curling.
Step 8: Experiment
@app.route("/api/greet/<name>")
def greet(name):
return jsonify({"message": f"Hello, {name}!"})
Test: curl http://127.0.0.1:5000/api/greet/Alice
→ {"message":"Hello, Alice!"}
Explanation: Why jsonify()?
Flask can return strings or HTML directly, but our mobile app needs JSON. jsonify() converts Python dictionaries into JSON format and sets the right Content-Type header.
Without jsonify():
return {"message": "hello"} # In older Flask, this didn't work!
With jsonify():
return jsonify({"message": "hello"}) # Proper JSON response
Verification
curl http://127.0.0.1:5000/
# → {"message":"Hello Flask!"}
curl http://127.0.0.1:5000/api/status
# → {"status":"ok","version":"1.0"}
If both work, you're ready for Step 3.