Skip to content

3 new blogs#1810

Merged
tgberkeley merged 7 commits intomainfrom
blogs-04-02-26
Apr 6, 2026
Merged

3 new blogs#1810
tgberkeley merged 7 commits intomainfrom
blogs-04-02-26

Conversation

@tgberkeley
Copy link
Copy Markdown
Collaborator

No description provided.

@tgberkeley
Copy link
Copy Markdown
Collaborator Author

Still missing the images here properly, working with carlos on this.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 2, 2026

Greptile Summary

This PR adds three new SEO-focused blog posts (Python dashboard without JavaScript, Streamlit vs. Dash comparison, and Django vs. Flask vs. Reflex comparison) along with supporting framework changes: keyword and word-count extraction in pcweb/pages/blog/page.py for structured blog_jsonld data, new QuoteBlock / TabsBlock flexdown block types in pcweb/flexdown.py, and carousel / "more customers" enhancements in pcweb/templates/storypage.py.

Key findings:

  • The database code example in build-dashboard-python-without-javascript.md references pd.read_sql(...) without importing pandas as pd, making the snippet non-runnable as written.
  • The feature comparison table in django-vs-flask-vs-reflex-comparison.md has a spurious trailing empty 5th column on every row due to an extra | | at the end of each line.
  • Several issues flagged in previous review rounds (missing code fences, product name inconsistency, "Javacript" typo) remain unaddressed in the blog markdown files.
  • The Python infrastructure changes (page.py, flexdown.py, storypage.py) are clean with no correctness issues.

Confidence Score: 4/5

Safe to merge for infrastructure changes; the blog posts still carry several unaddressed issues from prior review rounds alongside the new pd undefined reference.

All Python infrastructure changes are clean. The remaining open issues are confined to blog markdown content: the pd undefined in a code example, the trailing empty column in the comparison table, and the still-unaddressed items from earlier rounds (missing code fences, name inconsistency, typo). None of these will cause runtime errors for the site, but they do affect the quality and correctness of the published content, warranting at least one more pass before merge.

blog/build-dashboard-python-without-javascript.md (pd undefined in code example, missing code fences from prior round), blog/django-vs-flask-vs-reflex-comparison.md (empty 5th table column, name inconsistency and typo from prior round)

Important Files Changed

Filename Overview
blog/build-dashboard-python-without-javascript.md New blog post on building Python dashboards; previously flagged issues (missing code fences, grammar nit) remain, plus a new pd undefined reference in the database code example.
blog/django-vs-flask-vs-reflex-comparison.md New Django/Flask/Reflex comparison blog; previously flagged product-name inconsistency and "Javacript" typo remain; additionally has a spurious empty 5th column in the side-by-side feature table.
blog/streamlit-vs-dash-python-dashboards.md New Streamlit vs Dash comparison blog; Fortune 500 percentage figures now appear consistent at 40% throughout the file.
pcweb/pages/blog/page.py Adds keyword extraction from meta tags and word-count calculation fed to blog_jsonld for structured data; logic is straightforward and safe.
pcweb/flexdown.py Adds QuoteBlock and TabsBlock block types plus custom markdown table components; no correctness issues found.
pcweb/templates/storypage.py Case study template additions (carousel, more-customers section, blur-layer helpers); no issues identified.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Blog Markdown File] --> B{flexdown parser}
    B --> C["python exec block\n(imports: rx, image_zoom)"]
    B --> D["python eval block\n(uses REFLEX_ASSETS_CDN from env)"]
    B --> E[Markdown / fenced code blocks]
    C --> F[Adds symbols to eval env]
    D --> G[rx.Component rendered inline]
    E --> H[component_map renders headings,\ntables, paragraphs, etc.]
    F --> D
    G --> I[Final page Component]
    H --> I
    I --> J["page() in blog/page.py"]
    J --> K[blog_jsonld structured data\n+ keywords + word_count]
    J --> L[xd2.render → full blog HTML]
Loading

Reviews (3): Last reviewed commit: "Merge branch 'main' into blogs-04-02-26" | Re-trigger Greptile

Comment on lines +75 to +120
import reflex as rx

class DashboardState(rx.State):
revenue_data: list[dict] = [
{"month": "Jan", "amount": 12500},
{"month": "Feb", "amount": 15200},
]
selected_metric: str = "revenue"

State variables become the source of truth. When `selected_metric` changes, every component using that value updates automatically without manual DOM manipulation.

Build the UI by composing components in a Python function. Each component accepts keyword arguments for styling and behavior.
def index():
return rx.vstack(
rx.heading("Revenue Dashboard"),
rx.select(
["revenue", "profit", "costs"],
value=DashboardState.selected_metric,
),
rx.recharts.bar_chart(
rx.recharts.bar(data_key="amount"),
data=DashboardState.revenue_data,
),
)

Run `reflex run` and your dashboard appears at `localhost:3000`. Modify the data in your state class, save the file, and watch the charts update instantly.

## Adding Real-Time Updates Without addEventListener

Real-time dashboards update when data changes. In JavaScript frameworks, you'd attach event listeners, manage WebSocket connections, and manually update DOM elements. Reflex handles this through background tasks and Python's async patterns.

Background tasks run independently without blocking the UI. Decorate an async method with `@rx.event(background=True)` and wrap state mutations in `async with self:` blocks. Each mutation triggers a UI update with the current state, so your dashboard refreshes in real time while the task continues running.
@rx.event(background=True)
async def poll_api_continuously(self):
async with self:
self.monitoring_active = True
for i in range(10):
await asyncio.sleep(1)
async with self:
self.current_value = fetch_latest_data()
yield
The dashboard shows each update as the loop executes. Users see values change every second without you having to write WebSocket handlers or manage connection state.

Start a background task from any regular event handler by returning it as an event reference:
def start_monitoring(self):
return DashboardState.poll_api_continuously
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Code examples missing markdown code fences

The code snippets throughout this blog post are written as plain text paragraphs rather than inside ```python ``` code blocks. This means they will render as continuous prose in the published blog instead of formatted, syntax-highlighted code. All of the following sections are affected:

  • Lines 75–98: DashboardState class and index() function
  • Lines 107–120: background task poll_api_continuously and start_monitoring
  • Lines 127–139: rx.box styling example
  • Lines 146–160: SQLAlchemy DashboardState.load_data and fetch_api_data
  • Lines 167–170: CI/CD GitHub Actions YAML block

Each code example should be wrapped in a fenced code block. Other blog posts in this repo (e.g., blog/reflex-streamlit.md) use ```python exec blocks for executable code and ```python for display examples; this file needs the same treatment.

{"question": "What is Reflex's state management approach and how is it different?", "answer": "Reflex uses Python class-based state management where you define application state in classes and write event handlers as methods. The framework automatically tracks dependencies and updates only affected components through WebSocket synchronization, avoiding both Streamlit's full script reruns and Dash's manual callback wiring."},
{"question": "Why do data science teams struggle when moving Streamlit or Dash prototypes to production?", "answer": "Both frameworks handle the UI layer well for demos but lack authentication, RBAC, secure deployment, and production features that business applications need. Teams end up spending weeks building session management, user databases, and infrastructure that isn't included in the framework. Reflex includes built-in authentication with Clerk, Google Auth, Azure, and OpenID Connect providers, plus RBAC and one-command deployment, so production requirements are covered from day one."},
{"question": "How much code reduction does Reflex provide compared to Dash?", "answer": "Teams building equivalent dashboards in Reflex report approximately 50% less code compared to Dash implementations. The class-based structure and automatic dependency tracking in Reflex eliminate the callback wiring ceremony that accumulates in Dash applications as connected components multiply."},
{"question": "What types of organizations use Reflex for production applications?", "answer": "Finance teams run trading dashboards, healthcare organizations manage patient data, and government agencies deploy internal tools using Reflex. The framework is trusted by 30% of Fortune 500 companies for building production-grade web applications entirely in Python."},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Inconsistent Fortune 500 adoption figure (30% vs 40%)

The same blog post states two different percentages for Reflex's Fortune 500 adoption:

  • Line 45 (TLDR): "trusted by 40% of Fortune 500 companies"
  • Line 26 (FAQ answer): "The framework is trusted by 30% of Fortune 500 companies"

These are contradictory claims in the same published article. Please align both to the authoritative figure. The 40% figure is used consistently in the other two blogs in this PR.

]
faq: [
{"question": "How does Reflex differ from Django and Flask for full stack development?", "answer": "Django and Flask both require JavaScript frameworks like React or Vue for the frontend, splitting your team between Python backend developers and JavaScript frontend specialists. Reflex lets you write both frontend and backend in pure Python, compiling Python code into a React application automatically without touching JavaScript."},
{"question": "Can I deploy Reflex applications in my own infrastructure?", "answer": "Yes, Reflex supports on-premises deployment and VPC options for enterprise security requirements. You can run Reflex Build in your own environment while maintaining full control over data and code, meeting compliance requirements that cloud-only tools cannot satisfy."},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Inconsistent product name: "Reflex Build" vs "Reflex's AI App Builder"

The FAQ frontmatter (line 14) refers to the feature as "Reflex Build":

"You can run Reflex Build in your own environment..."

But the rendered FAQ body (line 163) calls it "Reflex's AI App Builder":

"You can run Reflex's AI App Builder in your own environment..."

Please decide on the canonical product name and use it consistently in both places.

| Frontend Development | Server-side templates with Jinja2 or separate JavaScript frontend using Django REST Framework for API serialization | No opinion on frontend, requiring choice between server-side Jinja2 templates or building separate JavaScript frontend | Pure Python frontend that compiles to React automatically, allowing developers to write UI components and state management entirely in Python | |
| Deployment Complexity | Requires WSGI server setup with Gunicorn, Nginx reverse proxy configuration, manual static file management, and database migration handling | Similar WSGI deployment requirements with lighter resource needs but same manual configuration for web server, static assets, and database connections | Single command deployment with 'reflex deploy' that handles infrastructure provisioning, multi-region scaling, and monitoring automatically | |
| Built-in Features | ORM with automatic migrations, admin interface, user authentication, form validation, security protections against SQL injection and XSS | Werkzeug for WSGI utilities and Jinja2 for templating only, requiring external packages for database, authentication, and form handling | 60+ built-in components, state management through Python classes, event handlers, automatic UI updates, and integrated frontend-backend architecture | |
| Ideal Use Cases | Content management systems, data-intensive applications with complex relational queries, best suited for teams already comfortable managing separate Python backends and Javascript frontends for any interactive or user-facing features | Microservices architectures, API-first projects for mobile apps or SPAs, projects where teams want granular control over dependency selection | Fortune 500 teams and compliance-focused industries (finance, healthcare, government) building enterprise-grade internal tools, interactive dashboards, real-time data visualization, LLM chat apps, and AI-powered workflows entirely in Python, eliminating frontend specialist headcount, maintaining audit-ready codebases, and deploying to on-premises or VPC infrastructure for full data sovereignty | |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Typo: "Javacript" should be "JavaScript"

In the comparison table's "Ideal Use Cases" row for Django, "Javacript" is misspelled.

Suggested change
| Ideal Use Cases | Content management systems, data-intensive applications with complex relational queries, best suited for teams already comfortable managing separate Python backends and Javascript frontends for any interactive or user-facing features | Microservices architectures, API-first projects for mobile apps or SPAs, projects where teams want granular control over dependency selection | Fortune 500 teams and compliance-focused industries (finance, healthcare, government) building enterprise-grade internal tools, interactive dashboards, real-time data visualization, LLM chat apps, and AI-powered workflows entirely in Python, eliminating frontend specialist headcount, maintaining audit-ready codebases, and deploying to on-premises or VPC infrastructure for full data sovereignty | |
| Ideal Use Cases | Content management systems, data-intensive applications with complex relational queries, best suited for teams already comfortable managing separate Python backends and JavaScript frontends for any interactive or user-facing features | Microservices architectures, API-first projects for mobile apps or SPAs, projects where teams want granular control over dependency selection | Fortune 500 teams and compliance-focused industries (finance, healthcare, government) building enterprise-grade internal tools, interactive dashboards, real-time data visualization, LLM chat apps, and AI-powered workflows entirely in Python, eliminating frontend specialist headcount, maintaining audit-ready codebases, and deploying to on-premises or VPC infrastructure for full data sovereignty | |

```python exec
import reflex as rx
from pcweb.components.image_zoom import image_zoom
from pcweb.constants import REFLEX_ASSETS_CDN
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Unused import: REFLEX_ASSETS_CDN

REFLEX_ASSETS_CDN is imported but never referenced in this blog's content — all image src values use full CloudFront URLs directly. The same unused import appears in the other two blog posts added in this PR (django-vs-flask-vs-reflex-comparison.md line 24 and streamlit-vs-dash-python-dashboards.md line 34).

Consider removing it from all three files, or use the constant for the image URLs if that was the original intent.


## Building Your First Dashboard With Pure Python

Build a dashboard with Python couldn't be easier with Reflex.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Minor grammar issue

"Build a dashboard with Python couldn't be easier with Reflex." reads awkwardly.

Suggested change
Build a dashboard with Python couldn't be easier with Reflex.
Building a dashboard with Python couldn't be easier with Reflex.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@tgberkeley
Copy link
Copy Markdown
Collaborator Author

@greptileai

@tgberkeley
Copy link
Copy Markdown
Collaborator Author

@greptileai

@tgberkeley tgberkeley merged commit ca76b5a into main Apr 6, 2026
10 checks passed
@tgberkeley tgberkeley deleted the blogs-04-02-26 branch April 6, 2026 16:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants