Back to blog
Tutorial

React or Astro: how to choose the right stack for your project

By Flávio Emanuel · · 8 min read

The common mistake

“Which framework should I use?” is the wrong question. The right question is: what does the project need to do?

A framework is a tool. A screwdriver isn’t better than a hammer. It depends on whether you’re driving a screw or hammering a nail. And using a hammer to drive a screw, even though it kind of works, leaves marks.

This post is for devs deciding between React and Astro, and for business owners who want to understand why the dev recommended a specific stack. The criteria are practical, based on real projects I’ve shipped with both.

I’ve seen a client pay R$15k for a corporate site built in React that loaded 350 KB of JS to show 5 pages of text and images. Lighthouse 60, weak rankings, high bounce rate on mobile. It wasn’t the dev’s fault — it was a tooling problem. The dev knew React and used React. But the project didn’t call for React.

When to use Astro

Astro is a framework for content. It generates static HTML at build time and sends zero JavaScript to the browser by default. The result is a site that loads instantly, indexes perfectly on Google, and hits Lighthouse 95+ without any special configuration.

Use Astro when:

  • The page content doesn’t change after it loads. It’s the same for every visitor
  • SEO is a priority. The site needs to rank on Google
  • There are no complex forms, shared state, or heavy interactions
  • It needs to load fast on any connection, including 3G
  • The project is a corporate site, landing page, blog, or portfolio

Projects I built with Astro: Family Pilates (boutique LP with local SEO), GPM2 (premium corporate site for a tax consulting firm), Tok Final (B2B corporate for construction companies), Soline (renewable energy with dense technical data), Carrega Rapido (LP for an electric mobility startup), Laura Nasralla (veterinary clinic with local SEO). All with Lighthouse 95+ and zero client-side JS.

What Astro does differently

Most frameworks (Next.js, Nuxt, SvelteKit) start from the assumption that you need JavaScript on the client and give you ways to reduce it. Astro flips that: it starts from the assumption that you don’t need it and gives you ways to add it.

The practical result: on an 8-page site in Astro, the browser receives 8 HTML files and zero JavaScript. The same site in Next.js receives 8 HTML pages + 70-300 KB of JavaScript for hydration, routing, and the React runtime. On 3G connections for someone browsing on their phone in rural Brazil, those extra 200 KB mean 3-5 extra seconds of load time. For a corporate site, that’s a lost visit.

Why I chose Astro over Next.js has the detailed numbers for each project.

Islands Architecture

When part of a page needs interactivity (carousel, form with validation, stateful component), Astro lets you hydrate just that component. This is the Islands Architecture pattern.

On Family Pilates, the only island is the testimonials carousel. It loads 12 KB of JavaScript. The rest of the page (hero, services, about, CTA) stays static. In Next.js, the entire framework would hydrate even the static parts.

The directive works like this:

  • client:load hydrates immediately (form that needs to work right away)
  • client:visible hydrates when it enters the viewport (carousel in the middle of the page)
  • client:idle hydrates when the browser is idle (non-urgent component)

No directive = static HTML. No JavaScript. No hydration.

Where Astro falls short

Applications with login, shared state between components, SPA-style internal navigation, real-time data, multi-step forms with complex validation. All of this needs client-side JavaScript. Astro can do it, but it’s not built for it. It’s like using a screwdriver to hammer nails: it works if you force it, but the result is ugly.

I’ve tried it myself. In a test project, I built a mini admin panel in Astro with React islands for each interactive part. Every navigation between pages reloaded everything, state was lost between routes, and the experience was slow and fragmented. The same panel in pure React was fluid, kept state across screens, and responded quickly to every click. Right tool for the right job.

When to use React

React is a library for interactive interfaces. Webapps, dashboards, admin panels, SaaS — anything that has state, complex forms, and real-time updates.

Use React when:

  • The user logs in and has a session
  • There are forms with validation, steps, or conditional logic
  • Data changes in real time (notifications, chat, order status, dashboard)
  • Multiple screens with internal navigation (sidebar, tabs, nested routes)
  • The system needs state management (cart, persistent filters, preferences)

Projects I built with React: AutoPars (marketplace with 3 panels, 5 integrations, admin dashboard with real-time metrics), Mariah (order management with financial dashboard and period filters), FitPlan (gym platform with 6 panels, workouts, nutrition, and marketplace).

React + TypeScript + Supabase

My standard stack for webapps is React + TypeScript + Supabase + Tailwind. TypeScript catches type errors before they hit production. Supabase delivers auth, PostgreSQL database, storage, and realtime without building a backend from scratch. Tailwind speeds up the UI.

This combination lets me ship an MVP in 4-8 weeks working solo. Supabase eliminates weeks of backend setup. React gives flexibility for any type of interface. Hooks like useState, useEffect, and custom hooks for business logic keep the code organized even when the system grows past 50+ components.

Where React doesn’t fit (for sites)

A 5-page static site. A conversion landing page. A blog. A portfolio. Does it work? Yes. Is it the best choice? No.

React shipping 200+ KB of JavaScript to render text and images is wasteful. The visitor pays with load time, Google penalizes with a lower Lighthouse score, and SEO suffers because a SPA needs extra configuration to be properly indexed.

That’s why AutoPars (React SPA) needed a separate Astro LP as an SEO layer. The SPA doesn’t index well on its own. The Astro LP solves that.

When the project needs both

This happens more often than you’d think. And the answer isn’t “pick one and adapt”. It’s using each where it makes sense.

Two separate projects

AutoPars: marketplace in React (app.autopars.com) + capture LP in Astro (autopars.com). Two repositories, two deploys, each on the right stack. React handles the marketplace interactivity. Astro handles SEO and organic acquisition.

Astro with React islands

A corporate site in Astro with an interactive area. Astro supports React components natively. The site is static, and the interactive part (advanced form, mini dashboard, calculator) is a React island that hydrates only where needed.

This pattern is ideal when 90% of the site is static content and 10% needs interactivity. Instead of loading React for the entire page because of that 10%, you load it only in the component that needs it.

Direct comparison

AstroReact
Project typeSites, LPs, blogs, portfoliosWebapps, dashboards, SaaS, panels
Client-side JSZero by defaultAlways present
SEONative, static HTMLNeeds SSR/SSG or a separate LP
PerformanceLighthouse 95+ without effortDepends on manual optimization
State/interactionLimited (Islands for exceptions)Full
Real-timeNoYes (WebSocket, polling)
AuthenticationPossible but not idealNative
Learning curveLow (HTML-first)Medium-high (hooks, state, effects)
EcosystemGrowing fastMature, massive

How I decide

Three questions, in this order:

Does the user log in? If yes, React. A system with authentication, sessions, and per-user data is React territory. Astro can handle it, but it’s not the natural path.

Does the content change after the page loads? If data updates in real time, if there are stateful forms, if the interface reacts to user actions, React. If the page is the same for everyone who visits, Astro.

Is SEO a priority? If yes, Astro wins by default. Static HTML, meta tags at build time, native Schema.org, zero SSR configuration. React needs Next.js with SSR/SSG to compete, and even then it ships more JS.

If you answered “no” to all three, it’s a static site. Astro. If you answered “yes” to either of the first two, it’s a webapp. React.

When in doubt, I start with the simpler option. Starting with React for a static site is wasted complexity. Migrating from Astro to React when the project grows is easier than optimizing React for something that should have been static from the start.

For devs who only know React

If you learned React and use it for everything, I’d recommend trying Astro on a personal project. The learning curve is low (1-2 days to feel productive), the syntax is familiar (looks like JSX with frontmatter), and the experience of seeing a Lighthouse 100 without any effort changes your perspective.

You don’t need to abandon React. You need to have two tools in the box instead of one. The hammer and the screwdriver.

I made this transition myself. I used to use Next.js for everything, including static sites. When I tried Astro, I realized how much unnecessary JavaScript I’d been shipping to the browser on projects that didn’t need it. Builds were faster, deploys were lighter, and Lighthouse hit 100 without any manual optimization. Now, when I start a new project, the first decision is: is this content or is this an application? The answer defines the stack in 30 seconds.

Next step

Need a dev who truly delivers?

Whether it's a one-time project, team reinforcement, or a long-term partnership. Let's talk.

Chat on WhatsApp

I reply within 2 hours during business hours.