HTML-first · SEO-first framework
Real HTML. Zero JavaScript you didn't ask for.
Nexa compiles every page to real HTML — with SEO, i18n and real data — and only ships JavaScript to the nodes that actually need it. No empty bundle just in case.
export const seo = {
title: "My shop",
description: "Running shoes"
};
function sayHi() {
alert("hi from Nexa!");
}
export default function Home() {
return (
<main>
<h1>Welcome</h1>
<button onClick={sayHi}>Say hi</button>
</main>
);
}One project
Web, desktop, Android and iOS — without rewriting anything
The same source code that compiles to real HTML for the web also packages into a real desktop binary or a real mobile app. No separate web build and native build to maintain.
Web
Chrome, Firefox, Safari — the same real HTML as always, indexable and with nothing to install.
nexa buildDesktop
Windows, macOS and Linux with Tauri — a real, runnable desktop binary, built with cargo.
nexa add tauri
cd src-tauri && cargo buildAndroid
A real APK built with Gradle via Capacitor — verified end to end with a real Android SDK.
nexa add capacitor
npx @capacitor/cli add android
cd android && ./gradlew assembleDebugiOS
Same Capacitor mechanism as Android — generates a real Xcode project. Needs macOS to build; not verified in this Linux environment.
npx @capacitor/cli add iosThe real difference
Nexa isn't "another Astro"
Astro, Next.js, Nuxt and SvelteKit already do a great job of "HTML first, JS only where needed". Nexa's difference sits one level deeper: in how that HTML actually gets produced.
How the HTML gets produced
Astro/Next/Nuxt/SvelteKit: to produce the HTML, they literally EXECUTE your code — they run React's, Vue's or Svelte's real renderer on the server, even for 100% static content.
Nexa: the compiler (written in Rust) never executes your code. It's a static analyzer that recognizes a fixed set of patterns in your file (data.x, t("key"), <For each={...}>, export const load/seo) and translates them straight to HTML — no JavaScript runtime involved, not even on the server.
Progressive Activation vs. hydration
Classic hydration: the entire component tree gets re-executed in the browser to "revive" event listeners, even when only one button is actually interactive.
Nexa: every interactive node (every onClick, every island) gets its own id and its own JS chunk, loaded independently with its own strategy (interaction/visible/idle/load/manual). There's no tree to revive — every piece activates itself.
Islands: opaque vs. rendered
Astro islands: they're real React/Vue/Svelte components. Astro's own renderer for that framework produces the island's initial HTML on the server.
Nexa islands: a total black box. The Rust compiler never opens or interprets what's inside — the island's initial HTML is whatever you write by hand (using the same static patterns as any other Nexa page), and the real framework you choose runs 100% on the client, never on the server.
In practice this means you don't have to pick a single paradigm for the whole project: the home page and blog can be pure HTML without a single line of framework code, a form can activate with just @nexa/reactivity, and a complex dashboard can be an island with a full Vue or React app inside — all in the same project, compiled by the same Rust that never needs to understand that Vue or that React.
Advantages
Why Nexa?
Zero JavaScript by default
A page with no interaction compiles to plain HTML. No runtime, no hydration, no empty bundle just in case.
Progressive activation
Every interactive node declares its own strategy: interaction, visible, idle, load, or manual.
Real SEO, not a plugin
Valid title, meta tags, Open Graph and JSON-LD, generated per page — with an analyzer that warns when something's missing.
Islands for what's truly interactive
A dashboard or a complex cart mounts with your favorite framework, without the rest of the site stopping being HTML-first.
Real cache-busting
Every generated file carries a hash of its own content — a redeploy never serves stale JS or CSS from a visitor's cache.
Native packaging
The same project ships a real desktop binary (Tauri) or a real APK (Capacitor), without rewriting anything.
First-class realtime
connectSSE/connectSocket wrap native EventSource/WebSocket in reactive signals — notifications, chat, live dashboards.
Backend-agnostic
load() makes a real HTTP GET against any backend you already have — PHP, Go, Node, whatever. Nexa doesn't impose its own.
About the logo
The lotus at the center is purity and rebirth, the same symbol from Nezha's (哪吒) myth. Around it, a single wheel of fire evokes his wind-fire wheels and divine momentum. Jade, gold and red connect the mythical with the modern.