Show HN: Proa – A Rust web framework with fast SSR and multi-target rendering
proa.soVideo: https://youtu.be/-CfCyvIKYyo?si=hCLuStkXxanCUJD1
Video on multi-target rendering: https://youtu.be/pJx84jdBDKU?si=HRRd6dgUWXiqeWhq
Benchmarks: https://github.com/Proa-Labs/proa-benchmarks
I've been eyeing this since you posted it yesterday, and I hadn't seen the Pro UI stuff until someone here pointed it out.
I have to say that $2000 UI components is enough for me to look for something else instead, even with the free tier being so generous today. I understand the desire the earn money from hard work, but that's exactly why I would be wary of the free tier getting smaller and smaller over time, or essentially being abandoned.
I'm not saying I'd never adopt it. But that Pro UI situation would make me wait years before even considering it. And with AI the way it is, I expect to see a lot of alternatives that are similar soon, and perhaps they meet my needs better, too.
I was going to wait a while anyhow, but now that wait time will be a lot longer.
I was recently scanning for newer, more-batteries-included options and this looks well-scoped at first bluff. Thanks for spreading it, might end up in my next experiment!
That's very kind of you, thank you! Yes the goal is to make it usable in production! It already powers proa.so, ui.proa.so, latency.so, and a few other sites. Let me know when you build it and I can add it to https://proa.so/ecosystem/apps!
I remember a friendly member around here recently remarking that rustc is a high quality project, with lots of eyes on it and lots of effort put into it.
And then this shows up.
https://github.com/rust-lang/rust/issues/164348#issuecomment...
A bug as careless as can be. Relying wantonly on hashing for equality checking, without even wondering about the specific hash's collision probability.
I think you were meaning to reply to another comment?
Man, that video was a pleasure to watch
that's very kind of you! thank you
I'm going to be making more in the future so make sure to subscribe!
This might be a silly question, but why 2 views for html and markdown? isn't there a broad base of cases where one can just be inferred from the other?
Also, I think it's exciting to see so many rust web frameworks popping up but I'm in total decision paralysis. If I want to build something with rust now there are at least 3 complete frameworks: loco, topcoat and now proa... plus actix, rocket, axum, and ...more?
> This might be a silly question, but why 2 views for html and markdown?
No such thing as silly questions! Yes there are cases where it can be inferred from one to the other, but in many cases you may want to be very specific about how you author the markdown view. I'll give you a few examples:
1. Custom components: For example, let's say you have a carousel component. It's not really straightforward to infer the markdown from this. But you probably want the carousel to render as a series of markdown image tags. A custom view would be helpful for this. Same goes for Calendars, SVG charts, Diagrams, form inputs, tabs, popovers, and more.
2. Information omission: Agents don't need all of the information on your page. For example, a dark/light button... probably doesn't need a markdown equivalent. But a button that is an anchor tag that links to another page, probably you should keep. So having the ability to custom author the markdown render target based on the data it's rendering is helpful.
One of the unique aspects of Proa's authoring model is that it supports composability of Markdown components, just like JSX, which is I think one of its standout features. And you can embed native control flow (if, loops, match, etc.) directly in the md!{} macro just like you could with JSX. https://www.youtube.com/watch?v=pJx84jdBDKU&t=21s explains it quite well if you're interested. Makes the readability and code ergonomics much much better.
> it's exciting to see so many rust web frameworks popping up but I'm in total decision paralysis.
I am a bit biased here but I think Proa is the most complete framework currently for building a production web application in Rust. I know its newer and doesn't have as many stars, but maybe I can point you to three things to see if it gives you more confidence:
1. Data loading: https://proa.so/docs/framework/data-loading 2. Browser interactivity: https://proa.so/docs/rsjs/signals (all in rust btw) 3. Security: https://proa.so/docs/framework/security-headers
Proa, Proa UI, latency.so, and a few other sites are all using Proa in production. It's the fastest SSR framework in production (https://github.com/Proa-Labs/proa-benchmarks) and supports streaming SSR (checkout the streaming SSR benchmark), suspense, etc. And it's server framework agnostic so you can use it with actix, axum, and other frameworks if you want.
Ah ok so it's more of the ui layer? because when I look at for instance loco, it handles background jobs, emails, auth - it's a battery included framework. So proa is something that could be used in place of askama + htmx but still with another full featured (or totally minimal) framework?
It's funny, my first thought with multiple render paths was specifically for htmx integrations... Such as a full render or just a main component render. There are extensions for C#/razor that with really well for this.
Would be cool to do the same with rust. That said, I didn't know how hard that would be with this framework. There are of course a lot of different limitations with ssr vs soa.
Very cool idea, I'm going to test this!
One nit: Forgive me if I'm missing something but why do you have pro components? Won't people vibe-code clones anyway? I'd rather have a donate button these days.
Hey! Author of Proa here, thanks for checking it out! The idea is to just accelerate the time it takes to create components, similar to Shadcn or other component libraries. You can create a new component and modify them however you like. It’s nice because they have both the WebRender and MdRender trait implemented, and saves you a bit of time. Also for slightly more complex components like Calendar, we’ve crafted the component with all the JS interactivity required to do things like switch months, select start and end date, etc
You answered "Why do you have a component library?" but I think the original question was more along the lines of "Why bother monetizing components that can be copyright-washed in minutes with LLMs instead of having a Donations funnel?"
Aren't Pro components the same as a donation, but then giving you something extra as well.
Kind of, not really, in this case it's a subscription that renews monthly/yearly so you have to remember to cancel it when your reach the amount you wanted to donate, maybe you didn't want to donate as much as 1 month costs so you're left not sending them any money in the end, right now you can't even subscribe cause their console 404's. You got to make it as easy as possible for people to part with their money, component library subscription is not it.
In any corporate structure it's 10000x easier to get approved to just buy something from a vendor than it is to set up donations for an open-source project/foundation.
PLus you're missing the licensing aspect, part of this is AGPL if you use the free version, lots of places are happy to throw down money to get a commercial license rather than hem and haw over AGPL.
This looks really cool! I’ve been really appreciating the revival of old-school server side rendering and foundational web components, but with modern tools or approaches.
That's very kind of you, appreciate it man! Thanks!
Damn, projects like these really spark my curiosity about Rust. I guess it's time to try it out, fomo is getting too big haha
I highly recommend! I've been writing Rust professionally for 5 years now. Compile times are slow but I love the language. https://cheats.rs/ is a resource i go back to often in case you're interested in learning more. Especially since as you get more into it, Rust has a lot of weird types like RefCell and Cell and OnceCell and disambiguating between them is a chore sometimes. Hope it helps!
It's painful at first and then a pleasure forever after.
Why does `fn render` need to borrow WebContext mutably?
Hey great question! WebContext owns an output buffer (i.e., RenderBuffer) that components write HTML into directly, avoiding intermediate allocations and copying. It needs to be mutable for this reason. This is one of the key ways we're able to make Proa the fastest server-side rendering engine on the market.
By default, WebContext composes RenderBuffer (but it can be overriden via generics) which uses fixed-size 4 KiB pages. When a page runs out of room, it adds another page without moving the HTML already written. This avoids copying the accumulated output during growth! Its designed to be a performance improvement over Vec<u8>
For context, the problem with Vec<u8> is that every time a vector reaches maximum capacity, it has to reallocate a new area of memory (typically 2x larger than the previous allocation) and then copy everything into that new buffer. This adds a ton of overhead, especially if you're writing large pages.
Checkout https://github.com/Proa-Labs/proa/blob/384136f87fc9f91747477... if you're curious about RenderBuffer's design
Great answer! Thanks
Can I get a TLDR of why Proa is seemingly so much faster tha existing Rust web frameworks (Dioxus, Leptos, Topcoat)?
I can't speak for the others as I am not as familiar with how they're engineered, but with Proa I spent a painstaking amount of time to try and move as much of the work to compile time as possible and being really careful about how memory is allocated. And a lot of those small improvements add up over time!
I would be mostly curious about CI/CD and build and deployment times on underpowered compute instances
I could drop the react ecosystem given considerable improvement over it at the deployment part
Especially since years of experience with frameworks doesnt matter anymore and won’t matter with recruitment soon
Compile times generally take longer with Rust. It's a trade-off you're making when using anything rust related, but in exchange, you get some pretty sweet runtime perf. But with efficient caching of crates you can claw back a lot of time in CI.
what is this compiling down to in the browser?
doesnt that determine runtime performance for web apps, unless the browser is running rust natively or maybe wasm, I don’t see how javascript for example would be more performant just because I configured it in rust
So... Multi-target = {chat, web, markdown}; Audience = {human, bot}; USPs = {speed, unified model}
Since I don't believe the maintenance challenges of a non-unified model are particularly high-friction in the LLM era (even if they may be error-prone, since that is usually solved with CI/CD or TDD), the nominal utility of this angle of architectural enhancement is considered dubious.
With regard to speed, there is no hardware shortage at present for any of these simple rendering tasks.
Overall, a nice efficient codebase but suffering a bit from NIH syndrome solving no particularly acute problem. Unless a community forms rapidly, this will probably die.
I'd like to see the benchmark compared to, eg. static files served with binserve.
This looks amazing, really appreciate your minimal JavaScript approach. I’ll definitely try it out, could see myself potentially doing pro version in future.
Thank you so much, that's very kind of you! Sounds great! Please feel free to provide any feedback or ways I can make it better for you.