With your development environment ready, it’s time to write some code! This chapter focuses on creating a minimal FastAPI application, understanding its basic components, and establishing a sensible project structure.

Purpose of this Chapter

By the end of this chapter, you will be able to:

  • Write a simple “Hello, World!” FastAPI application.
  • Run the FastAPI application using Uvicorn.
  • Understand basic FastAPI routing.
  • Create a foundational project directory structure.

Concepts Explained: FastAPI Basics

FastAPI is a modern, fast (high-performance) web framework for building APIs with Python 3.8+ based on standard Python type hints. It offers:

  • Automatic documentation: Generates interactive API documentation (Swagger UI and ReDoc) from your code.
  • Data validation and serialization: Uses Pydantic for robust data handling.
  • Performance: Built on Starlette (for web parts) and Pydantic (for data parts), making it extremely fast.

An “endpoint” or “route” in FastAPI is a specific URL that your application listens to. When a client sends a request to that URL, FastAPI executes a Python function associated with that route.

Step-by-Step Tasks

1. Create main.py

Inside your realtime-chat-app directory, create a new file named main.py. This will be the entry point for our FastAPI application.

# realtime-chat-app/main.py

from fastapi import FastAPI

# Create a FastAPI instance
app = FastAPI()

# Define a root endpoint
@app.get("/")
async def read_root():
    return {"message": "Welcome to the Real-time Chat API!"}

# Define another endpoint to test
@app.get("/health")
async def health_check():
    return {"status": "ok"}

Code Explanation:

  • from fastapi import FastAPI: Imports the FastAPI class.
  • app = FastAPI(): Creates an instance of the FastAPI application.
  • @app.get("/"): This is a “decorator” that registers the read_root function to handle HTTP GET requests to the / path.
  • async def read_root():: Defines an asynchronous function. FastAPI leverages Python’s async/await for efficient handling of I/O operations, which is crucial for real-time applications.
  • return {"message": "..."}: The function returns a Python dictionary, which FastAPI automatically converts into a JSON response.

2. Run the Application with Uvicorn

Open your terminal, navigate to your realtime-chat-app directory, and activate your virtual environment.

pipenv shell

Now, run your FastAPI application using Uvicorn:

uvicorn main:app --reload

Command Explanation:

  • uvicorn: The command to run the Uvicorn server.
  • main:app: Tells Uvicorn to look for an application object named app inside the main.py file.
  • --reload: This flag enables auto-reloading. Uvicorn will monitor your code for changes and restart the server automatically, which is very useful during development.

You should see output similar to this:

INFO:     Will watch for changes in these directories: ['/path/to/your/realtime-chat-app']
INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO:     Started reloader process [12345] using WatchFiles
INFO:     Started server process [12347]
INFO:     Waiting for application startup.
INFO:     Application startup complete.

3. Test Your Endpoints

Open your web browser or a tool like Postman/Insomnia and visit:

  • http://127.0.0.1:8000/
    • You should see: {"message": "Welcome to the Real-time Chat API!"}
  • http://127.0.0.1:8000/health
    • You should see: {"status": "ok"}
  • http://127.0.0.1:8000/docs
    • You’ll find the automatically generated interactive API documentation (Swagger UI).
  • http://127.0.0.1:8000/redoc
    • You’ll find the alternative API documentation (ReDoc).

This confirms that your FastAPI application is running and accessible.

4. Establish Initial Project Structure

As our application grows, a clear project structure becomes essential. Let’s create a few subdirectories to organize our code.

Stop the Uvicorn server (Ctrl+C) and create the following structure within your realtime-chat-app directory:

realtime-chat-app/
├── app/
│   ├── __init__.py
│   └── main.py       # Our FastAPI app will be here
├── .env              # For environment variables (later)
├── Pipfile
├── Pipfile.lock
├── README.md

Now, move your main.py file into the app/ directory:

mv main.py app/
touch app/__init__.py # Create an empty __init__.py to make 'app' a Python package

Your main.py content remains the same. The __init__.py file is empty but tells Python that the app directory should be treated as a Python package.

5. Update Uvicorn Command

Since main.py is now inside the app directory, you need to update the Uvicorn command to reflect this:

uvicorn app.main:app --reload

Test it again in your browser to ensure it’s still working.

Tips/Challenges/Errors

  • “uvicorn: command not found”: Ensure you’ve activated your virtual environment (pipenv shell) or installed Uvicorn globally (not recommended for projects).
  • “ModuleNotFoundError: No module named ‘app.main’”: Double-check that main.py is inside the app directory and that you created an empty app/__init__.py file. Also, verify your uvicorn command points to app.main:app.
  • Port already in use: If you see OSError: [Errno 98] Address already in use, it means another process is using port 8000. You can either find and kill that process or run Uvicorn on a different port: uvicorn app.main:app --reload --port 8001.

Summary/Key Takeaways

You’ve successfully created and run your first FastAPI application, establishing the foundation of our project. A clear project structure will aid maintainability as we add more features. The next step is to introduce WebSockets to enable real-time communication.