Using no_std
Ratatui is no_std-compatible, which allows it to run in embedded and other resource-constrained
environments. This means you can run TUIs on a wider range of targets and have widget usable in both
desktop and embedded environments.
Using Ratatui without std
Section titled “Using Ratatui without std”- Disable default features so the crate does not pull in
std-only dependencies:
ratatui = { version = "0.30", default-features = false }- Choose a backend that works on your platform.
The built-in backends rely on std, so no_std targets need a custom backend that implements
ratatui::backend::Backend or a third-party option like mousefood 🧀
- When checking a
no_stdbuild, compile with ano_stdtarget.
For example, on ESP32:
cargo check --target riscv32imc-unknown-none-elfCreating no_std widgets
Section titled “Creating no_std widgets”If you already have a Ratatui widget, you can make it no_std-compatible with a few small changes.
Even if you haven’t built for embedded before!
-
Opt into
no_stdand addalloccrate:lib.rs #![no_std]extern crate alloc; -
Depend on
ratatui-coreinstead of the fullratatuicrate to avoid backend dependencies:ratatui-core = { version = "0.30", default-features = false } -
Swap
stdtypes for theircore/allocequivalents, for examplecore::fmt,alloc::string::String,alloc::vec::Vec, andalloc::boxed::Box. -
Keep a
stdfeature (off by default) for conveniences like tests or examples, but write your core widget logic so it also works without it. -
Avoid
std-only APIs in widget code paths. Examples: usecore::time::Durationinstead ofstd::time::Duration, pass in data rather than reading files, and keep logging behind a feature so it can be disabled on targets without I/O.
Here is a minimal no_std widget implementation:
#![no_std]extern crate alloc;
use alloc::string::String;
use ratatui_core::buffer::Buffer;use ratatui_core::layout::Rect;use ratatui_core::text::Line;use ratatui_core::widgets::Widget;
struct Greeting { message: String,}
impl Widget for &Greeting { fn render(self, area: Rect, buf: &mut Buffer) { Line::raw(&self.message).render(area, buf); }}