From 4ce1ebc61211a8d6b08469f9066f013ecfce7a6a Mon Sep 17 00:00:00 2001 From: ricardo-agz Date: Wed, 1 Oct 2025 14:01:52 -0700 Subject: [PATCH 1/3] updates fastapi example --- python/fastapi/main.py | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/python/fastapi/main.py b/python/fastapi/main.py index 4214abc1a0..43c9028b7b 100644 --- a/python/fastapi/main.py +++ b/python/fastapi/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI -from fastapi.staticfiles import StaticFiles -from fastapi.responses import FileResponse, HTMLResponse +from fastapi.responses import HTMLResponse + app = FastAPI( title="Vercel + FastAPI", @@ -9,14 +9,6 @@ ) -app.mount("/public", StaticFiles(directory="public"), name="public") - - -@app.get("/favicon.ico", include_in_schema=False) -async def favicon(): - return FileResponse("public/favicon.ico") - - @app.get("/api/data") def get_sample_data(): return { From 76a3691c45e1dfd1da898880a7fed260c624d4fd Mon Sep 17 00:00:00 2001 From: ricardo-agz Date: Wed, 8 Oct 2025 17:42:55 -0700 Subject: [PATCH 2/3] flask example --- python/flask/README.md | 31 +++++++++ python/flask/endpoints/__init__.py | 3 + python/flask/endpoints/routes.py | 33 ++++++++++ python/flask/main.py | 101 +++++++++++++++++++++++++++++ python/flask/public/favicon.ico | Bin 0 -> 67646 bytes python/flask/pyproject.toml | 7 ++ 6 files changed, 175 insertions(+) create mode 100644 python/flask/README.md create mode 100644 python/flask/endpoints/__init__.py create mode 100644 python/flask/endpoints/routes.py create mode 100644 python/flask/main.py create mode 100644 python/flask/public/favicon.ico create mode 100644 python/flask/pyproject.toml diff --git a/python/flask/README.md b/python/flask/README.md new file mode 100644 index 0000000000..0fef350fcc --- /dev/null +++ b/python/flask/README.md @@ -0,0 +1,31 @@ +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fflask&demo-title=Flask%20API&demo-description=Use%20Flask%20API%20on%20Vercel%20with%20Serverless%20Functions%20using%20the%20Python%20Runtime.&demo-url=https%3A%2F%2Fvercel-plus-flask.vercel.app%2F&demo-image=https://assets.vercel.com/image/upload/v1669994600/random/python.png) + +# Flask + Vercel + +This example shows how to use Flask on Vercel with Serverless Functions using the [Python Runtime](https://vercel.com/docs/concepts/functions/serverless-functions/runtimes/python). + +## Demo + +https://vercel-plus-flask.vercel.app/ + +## How it Works + +This example uses the Web Server Gateway Interface (WSGI) with Flask to handle requests on Vercel with Serverless Functions. + +## Running Locally + +```bash +npm i -g vercel +python -m venv .venv +source .venv/bin/activate +uv sync # or alternatively pip install flask +vercel dev +``` + +Your Flask application is now available at `http://localhost:3000`. + +## One-Click Deploy + +Deploy the example using [Vercel](https://vercel.com?utm_source=github&utm_medium=readme&utm_campaign=vercel-examples): + +[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https%3A%2F%2Fgithub.com%2Fvercel%2Fvercel%2Ftree%2Fmain%2Fexamples%2Fflask&demo-title=Flask%20API&demo-description=Use%20Flask%20API%20on%20Vercel%20with%20Serverless%20Functions%20using%20the%20Python%20Runtime.&demo-url=https%3A%2F%2Fvercel-plus-flask.vercel.app%2F&demo-image=https://assets.vercel.com/image/upload/v1669994600/random/python.png) diff --git a/python/flask/endpoints/__init__.py b/python/flask/endpoints/__init__.py new file mode 100644 index 0000000000..b497fd4f42 --- /dev/null +++ b/python/flask/endpoints/__init__.py @@ -0,0 +1,3 @@ +from .routes import api_bp + +__all__ = ["api_bp"] diff --git a/python/flask/endpoints/routes.py b/python/flask/endpoints/routes.py new file mode 100644 index 0000000000..5521deb675 --- /dev/null +++ b/python/flask/endpoints/routes.py @@ -0,0 +1,33 @@ +from flask import Blueprint, jsonify + + +api_bp = Blueprint("api", __name__) + + +@api_bp.get("/api/data") +def get_sample_data(): + return jsonify( + { + "data": [ + {"id": 1, "name": "Sample Item 1", "value": 100}, + {"id": 2, "name": "Sample Item 2", "value": 200}, + {"id": 3, "name": "Sample Item 3", "value": 300}, + ], + "total": 3, + "timestamp": "2024-01-01T00:00:00Z", + } + ) + + +@api_bp.get("/api/items/") +def get_item(item_id: int): + return jsonify( + { + "item": { + "id": item_id, + "name": f"Sample Item {item_id}", + "value": item_id * 100, + }, + "timestamp": "2024-01-01T00:00:00Z", + } + ) diff --git a/python/flask/main.py b/python/flask/main.py new file mode 100644 index 0000000000..7fb7afb6c6 --- /dev/null +++ b/python/flask/main.py @@ -0,0 +1,101 @@ +from flask import Flask +from endpoints import api_bp + + +app = Flask(__name__) + + +app.register_blueprint(api_bp) + + +@app.get("/") +def read_root(): + return """ + + + + + + Vercel + Flask + + + + +
+ +
+
+
+

Vercel + Flask

+
+
from flask import Flask
+
+app = Flask(__name__)
+
+@app.get("/")
+def read_root():
+    return {"Python": "on Vercel"}
+
+
+ +
+
+

Sample Data

+

Access sample JSON data through our REST API. Perfect for testing and development purposes.

+ Get Data → +
+
+
+ + + """ diff --git a/python/flask/public/favicon.ico b/python/flask/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..efc4a4c989adc6decfe00d38f5b0206b5bad3f0f GIT binary patch literal 67646 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.1", +] From 28a1f4678d2987bd3f37df0b308915973b78a1f5 Mon Sep 17 00:00:00 2001 From: ricardo-agz Date: Wed, 8 Oct 2025 17:44:26 -0700 Subject: [PATCH 3/3] fix --- python/flask/README.md | 4 ++-- python/flask/pyproject.toml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/python/flask/README.md b/python/flask/README.md index 0fef350fcc..0c2fb66cdb 100644 --- a/python/flask/README.md +++ b/python/flask/README.md @@ -18,8 +18,8 @@ This example uses the Web Server Gateway Interface (WSGI) with Flask to handle r npm i -g vercel python -m venv .venv source .venv/bin/activate -uv sync # or alternatively pip install flask -vercel dev +uv sync # or alternatively pip install flask gunicorn +gunicorn main:app ``` Your Flask application is now available at `http://localhost:3000`. diff --git a/python/flask/pyproject.toml b/python/flask/pyproject.toml index b71056e7c1..058026c02a 100644 --- a/python/flask/pyproject.toml +++ b/python/flask/pyproject.toml @@ -3,5 +3,6 @@ name = "vercel-flask-starter" version = "0.1.0" requires-python = ">=3.9" dependencies = [ - "flask>=3.1", + "flask~=3.1", + "gunicorn~=23.0.0 ]