diff --git a/blog/2026-01-09-top-python-web-frameworks-2026.md b/blog/2026-01-09-top-python-web-frameworks-2026.md index a7395f47a..221e1ca1a 100644 --- a/blog/2026-01-09-top-python-web-frameworks-2026.md +++ b/blog/2026-01-09-top-python-web-frameworks-2026.md @@ -1,13 +1,21 @@ --- author: Tom Gotsman +author_bio: Tom Gotsman is a Software Engineer at Reflex. date: 2026-01-09 +updated_at: 2026-01-09 title: Top Python Web Development Frameworks in 2026 +title_tag: Best Python Web Frameworks 2026 - Reflex, Django, Flask & More description: Reflex vs Django vs Flask vs Gradio vs Streamlit vs Dash vs FastAPI image: /blog/top_python_web_frameworks_2026.png tag: Builder meta: [ {"name": "keywords", "content": "streamlit python, streamlit, streamlit alternatives, plotly, dash app, plotly python, fastapi"}, ] +faq: [ + {"question": "What is the best Python web framework in 2026?", "answer": "It depends on your use case. Reflex is ideal for full-stack apps in pure Python, Django for large-scale applications, Flask for lightweight APIs, and FastAPI for high-performance async APIs."}, + {"question": "Can I build a full-stack web app with only Python?", "answer": "Yes. Frameworks like Reflex let you build both the frontend and backend entirely in Python without writing JavaScript."}, + {"question": "What is the difference between Streamlit and Reflex?", "answer": "Streamlit is designed for quick data apps and dashboards, while Reflex is a full-stack framework for building production-grade, customizable web applications entirely in Python."}, +] --- diff --git a/pcweb/meta/meta.py b/pcweb/meta/meta.py index fd06dc52d..1b9d25371 100644 --- a/pcweb/meta/meta.py +++ b/pcweb/meta/meta.py @@ -1,3 +1,5 @@ +import json + import reflex as rx from pcweb.constants import REFLEX_DOMAIN, REFLEX_DOMAIN_URL, TWITTER_CREATOR @@ -105,3 +107,79 @@ def create_meta_tags( image=image_url, url=page_url, ) + + +def _normalize_image_url(image: str) -> str: + """Ensure image path is a full URL.""" + if image and not image.startswith(("http://", "https://")): + return f"https://reflex.dev{'' if image.startswith('/') else '/'}{image}" + return image + + +def blog_jsonld( + title: str, + description: str, + author: str, + date: str, + image: str, + url: str, + faq: list[dict[str, str]] | None = None, + author_bio: str | None = None, + updated_at: str | None = None, +) -> rx.Component: + """Create a single JSON-LD script tag with @graph for a blog post. + + Always includes a BlogPosting entry. If faq items are provided, + a FAQPage entry is also added to the graph. + """ + author_node: dict = {"@type": "Person", "name": author} + if author_bio: + author_node["description"] = author_bio + + posting: dict = { + "@type": "BlogPosting", + "headline": title, + "description": description, + "image": _normalize_image_url(image), + "datePublished": str(date), + "author": author_node, + } + if updated_at: + posting["dateModified"] = str(updated_at) + + graph: list[dict] = [ + { + **posting, + "publisher": { + "@type": "Organization", + "name": "Reflex", + "url": REFLEX_DOMAIN_URL, + }, + "mainEntityOfPage": { + "@type": "WebPage", + "@id": url, + }, + }, + ] + if faq: + graph.append( + { + "@type": "FAQPage", + "mainEntity": [ + { + "@type": "Question", + "name": item["question"], + "acceptedAnswer": { + "@type": "Answer", + "text": item["answer"], + }, + } + for item in faq + ], + } + ) + data = { + "@context": "https://schema.org", + "@graph": graph, + } + return rx.el.script(json.dumps(data), type="application/ld+json") diff --git a/pcweb/pages/blog/blog.py b/pcweb/pages/blog/blog.py index 2755cf1f0..3a3f0e0ef 100644 --- a/pcweb/pages/blog/blog.py +++ b/pcweb/pages/blog/blog.py @@ -211,13 +211,15 @@ def blogs(): # Get the docpage component. route = f"/blog/{path}" title = rx.utils.format.to_snake_case(path.rsplit("/", 1)[1].replace(".md", "")) + # Use title_tag for