Proa UI
Quickstart
Add Proa UI to a Proa site and render your first component in five minutes.
This quickstart takes a new Proa site from its starter page to a styled, server-rendered Proa UI component. Allow about five minutes once Rust and the Proa CLI are ready.
1. Install Proa
Install the CLI with the platform installer.
curl --proto '=https' --tlsv1.2 -sSf https://proa.so/install.sh | sh
irm https://proa.so/install.ps1 | iex
Prefer building from source?
cargo install --git https://github.com/proa-labs/proa --locked proa-cli
Pin a specific version?
curl --proto '=https' --tlsv1.2 -sSf https://proa.so/install.sh | PROA_VERSION=0.1.0 sh
2. Create A Site
Scaffold a site and enter its directory:
proa new site hello-proa --template marketing --docs proa_docs --tailwind --yes
cd hello-proa
The generated Axum site already has the render, route, static-file, and asset build boundaries Proa UI needs:
Cargo.tomlproa.config.jsonproa.lock.jsonbuild.rsREADME.mdAGENTS.md.cargo/config.tomlscripts/dev.shwatch-lock.shsrc/components/data/docs/layouts/pages/main.rsstatic_assets.rspublic/favicon.svgstyles.cssstyles/input.csstailwind.config.cjspaths.components defaults to src/components, so both individual components
and complete blocks become ordinary modules in your app. paths.assets
defaults to public/proa, which the generated static-file service mounts at
/static, so installed CSS and JavaScript are reachable at /static/proa/...
with no changes.
The --tailwind flag configures an asset build that shells out to a
tailwindcss binary on your PATH. Install the standalone
CLI, which needs no
Node.js, or install Tailwind into the project and point the asset at it:
npm install -D tailwindcss @tailwindcss/cli
{ "command": ["./node_modules/.bin/tailwindcss", "-i", "styles/input.css", "-o", "public/styles.css"] }
Install it into the project rather than running npx @tailwindcss/cli: npx
resolves the CLI in a temporary directory, so @import "tailwindcss" in
styles/input.css fails with Can't resolve 'tailwindcss'.
Scaffold with --no-tailwind to skip the asset entirely. Component recipes are
Tailwind utility classes, though, so a project without a Tailwind build renders
them with colours but no spacing or radius.
Checkpoint: Cargo.toml, proa.config.json, src/pages/home.rs, and
src/layouts/root.rs should exist.
3. Add A Component
Install the Free Button component from the public @proa registry:
proa ui add button
The CLI verifies every downloaded file by SHA-256, installs Button and its
dependency closure directly into your app, adds the framework dependencies the
source needs to the root Cargo.toml, copies the reviewed runtime assets, and
records the transaction in proa.lock.json. Published installs contain
production source only—component test modules are not copied. Button pulls in
foundation and spinner, so the command reports three registry items.
Running the command again is idempotent: it rewrites nothing and reports every
file as already current. To reinstall after deleting installed files or moving
paths.assets, pass --force.
src/components/_proa/button/spinner/mod.rspublic/proa/proa-ui/proa-free.cssproa-free.jsproa.lock.jsonFree installs are anonymous and use source licensed under MIT OR
Apache-2.0. Pro components resolve through the private @proa-pro registry
and require an active Proa UI Pro entitlement and registry token.
Preview the install first?
proa ui add button --dry-run
proa ui add button --json
--dry-run verifies the whole transaction without changing the project.
--json returns the same plan in a machine-readable form.
Using a custom registry?
The default @proa entry points to
https://ui.proa.so/r/{name}.json. Replace that template in
proa.config.json for a local or self-hosted publication. The CLI accepts
local paths, file:// URLs, HTTPS, and localhost HTTP fixtures.
Blocks use the same command and sit at the same level. For example:
proa ui add login
src/components/button/card/input/login/mod.rsThe block manifest installs its component dependency closure automatically.
4. Run The Server
bash scripts/dev.sh
Open http://localhost:3000. The development script builds configured assets, starts the Axum server, and restarts when Rust, documentation, or styles change.
5. Render The Button
Open src/layouts/root.rs. Add the Proa UI stylesheet and runtime next to the
generated site stylesheet:
<link rel="stylesheet" href="/static/styles.css" />
<link rel="stylesheet" href="/static/proa/proa-ui/proa-free.css" />
<script src="/static/proa/proa-ui/proa-free.js" defer></script>
Then open src/pages/home.rs, import the Button API, and replace the starter
content inside HomePage::render:
use crate::components::{Button, ButtonColor, ButtonSize, ButtonVariant};
html_sync! {
<main class="mx-auto max-w-4xl px-6 py-16">
<p class="font-mono text-sm uppercase tracking-[0.18em] text-zinc-500">"Proa UI"</p>
<h1 class="mt-4 text-5xl font-semibold tracking-[-0.04em]">
"Typed components, rendered in Rust"
</h1>
<p class="mt-4 text-lg leading-8 text-zinc-600">
"The button below is a Rust value in a compiled HTML template."
</p>
<div class="mt-8">
{Button {
color: Some(ButtonColor::Primary),
variant: Some(ButtonVariant::Solid),
size: Some(ButtonSize::Lg),
children: Some("Create a project"),
..Button::default()
}}
</div>
</main>
}
.render(cx)
Refresh the browser. The page is still rendered entirely on the server; the
Button is a typed struct composed directly into html_sync!. Its variant
fields are checked by Rust, while the installed stylesheet supplies its visual
recipe.
Checkpoint: the page shows a styled primary button and the rendered element
has data-button, data-scope="button", and data-part="root" attributes.
6. Validate Before Moving On
Run Proa's source-aware checks, then validate the linked application:
proa fmt --check --verify src
proa lint src --deny warnings
proa build
proa fmt --check --verify confirms canonical template formatting without
changing rendered output. proa lint follows render paths and catches
allocation or async-render mistakes that ordinary Rust linting cannot see.
proa build then checks the complete application and its configured assets.
Next steps
- Components
- Browse every component live and copy the install command or Rust source.
- Composition
- Nest components, text, and compiled fragments through typed children.
- Styling and variants
- Change recipes, design tokens, and strongly typed variant axes.
- Interactivity
- Choose native controls, the delegated runtime, or an rsjs controlled component.
- API reference
- Look up public structs, enums, feature flags, and stable data attributes.