Use Vue with Flask & HTMX
May 31, 2025
You will learn how to set up your flask app to use Vue and HTMX.
What you will need:
- Flask - Python web framework
- Vue CDN - for snappy frontend UI
- Tailwind CDN - for fast CSS styling
- HTMX - for a more dynamic frontend (not heavily used)
Create a new Flask App
Create the folders for your flask app. You should be able to copy the content below and paste it into your terminal. You can also create the folders manually using your mouse and keyboard. the app_name/
folder can be called whatever the name of your app is. For example you can do mkdir inventory_app
instead of mkdir app_name
.
mkdir app_name
cd app_name
touch app.py
mkdir templates
touch templates/index.html
mkdir static
touch static/style.css
touch static/index.js
This is the folder structure of the app.
app_name/
templates/
index.html
static/
index.js
style.css
app.py
Install dependencies
Create a virtual environment and install flask
.
python3 -m venv .venv
source .venv/bin/activate
pip3 install flask
Configuration
Set up some configuration.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="https://unpkg.com/vue@3"></script>
<title>Method 1 - Vue in Jinja</title>
</head>
<body>
<div id="app">
<p>{{ greeting }}</p>
<p>[[ greeting ]]</p>
<button hx-get="/clicked" hx-swap="outerHTML">
Click Me
</button>
</div>
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<script src="{{ url_for('static', filename='index.js') }}"></script>
</body>
</html>
const app = Vue.createApp({
delimiters: ['[[', ']]'],
data() {
return {
greeting: 'Hello from Vue 3 + Flask!'
}
}
})
app.mount('#app')
The Code
All components live in /templates/
. CSS and Javascript files live in /static/
. Copy the code in the files below to the appropriate files in your project.
from flask import Flask, render_template
app = Flask(__name__)
@app.route("/")
def index():
return render_template("index.html", **{'greeting': 'Hello from Flask!'})
@app.route("/clicked")
def clicked():
return 'You clicked'
if __name__ == '__main__':
app.run(debug=True,port=4000)
Run the App
python3 app.py
Vite + Vue + Flask Version
You can separate the frontend Vue code from the backend flask code using the steps below. Please note that I am using Vite, but you can just as well use the Vue CLI or other frontend frameworks like React or Svelte.
You will need:
Create two folders. One for your backend code and another for your frontend code.
mkdir backend
mkdir frontend
The Backend
The backend will be similar to the flask portion above but we will add CORS and rename app.py
to server.py
so that we know this is a backend server (see server.py
below).
from flask import Flask, render_template
from flask_cors import CORS # Import CORS
app = Flask(__name__)
CORS(app)
@app.route("/")
def index():
return render_template("index.html", **{'greeting': 'Hello from Flask!'})
@app.route("/clicked")
def clicked():
return 'You clicked'
if __name__ == '__main__':
app.run(debug=True,port=4000)
The Frontend
Change your directory to the frontend
directory and create your vue frontend using vite. Set your app's name to something like app_name
and select Vue
then Javascript
(you can select Typescript if you prefer that), and finally, change directory into the new app_name directory
cd frontend
yarn create vite
cd app_name
Update the index.html
file in the frontend folder as follows. We need to add a meta tag for htmx to allow us to fetch data from the flask backend.
Now, you can use HTMX in any vue component (See Component.vue
)
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="htmx-config" content='{"selfRequestsOnly":false}'>
<!-- Needed so that you don't get an invalidPath error -->
<title>Vite + Vue</title>
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
<script type="module" src="/src/main.js"></script>
</body>
</html>
<template>
<button hx-get="http://127.0.0.1:4000/" hx-swap="outerHTML">
Click Me
</button>
</template
<script setup>
</script>
Run the frontend and backend with a bash script
We can use a bash script to run the frontend and backend at the same time. Add a file named run.sh
(you can call it whatever you want) at the same level as the frontend and backend folders and add the following.
#!/bin/bash
# Start backend in background
cd backend
python3 server.py &
# Capture the backend PID if you want to stop it later
BACKEND_PID=$!
# Move to frontend and start dev server
cd ../frontend/flask-vue
yarn dev
# Optional: Kill backend when frontend exits
kill $BACKEND_PID
To run the script run bash run.sh
.
To make this script executable, you can run it by giving the file execution permissions:
chmod +x run.sh
After that, you can execute the script by running:
./run.sh