topcoat README

The project's README from github.com/tokio-rs/topcoat. As one markdown file: README.md.

Topcoat

The full full-stack framework for Rust

Crates.io Docs.rs MIT licensed Build Status Discord chat

Topcoat is a modular, batteries-included Rust framework for building full-stack apps. It prioritizes simplicity and productivity. See Learn Topcoat to get started, or the Roadmap for what's coming next.

Early-stage and experimental. Expect breaking changes.

use topcoat::{
    Result,
    router::{Router, RouterBuilderDiscoverExt, page},
    view::{View, component, view},
};

#[tokio::main]
async fn main() {
    topcoat::start(Router::builder().discover().build()).await.unwrap();
}

#[page("/")]
async fn home() -> Result<impl View> {
    Ok(view! {
        <!DOCTYPE html>
        <html>
            <body>
                hello(name: "World")
            </body>
        </html>
    })
}

#[component]
async fn hello(name: &str) -> Result<impl View> {
    Ok(view! { <h1>"Hello, " (name) "!"</h1> })
}

What makes Topcoat different

Client reactivity without the boilerplate

Topcoat renders all markup on the server: components can be async and query the database directly, eliminating all the traditional boilerplate needed for a separate API layer. Interactivity does not have to cost a round-trip, though. A $(...) expression is ordinary type-checked Rust that Topcoat evaluates on the server for the initial render and also translates to JavaScript, so it re-runs instantly in the browser. No wasm bundle, no client build step:

#[component]
async fn faq(cx: &Cx) -> Result<impl View> {
    let open = signal(cx, || false);

    Ok(view! {
        // Runs entirely in the browser; no server round-trip.
        <button @click=$(|_e| open.set(!open.get()))>"What is Topcoat?"</button>
        <p :hidden=$(!open.get())>"A full-stack Rust framework."</p>
    })
}

When an update does need the server, like fresh search results, mark the component as a #[shard]. Topcoat re-renders it on the server whenever one of its $(...) arguments changes and swaps the new HTML in place:

#[component]
async fn search(cx: &Cx) -> Result<impl View> {
    let query = signal(cx, String::new);

    Ok(view! {
        <input @input=$(|e: Event| query.set(e.target.value))>

        // Updates as the user types.
        search_results(query: $(query.get()))
    })
}

#[shard]
async fn search_results(cx: &Cx, query: String) -> Result<impl View> {
    Ok(view! {
        <ul>
            // Your own server-side code, like a database query:
            for product in search_products(cx, &query).await? {
                <li>(product.name)</li>
            }
        </ul>
    })
}

Powerful, unsurprising HTML templates

The view! macro stays true to HTML and Rust. Use familiar Rust control flow as part of your templates:

view! {
    <nav>
        for item in nav_items {
            <a
                href=(item.url)
                if item.url == current_path {
                    aria-current="page"
                    class="active"
                }
            >
                (item.label)
            </a>
        }
    </nav>
}

Use the topcoat fmt CLI command to automatically format view! snippets (and other macros) across your codebase.

Module-based routing

Topcoat can optionally infer your route tree from your app's module structure (without a build step):

src/
|-- app.rs              -> /            (and the root <html> layout)
`-- app/
    |-- about.rs        -> /about
    |-- _marketing.rs                  (layout, no URL segment)
    |-- _marketing/
    |   `-- pricing.rs  -> /pricing
    |-- posts.rs        -> /posts
    |-- posts/
    |   `-- id.rs       -> /posts/{post_id}
    `-- api/
        `-- health.rs   -> GET /api/health

Premade components you can edit

Topcoat UI is a component library based on Tailwind inspired by shadcn/ui. Components are copied into your project via the topcoat ui CLI command, meaning you can freely change their design and functionality to fit your use case:

#[component]
async fn delete_card() -> Result<impl View> {
    Ok(view! {
        card(
            card_header(
                card_title("Delete workspace")
                card_description(
                    "This permanently removes the workspace and all of its data."
                )
            )
            card_footer(
                attrs: attributes! { class="justify-end" },
                button(variant: ButtonVariant::Ghost, "Cancel")
                button(variant: ButtonVariant::Destructive, "Delete workspace")
            )
        )
    })
}

Asset bundling

The bundler scans your compiled binary for asset! calls, copies (or even downloads) every file into a local asset directory, and allows Topcoat to serve them efficiently with aggressive browser caching.

const FERRIS: Asset = asset!("./ferris.png");

view! { <img src=(FERRIS)> }

Topcoat also ships with utilities for web fonts and icons, as well as easy integrations for Fontsource (Google Fonts) and Iconify.

Built-in Tailwind support

Enable the tailwind feature to integrate Tailwind into your project:

view! { <link rel="stylesheet" href=(topcoat::tailwind::stylesheet!())> }

Learn Topcoat

Start here

Rendering

Routing

Working with requests

Asset system

Client reactivity

Miscellaneous

Third-party integrations

Roadmap

Planned features we'd like to bring to Topcoat. Have an idea? Open an issue.

topcoat (tokio-rs/topcoat)

Searching Database…

6.1K ·GitHub
这是什么?Topcoat 是一个功能齐全、模块化的 Rust 框架,用于构建全栈 Web 应用。组件在服务器端渲染,并且可以直接查询数据库。
它和常见的 Rust Web 框架有什么不同?Topcoat 在服务器端渲染所有标记,组件可以是异步的并直接查询数据库,因此无需单独的 API 层。它的 $(...) 表达式就是普通的 Rust 代码,也能在浏览器中运行,不需要 wasm 包,也不需要客户端构建步骤。
我该如何运行 Topcoat 项目?按照入门指南创建新项目、安装 Topcoat CLI,然后运行开发服务器即可。
响应式部分是否需要 Node.js 或单独的 JS 构建步骤?不需要。$(...) 表达式是普通的 Rust 代码,Topcoat 在服务器端对其求值,同时也会自行将其转换为 JavaScript,因此既没有 wasm 包,也没有客户端构建步骤。此外,还可以通过内置的功能开关启用 Tailwind。
Topcoat 可以用于生产环境吗?不能。项目明确表示自己仍处于早期阶段、属于实验性质,并且应当预期会出现破坏性变更。
Topcoat 中的 “shards” 是什么?Shards 是标有 #[shard] 的组件。只要其中某个 $(...) 参数发生变化,Topcoat 就会在服务器端重新渲染它,并将新的 HTML 原地替换到页面中。
什么是 Topcoat UI?Topcoat UI 是一个基于 Tailwind 的组件库,灵感来自 shadcn/ui。通过 topcoat ui CLI 命令,组件会被复制到你的项目中,因此你可以自由修改它们的设计和行为。
路由能否无需手动配置?可以。Topcoat 可以选择直接从应用的模块结构推断出完整的路由树,无需任何构建步骤。
Topcoat 现在支持身份验证了吗?还不完整。它目前已内置基于会话的身份验证,支持登录/登出、滑动过期和令牌轮换,但完整的身份验证支持和验证功能仍在路线图中。
Creator
tokio-rs
Size
6.9 MB
Stars
6.1K
Age
6mo
Commits · 90 Days