Claude Code for Quart: Async Flask Web Framework in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for Quart: Async Flask Web Framework in Python
AI

Claude Code for Quart: Async Flask Web Framework in Python

Published: May 13, 2028
Read time: 5 min read
By: Claude Skills 360

Quart is an async Flask-compatible web framework. pip install quart. Basic: from quart import Quart; app = Quart(__name__); @app.route("/"); async def index(): return "Hello". Run: app.run() or hypercorn app:app. JSON: from quart import jsonify; return jsonify({"ok": True}). Request: from quart import request; data = await request.get_json(). Form: await request.form. Files: await request.files. Blueprint: from quart import Blueprint; bp = Blueprint("api", __name__). app.register_blueprint(bp, url_prefix="/api"). WebSocket: @app.websocket("/ws"); async def ws(): while True: msg = await websocket.receive(); await websocket.send(f"Echo: {msg}"). Before: @app.before_request async def check_auth(): .... After: @app.after_request async def add_cors(response): .... g: from quart import g; g.user = .... current_app. Template: from quart import render_template; return await render_template("index.html", name=name). Error handler: @app.errorhandler(404) async def not_found(e): return jsonify({"error": "not found"}), 404. Testing: async with app.test_client() as c: resp = await c.get("/"). Config: app.config["DEBUG"] = True. Hypercorn: hypercorn app:app --bind 0.0.0.0:8000. --workers 4. Claude Code generates Quart REST APIs, WebSocket servers, Blueprint modules, and async middleware.

CLAUDE.md for Quart

## Quart Stack
- Version: quart >= 0.19 | pip install quart hypercorn
- App: app = Quart(__name__) | async def view() with await
- Request: await request.get_json() | await request.form | await request.files
- WebSocket: @app.websocket("/ws") | await websocket.receive() / .send()
- Blueprint: bp = Blueprint("name", __name__); app.register_blueprint(bp)
- Deploy: hypercorn app:app --bind 0.0.0.0:8000 --workers 4

Quart Async Web Pipeline

# app/quart_app.py — Quart REST API, WebSocket, Blueprint, middleware, and testing
from __future__ import annotations

import asyncio
import json
import time
from functools import wraps
from typing import Any

from quart import (
    Blueprint,
    Quart,
    Response,
    current_app,
    g,
    jsonify,
    make_response,
    render_template_string,
    request,
    websocket,
)


# ─────────────────────────────────────────────────────────────────────────────
# 1. Application factory
# ─────────────────────────────────────────────────────────────────────────────

def create_app(config: dict | None = None) -> Quart:
    """
    Application factory pattern.
    config: dict of config overrides.

    Usage:
        app = create_app({"DEBUG": True})
        app.run()
    """
    app = Quart(__name__)

    # Defaults
    app.config.update({
        "DEBUG":          False,
        "JSON_SORT_KEYS": False,
    })
    if config:
        app.config.update(config)

    # Register blueprints
    app.register_blueprint(api_bp,   url_prefix="/api")
    app.register_blueprint(ws_bp,    url_prefix="/ws")

    # Middleware
    @app.before_request
    async def time_start():
        g.start = time.monotonic()

    @app.after_request
    async def add_timing(response: Response) -> Response:
        elapsed = time.monotonic() - g.start
        response.headers["X-Processing-Time"] = f"{elapsed * 1000:.1f}ms"
        response.headers["Access-Control-Allow-Origin"] = "*"
        return response

    @app.errorhandler(404)
    async def not_found(e):
        return jsonify({"error": "not found", "status": 404}), 404

    @app.errorhandler(422)
    async def unprocessable(e):
        return jsonify({"error": str(e), "status": 422}), 422

    return app


# ─────────────────────────────────────────────────────────────────────────────
# 2. Auth decorator
# ─────────────────────────────────────────────────────────────────────────────

VALID_TOKENS = {"secret-token-123", "dev-token"}


def require_auth(fn):
    """Simple bearer token auth decorator for Quart routes."""
    @wraps(fn)
    async def wrapper(*args, **kwargs):
        auth = request.headers.get("Authorization", "")
        if not auth.startswith("Bearer "):
            return jsonify({"error": "missing token"}), 401
        token = auth[len("Bearer "):]
        if token not in VALID_TOKENS:
            return jsonify({"error": "invalid token"}), 403
        return await fn(*args, **kwargs)
    return wrapper


# ─────────────────────────────────────────────────────────────────────────────
# 3. REST API blueprint
# ─────────────────────────────────────────────────────────────────────────────

api_bp  = Blueprint("api",  __name__)

# In-memory "database"
_items: dict[int, dict] = {}
_next_id = 1


def _next() -> int:
    global _next_id
    _next_id += 1
    return _next_id - 1


@api_bp.get("/items")
async def list_items():
    """GET /api/items — list all items."""
    limit  = int(request.args.get("limit",  20))
    offset = int(request.args.get("offset",  0))
    items  = list(_items.values())[offset: offset + limit]
    return jsonify({"items": items, "total": len(_items)})


@api_bp.post("/items")
async def create_item():
    """POST /api/items — create an item."""
    data = await request.get_json()
    if not data or "name" not in data:
        return jsonify({"error": "name required"}), 422
    item = {"id": _next(), "name": data["name"],
            "tags": data.get("tags", []), "active": True}
    _items[item["id"]] = item
    return jsonify(item), 201


@api_bp.get("/items/<int:item_id>")
async def get_item(item_id: int):
    """GET /api/items/:id"""
    item = _items.get(item_id)
    if not item:
        return jsonify({"error": "not found"}), 404
    return jsonify(item)


@api_bp.put("/items/<int:item_id>")
async def update_item(item_id: int):
    """PUT /api/items/:id"""
    item = _items.get(item_id)
    if not item:
        return jsonify({"error": "not found"}), 404
    data = await request.get_json() or {}
    item.update({k: v for k, v in data.items() if k != "id"})
    return jsonify(item)


@api_bp.delete("/items/<int:item_id>")
async def delete_item(item_id: int):
    """DELETE /api/items/:id"""
    if item_id not in _items:
        return jsonify({"error": "not found"}), 404
    del _items[item_id]
    return jsonify({"deleted": item_id})


@api_bp.get("/protected")
@require_auth
async def protected():
    """Protected endpoint — needs Authorization: Bearer <token>"""
    return jsonify({"message": "secret data", "user": "authenticated"})


# ─────────────────────────────────────────────────────────────────────────────
# 4. WebSocket blueprint
# ─────────────────────────────────────────────────────────────────────────────

ws_bp = Blueprint("ws", __name__)

_ws_clients: set = set()


@ws_bp.websocket("/echo")
async def ws_echo():
    """Bidirectional echo WebSocket."""
    while True:
        msg = await websocket.receive()
        await websocket.send(f"Echo: {msg}")


@ws_bp.websocket("/chat")
async def ws_chat():
    """Broadcast chat: every message sent to all connected clients."""
    global _ws_clients
    _ws_clients.add(websocket._get_current_object())
    try:
        while True:
            msg = await websocket.receive()
            data = json.loads(msg) if msg.startswith("{") else {"text": msg}
            payload = json.dumps({"user": data.get("user", "anon"),
                                   "text": data.get("text", msg)})
            dead = set()
            for client in list(_ws_clients):
                try:
                    await client.send(payload)
                except Exception:
                    dead.add(client)
            _ws_clients -= dead
    finally:
        _ws_clients.discard(websocket._get_current_object())


# ─────────────────────────────────────────────────────────────────────────────
# 5. Health / HTML endpoints on main app
# ─────────────────────────────────────────────────────────────────────────────

_HTML = """<!doctype html>
<html><head><title>Quart Demo</title></head>
<body>
  <h1>Quart Async API</h1>
  <p>Endpoints: <code>GET /api/items</code>, <code>POST /api/items</code></p>
  <p>WebSocket: <code>ws://localhost:5000/ws/echo</code></p>
</body></html>"""


def register_main_routes(app: Quart) -> None:
    @app.get("/")
    async def index():
        return await render_template_string(_HTML)

    @app.get("/health")
    async def health():
        return jsonify({"status": "ok", "version": "1.0.0"})


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

app = create_app({"DEBUG": True})
register_main_routes(app)


async def _demo():
    async with app.test_client() as client:
        print("=== GET /health ===")
        resp = await client.get("/health")
        print(f"  {resp.status_code}: {await resp.get_json()}")

        print("\n=== POST /api/items ===")
        resp = await client.post("/api/items",
                                  json={"name": "Widget", "tags": ["new"]})
        print(f"  {resp.status_code}: {await resp.get_json()}")

        resp2 = await client.post("/api/items", json={"name": "Gadget"})
        item = await resp2.get_json()
        print(f"  {resp2.status_code}: {item}")

        print("\n=== GET /api/items ===")
        resp = await client.get("/api/items")
        data = await resp.get_json()
        print(f"  {resp.status_code}: total={data['total']}, items={[i['name'] for i in data['items']]}")

        print("\n=== GET /api/items/:id ===")
        resp = await client.get(f"/api/items/{item['id']}")
        print(f"  {resp.status_code}: {await resp.get_json()}")

        print("\n=== DELETE /api/items/:id ===")
        resp = await client.delete(f"/api/items/{item['id']}")
        print(f"  {resp.status_code}: {await resp.get_json()}")

        print("\n=== Protected (no auth) ===")
        resp = await client.get("/api/protected")
        print(f"  {resp.status_code}: {await resp.get_json()}")

        print("\n=== Protected (with auth) ===")
        resp = await client.get("/api/protected",
                                 headers={"Authorization": "Bearer secret-token-123"})
        print(f"  {resp.status_code}: {await resp.get_json()}")


if __name__ == "__main__":
    asyncio.run(_demo())
    print("\nTo run the server:")
    print("  hypercorn quart_app:app --bind 0.0.0.0:5000")

For the Flask alternative — Flask uses synchronous view functions and a WSGI server model; Quart is API-compatible with Flask (many Flask extensions work unchanged) but runs on ASGI with asyncio, enabling await db.fetch(), await httpx.get(), and WebSocket endpoints in the same codebase — migrate Flask to Quart by adding async def to views and await to I/O calls. For the FastAPI alternative — FastAPI has Pydantic-based request validation, automatic OpenAPI documentation, and a large ecosystem; Quart is closer to Flask’s minimal style with less magic — use Quart when you want Flask’s simplicity in an async context, FastAPI when you need auto-generated docs and type-validated request bodies. The Claude Skills 360 bundle includes Quart skill sets covering create_app() application factory, before_request/after_request timing middleware, require_auth() bearer token decorator, Blueprint CRUD (list/create/get/update/delete), ws_echo()/ws_chat() WebSocket endpoints, test_client() async testing, health endpoint, error handlers, and Hypercorn deployment. Start with the free tier to try async Flask-style web framework code generation.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free