The internet has a bad habit of defaulting to React for everything. Your marketing site becomes a SPA (single-page app) by reflex. A 250kb JavaScript bundle loads on every page view. Users on 4G networks wait three seconds for a form to be interactive. Lighthouse scores crater. SEO gets weird. And then you realize: this site is 90% static content. You didn't need React. You needed htmx.
htmx is having a moment because it solves a real problem: dynamic HTML without the framework tax. 8kb of JavaScript that lets your server render HTML and swap it into the DOM. Forms submit without full-page reloads. Dropdowns fetch live data. Infinite scroll works. All from the server, all from static HTML. No build tool, no JavaScript bundle, no framework boilerplate. Astro (which powers this site and Velocity X) takes it further: static HTML on first load, React islands only where state actually lives. This is the philosophy that wins.
What htmx Actually Is
htmx isn't a framework. It's a library that adds HTML attributes to your markup. <button hx-post="/form">Submit</button> replaces the default form submit with an AJAX request. The server returns HTML. htmx swaps it into the DOM. Done. No JavaScript written, no state management, no component lifecycle. Just attributes and a server that understands them.
The core idea: extend HTML with request attributes (hx-get, hx-post, hx-put, hx-delete), swap targets (hx-target), and triggers (hx-trigger). A dropdown that fetches options on focus: <select hx-get="/api/options" hx-trigger="focus">. An infinite-scroll list: <div hx-get="/next-page" hx-trigger="revealed">. A search box that filters results live: <input hx-post="/search" hx-target="#results">. Server renders HTML. htmx swaps it. Browser renders it. No JavaScript framework involved.
The Bundle Size Reality Check
React 19: ~42kb (production minified). React Router: ~15kb. State manager (Zustand): ~3kb. Build toolchain (Vite, webpack): hundreds of kb of node_modules. Total payload to ship: 250kb+ to the browser. Then you hydrate. Then you wait for interactive. Then navigation is instant (if you wired up client-side routing). Still fast by 2010 standards, glacial by 2026 standards when marketing sites should load in under 1 second on 4G.
htmx: 8kb uncompressed. Gzip it: 3kb. No build step. No hydration delay. No JavaScript runtime overhead. Server renders static HTML. htmx adds interactivity on top. First paint: ~500ms on a 4G connection for a 50kb HTML document. htmx interactive: immediate, because the library is already there. The math is brutal: htmx is 30× smaller than React and solves 95% of marketing-site use cases.
When to Use htmx vs React vs Astro
htmx: Server-driven sites with interactive forms, live search, filters, modals, tabs. Rails, Django, Express, Laravel. Build-free. Pair with a server that renders HTML (Jinja, ERB, Blade). Use when your server is already rendering HTML and you need to add interactivity without shipping JavaScript.
React: Apps that own their state. Dashboards, calendars, collaborative tools, rich editors. Heavy client-side logic. Use when the browser IS the app. Not a marketing site. Not a blog. Not a brochure. An actual app with a data model that lives on the client.
Astro: Static sites with lightweight interactive islands. Marketing pages, blogs, docs, portfolios. Render 99% of the page as static HTML at build time. Drop React/Vue/Svelte islands into specific components that need state (a cart counter, a theme toggle, a filtered product list). Zero JavaScript by default. Only ship what you need. This site (aidxn.com) uses Astro static + a few React islands. Velocity X does too. That's why it's fast.
Real Code: htmx Form vs React Form (Same Outcome)
htmx approach:
<form hx-post="/contact" hx-target="#status">
<input type="text" name="name" required />
<input type="email" name="email" required />
<textarea name="message" required></textarea>
<button type="submit">Send</button>
</form>
<div id="status"></div>
Server endpoint (POST /contact) receives form data, validates it, renders HTML response (success message or error list), sends it back. htmx inserts it into #status. Form clears. User sees feedback. No JavaScript written. Done in 6 lines of markup.
React approach:
export function ContactForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const [status, setStatus] = useState('');
const [loading, setLoading] = useState(false);
const handleSubmit = async (e) => {
e.preventDefault();
setLoading(true);
try {
const res = await fetch('/api/contact', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name, email, message }),
});
const data = await res.json();
setStatus(data.success ? 'Sent!' : data.error);
} catch (err) {
setStatus('Error. Try again.');
} finally {
setLoading(false);
}
};
return (
<>
<form onSubmit={handleSubmit}>
<input value={name} onChange={e => setName(e.target.value)} required />
<input value={email} onChange={e => setEmail(e.target.value)} required />
<textarea value={message} onChange={e => setMessage(e.target.value)} required />
<button disabled={loading}>{loading ? 'Sending...' : 'Send'}</button>
</form>
<div>{status}</div>
</>
);
}
React form is 40 lines. You manage state for every field. You handle async logic. You prevent double-submit with loading state. You manage error states. All in the browser, all in JavaScript, all loaded upfront. The htmx version? The server handles all of it. HTML attributes do the UI orchestration. No state, no async wrangling, no double-submit guards needed (the server enforces them).
Same outcome. htmx: 6 lines. React: 40 lines + 250kb bundle. The business logic is identical (validate, send email, return response). The delivery mechanism is radically different.
Why Marketing Sites ≠ Apps
A marketing site's job is to convince someone to book a call, buy a product, or sign up. It's mostly static content: copy, images, testimonials, pricing tables, a contact form. A few interactive elements: a theme toggle, a dropdown menu, a form submission, maybe a filter. That's it. You don't need a real-time data model. You don't need Redux. You don't need hydration. You need fast page loads and forms that work without a full refresh.
Apps need state. Dashboards live in client-side state. Collaborative editors sync state across clients. Chat apps need real-time messaging. Those are React problems. Your marketing site isn't a problem at all — it's a solution looking for the simplest possible delivery mechanism, which is static HTML.
Astro solves this elegantly: static HTML by default, React islands only for the 1–2 components that actually need state. Your homepage loads as 15kb of HTML and CSS. Your React cart counter is a 40kb island that only loads when a user lands on the pricing page. Total cost: 55kb instead of 250kb. Lighthouse scores jump. SEO works. Conversion rates go up because the page is actually usable.
Six FAQs
Can htmx handle complex interactions like autocomplete?
Yes. <input hx-get="/autocomplete" hx-trigger="keyup changed delay:300ms"> fires a request every 300ms and populates a dropdown with results. The server renders the options. htmx inserts them. Debouncing is automatic. No JavaScript written.
Is htmx production-ready?
Yes. Thousands of production sites use it. Django + htmx is a fully viable architecture. The tradeoff is you need a real server (Rails, Django, Laravel, Node). You're not building a static site. You're building a traditional server-rendered app but with 8kb of interactivity on top instead of 250kb of React.
What about SEO with htmx?
htmx doesn't hurt SEO because the initial HTML is server-rendered. AJAX requests aren't crawled. But the first page is crawlable, which is what matters. Astro is better for SEO because the entire site is pre-rendered as static HTML at build time — every page is immediately indexable.
Can I use Astro with htmx?
Yes, but it's redundant. Astro does static rendering. htmx adds dynamic interactivity on top. If you're already building static sites with Astro, you only use htmx if you're adding a server component (e.g. a live chat widget, a real-time notification bell). Most Astro projects don't need htmx.
What's the development experience like with htmx?
Slower iteration than React in some cases because you can't hot-reload the browser state. Faster in others because you're not debugging state management. You're debugging server responses. If your server is Python/Django with auto-reload, it's seamless — change the template, refresh, done. No build step.
Should I use htmx if I'm already comfortable with React?
Only if your team is building server-rendered apps (Node, Python, Ruby). If you're in the React ecosystem (Next.js, Remix), stick with it — the ecosystem gravity is real. htmx shines when you're working with traditional web frameworks where React is overkill.
The Bottom Line
htmx is a real alternative to React for marketing sites and server-rendered apps. 8kb, no build step, no bundle overhead, no hydration delay. The server renders HTML. htmx adds interactivity on top. Same outcome as React, vastly lighter payload. If your site is mostly static with a few interactive elements, htmx or Astro beats React by a factor of 30 on bundle size.
But htmx isn't a silver bullet. It requires a real server. It's not suited for apps that own their state. It doesn't replace React for dashboards, editors, real-time apps. Use the right tool for the right job: htmx for traditional server-rendered sites, React for apps, Astro for static sites with interactive islands. This site (Astro) and every Velocity X marketing site we build lean on the same principle: ship as little JavaScript as possible, render as much HTML as you can, and let the server do what it does best.
Ready to build a marketing site that's actually fast? Check Aidxn Design pricing for web projects, or dive into Astro 5 and why it's the framework to learn in 2026.