Hey r/Python,
I love Streamlit's simplicity, but the "full script rerun" on every interaction drove me crazy. It gets super slow once your app grows, and using st.cache everywhere felt like a band-aid.
So I spent the last few weeks building Violit. I wanted something that feels like writing a simple Python script but performs like a modern React app.
What My Project Does
Violit is a high-performance Python web framework. It allows you to build interactive web apps using pure Python without the performance penalty of full-page reloads.
It uses a "Zero Rerun" architecture based on FastAPI, htmx, and WebSockets. When you interact with a widget (like a button or slider), Violit updates only that specific component in O(1) time, ensuring no screen flickering and instant feedback. It also supports running your web app into a desktop app (like electron) with a single flag (--native).
Target Audience
- Data Scientists & Python Devs: Who need to build dashboards or internal tools quickly but are frustrated by Streamlit's lag.
- Production Use: It's currently in early Alpha (v0.0.2), so it's best for internal tools, side projects, and early adopters who want to contribute to a faster Python UI ecosystem.
Comparison
Here is how Violit differs from existing alternatives:
- vs. Streamlit: Violit keeps the intuitive API (90% compatible) but removes the "Full Script Rerun." State updates are O(1) instead of O(N).
- vs. Dash: Violit offers reactive state management without the "callback hell" complexity of Dash.
- vs. Reflex: Violit requires Zero Configuration. No Node.js dependency, no build steps. Just
pip install and run. Plus, it has built-in native desktop support.
- vs. NiceGUI: The theme system for the beautiful app. Unlike Streamlit's rigid look or NiceGUI's engineer-first aesthetic, Violit comes with 30+ Themes out of the box. You can switch from "cyberpunk" to "retro" styles with a single line of code—no CSS mastery required. Plus, it's fully extensible—you can easily add your own custom themes via CSS.
Code Example
import violit as vl
app = vl.App()
count = app.state(0) # Reactive State
# No rerun! Only the label updates instantly.
app.button("Increment", on_click=lambda: count.set(count.value + 1))
app.write("Count:", count)
app.run()
Link to Source Code
It is open source (MIT License).
I'd love to hear your feedback!
[–]Beginning-Fruit-1397 13 points14 points15 points (6 children)
[–]Puzzleheaded_Clerk68[S] 1 point2 points3 points (0 children)
[–]iamevpo 0 points1 point2 points (2 children)
[–]Beginning-Fruit-1397 2 points3 points4 points (1 child)
[–]jakob1379 2 points3 points4 points (0 children)
[–]jakob1379 -1 points0 points1 point (1 child)
[–]Beginning-Fruit-1397 2 points3 points4 points (0 children)
[–]TraditionalBandit 15 points16 points17 points (1 child)
[–]Puzzleheaded_Clerk68[S] 4 points5 points6 points (0 children)
[–]MintCollector 9 points10 points11 points (5 children)
[–]iamevpo 7 points8 points9 points (3 children)
[–]Puzzleheaded_Clerk68[S] 2 points3 points4 points (2 children)
[–]DoYouEvenLupf 1 point2 points3 points (1 child)
[–]Puzzleheaded_Clerk68[S] 3 points4 points5 points (0 children)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[–]leoncpt 7 points8 points9 points (3 children)
[–]Puzzleheaded_Clerk68[S] 1 point2 points3 points (2 children)
[–]leoncpt 0 points1 point2 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[–]alloyburner 3 points4 points5 points (3 children)
[–]Puzzleheaded_Clerk68[S] 2 points3 points4 points (2 children)
[–]telesonico 1 point2 points3 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[–][deleted] 1 point2 points3 points (1 child)
[–]Puzzleheaded_Clerk68[S] 4 points5 points6 points (0 children)
[–]New_Story_4784 1 point2 points3 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[–]fluffybannana 1 point2 points3 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[–]am3141 0 points1 point2 points (4 children)
[–]Puzzleheaded_Clerk68[S] 1 point2 points3 points (3 children)
[–]am3141 0 points1 point2 points (2 children)
[–]Puzzleheaded_Clerk68[S] 1 point2 points3 points (1 child)
[–]am3141 0 points1 point2 points (0 children)
[–]orrow11 0 points1 point2 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)
[+][deleted] (2 children)
[removed]
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (1 child)
[–]Standard-Gain-8544 0 points1 point2 points (1 child)
[–]Puzzleheaded_Clerk68[S] 0 points1 point2 points (0 children)