Leptos 0.8 + tailwind4 + daisyUI5 for easy websites

As a follow-up from my Full stack with Rust: axum + leptos + tailwind.css post, in this entry we'll update it to the new tailwind4 and we'll add daisyUI for easier themes and some useful pre-built components.

What you need to do will change depending if you use trunk (for CSR) or cargo watch (for SSR).

Trunk config (CSR)

As before we'll start from a template, for example this start-trunk

cargo install cargo-generate trunk leptosfmt
cargo generate --git https://github.com/leptos-rs/start-trunk
cd {your_project}

Update index.html to remove the existing css link and add the following

<link data-trunk rel="tailwind-css" href="tailwind.css" />

And update Trunk.toml to use the correct tailwind version

[tools]
tailwindcss = "4.1.10"

Server side rendering (cargo watch)

cargo install cargo-generate trunk leptosfmt
cargo generate --git https://github.com/leptos-rs/start-axum-workspace
cd {your_project}

Update Cargo.toml

[[workspace.metadata.leptos]]
...
# style-file = ""  # Remove this line
tailwind-input-file = "./tailwind.css"

And that's really it for the config. Pretty simple.

Final thing: add our tailwindcss and homepage

Create tailwind.css file

@import 'tailwindcss';
@plugin "@tailwindcss/typography";

@source "./src/**/*.rs";

@plugin "daisyui" {
  themes: light --default, dark --prefersdark, cupcake;
}

Update src/pages/home.rs for CSR app and app/src/lib.rs for SSR to add the following component.


#[component]
pub fn Home() -> impl IntoView {
    let count = RwSignal::new(0);
    view! {
        <div class="container gap-6 grid grid-cols-1 pt-20 mx-auto text-center">

            <h1 class="text-6xl tracking-wide">"Welcome to Leptos"</h1>

            <div class="mx-auto">
                <label class="flex cursor-pointer gap-2">
                    <span class="label-text">Current</span>
                    <input type="checkbox" value="cupcake" class="toggle theme-controller" />
                    <span class="label-text">Cupckake</span>
                </label>
            </div>

            <div>
                <button
                    class="btn btn-primary my-4"
                    on:click=move |_| *count.write() += 1
                >
                    Click me
                    {count}
                </button>

            </div>
            <div>
                <button class="btn" onclick="my_modal_1.showModal()">
                    open modal
                </button>
                <dialog id="my_modal_1" class="modal">
                    <div class="modal-box">
                        <h3 class="text-lg font-bold">Hello!</h3>
                        <p class="py-4">Press ESC key or click the button below to close</p>
                        <div class="modal-action">
                            <form method="dialog">
                                <button class="btn">Close</button>
                            </form>
                        </div>
                    </div>
                </dialog>
            </div>
        </div>
    }
}

And now use either trunk serve or cargo leptos watch to spin up the page.