Building apps in Rust is supposed to be the future. But for anyone who's actually tried to build a real application — not a toy, not a CLI tool, but something with a UI — you know the pain.

This week, Ply 1.0 landed, and it's the most honest Rust framework story I've read in a while.

The Problem Every Rust Developer Knows

The author wanted to build a multiplayer board game. Server, client, shared game logic — all in Rust. Clean architecture, full control. Sounds reasonable.

Then the wall.

Bevy crams you into an ECS that turns simple things into thousands of lines of virtual database queries. Its UI system is macro-and-node-based with impl Bundle and ..default() everywhere. The architecture wouldn't work with what he'd spent weeks building for the server.

Iced looked promising until the code: ..default() everywhere. .into() on every line. The nesting is unclear and everything reads backwards — where the top element ends up at the bottom.

egui was better, but you're manually calling .add_space() for gaps and allocating rects. Fine for simple UIs. For a real app? Exhausting.

Slint impressed with clean nesting, but it's a separate markup language. You can't cleanly integrate it into Rust. Parent width references and <real> declarations don't belong in a Rust codebase.

Macroquad — inspired by Love2D's simplicity — felt close. But it's a rendering library, not an app engine. No layout system, no text input, no UI structure. You'd be building years of infrastructure on top of it.

And this isn't a niche complaint. Search any Rust UI forum. You'll find the same stories, the same workarounds, the same resigned acceptance of "good enough."

What Ply Does Differently

The author spent months on Clayquad (Macroquad + Clay layout bindings), then hit hard limits:

So he built Ply. The philosophy is worth understanding:

Closures cure the .end() problem. Instead of chaining .end() calls or deep indentation for every nested element, you use closures. The UI reads naturally.

Builder pattern with Into<T> everywhere. When .background_color() accepts Into<Color>, it takes hex integers, float tuples, or macroquad colors. No hex_to_macroquad_color!() wrappers.

Immediate-mode rendering. Rebuilding the UI every frame sounds wasteful, but it's actually faster than tracking mutations. The layout takes a fraction of a percent of total frame time. You have to redraw every frame anyway.

Managers for everything. TEXTURE_MANAGER, MATERIAL_MANAGER, FONT_MANAGER, NET_MANAGER. Everything runs in a loop, and there are few good ways to persist state between iterations. The managers handle caching, eviction, and lifetime automatically.

What 1.0 Ships With

The interactive docs alone — with live code playgrounds where you can tweak values and see results instantly — put it ahead of most Rust projects.

Why This Matters

This is the most honest framework launch I've seen in the Rust ecosystem. No "we're 10x faster" benchmarks. No "AI-powered" marketing. Just: everything else failed, so I built what I needed.

The result is genuinely innovative. Not because it's the most feature-complete — it's 1.0, so it's growing. But because it solves real problems that other frameworks refuse to acknowledge exist.

cargo install plyx
plyx init

Two commands to get an app with a Google Font, feature flags, and a project structure.

The source is on GitHub under Zero-Clause BSD. Use it for anything, no attribution required.

Go build something.