DEV Community

Cover image for Single Page Web App in Python - Part 1
Stefan Meisner Larsen
Stefan Meisner Larsen

Posted on

Single Page Web App in Python - Part 1

Why this?

I found myself working on yet another python web application, copying some stuff from the previous one, improving it a bit and wondering if now is the time to create that great example project to make life easier next time.
I am starting this without knowing exactly where it will end, but I imagine a basic single page application with complete build and installation scripts for Linux, Docker and Kubernetes.

In this post

In this post I will create a small python project that can render a page in a browser - like Hello World for web apps. This will be the foundation for the next, soon to follow post. Stay tuned!

Source on GitHub

Source for this post in on branch post_1 on https://github.com/stefanmeisner/single_page_python

Here we go!

There are a number of web frameworks for python out there. I have stumbled into Flask a number of times. It's quite minimalistic compared to for example Django, and you're up and running in a very few lines of code.

Flask comes along with Jinja2 templating engine], another of my favorite tools.

Project layout

First things first - I have googled around and experimented too, until I settled with this project layout, which is quite common I believe.
If you are used to setup.py and requirements.txt this may be new for you. Welcome to the world of pyproject.toml!

I have found the following project layout to work well for me:


  single_page_python/
    README.md
    LICENSE
    .gitignore
    pyproject.toml
    src/
      single_page_python.py
      single_page_python/
        __init__.py
        server.py
        templates/
          index.html.j2

Enter fullscreen mode Exit fullscreen mode

Quick walk-through of the project files

pyproject.toml

I have not experimented with other build systems than setuptools, it has worked well for me so far. Dependencies goes into "dependencies" in the project section, and in the last section there is a list of development dependencies, required to build the project. This is also where you would add pytest and other stuff that should not be part of the shipped application.

[build-system]
requires = ["setuptools >= 80", "setuptools-scm", "wheel"]
build-backend = "setuptools.build_meta"

[project]
name = "single_page_python"
version = "0.0.1"
description = "Single Page Web Application with Python and JavaScript"
authors = [
  {name = "Stefan Meisner Larsen", email="developer@meisner-larsen.dk"}
]
readme = "README.md"
requires-python = ">=3.11"
dependencies = ["flask"]

[project.optional-dependencies]
dev = ["build"]
Enter fullscreen mode Exit fullscreen mode

server.py - the interesting stuff :)

We start by creating a Flask app - an instance of the class Flask, stating the name of our module as argument.

Using the app.route as decorator, we can easily specify, that any request for '/' should be handled by the index() method.

The render_template() function takes the name of a jinja2 template located in 'templates' folder, relative to server.py.

The 'title' argument is a context variable, that will be passed to the jinja template.
Let's take a look at that!

# Copyright 2025 Stefan Meisner Larsen
# Licensed under the MIT License.
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def index():
    return render_template('index.html.j2', title='Single Page Web Application')


def start_server():
    app.run(debug=True, host="localhost")

Enter fullscreen mode Exit fullscreen mode

templates/index.html.j2

The naming of this file, with double extension, makes it possible to provide syntax highlighting for both Jinja and HTML (at least in vscode, I did not get it to work here). Look how the 'title' argument to render_template() is being used:

<!DOCTYPE html>
<html>
    <head>
        <title>{{ title }}</title>
    </head>
    <body>
        <h5>{{ title }}</h5>
    </body>
</html>
Enter fullscreen mode Exit fullscreen mode

single_page_python.py - Where it all begins

This is the application entry point, the python file that you will actually be executing.

from single_page_python.server import start_server

if __name__ == '__main__':
    start_server()
Enter fullscreen mode Exit fullscreen mode

Creating a virtual environment for our project

Before installing any packages, we will create a virtual python environment ".venv" in the project root. The virtual environment is an isolated python installation, This will ensure that we don't tamper with the global python installation. On my linux system, the global python interpreter is called python3. We use the global interpreter to create the virtual environment.
After creating the environment, don't forget to activate it. This is done by "sourcing" the activate script using ".":

python -m venv .venv
. .venv/bin/activate
Enter fullscreen mode Exit fullscreen mode

Running the application

In the project root (where pyproject.tom is) install the application and the required dependencies:

python -m pip install -e '.[dev]'
Enter fullscreen mode Exit fullscreen mode

Then run it with:

python src/single_page_python.py
Enter fullscreen mode Exit fullscreen mode

Try it out here http://localhost:5000!

Top comments (0)