# React, Vue and MDX Components when you want them, JavaScript only where you need it.

> vagejs is a React and MDX static site generator that renders React and Vue components to plain HTML, and sends JavaScript only for interactive islands.

vagejs is a static site generator that lets you build pages with React and Vue components and write content in MDX, then turns all of it into plain HTML when it builds your site. Visitors get no JavaScript unless you mark a React component interactive, and then only on the pages that use it.

`npm create vagejs@latest my-site`

[Read the component docs](https://vagejs.com/docs/components/)[Add an interactive component](https://vagejs.com/guides/interactive-react-component-static-site/)

## What you can build with components

Components are a nice way to build a site: write a pricing card once, use it on ten pages. The usual cost is JavaScript that every visitor downloads, even for parts of the page that never change. We keep the components and drop that cost.

-   ### Layouts as React or Vue components
    
    Write `src/layouts/default.tsx` or `default.vue`. A React layout gets the same data as a TypeScript one: the page, the site, the list of pages and your menus. Visitors get plain HTML and no JavaScript.
    
-   ### MDX pages
    
    MDX is Markdown that can use React components. Write `src/pages/pricing.mdx` and import any component from `src/components/`. It becomes plain HTML too, with no JavaScript.
    
-   ### Interactive React islands
    
    Add `client:load`, `client:visible` or `client:idle` to a React component and it runs in the browser. JavaScript goes only to the pages that use one.
    

## Islands only where you ask

An island is one interactive part on an otherwise static page. It's rendered to HTML first, so visitors see the component right away and the page works while its JavaScript loads.

```
import Calculator from "../components/Calculator.tsx";

<Calculator client:load rate={4.5} />
```

| Directive | Starts |
| --- | --- |
| `client:load` | as soon as the page loads |
| `client:visible` | when it scrolls into view |
| `client:idle` | when the browser has nothing else to do |

With `client:visible`, visitors who never scroll that far never download the component.

## MDX is checked like Markdown

MDX pages and component layouts get the same treatment as Markdown pages: titles, descriptions, sitemap entries, structured data, and `vage check` for broken links, hidden links and links to websites you haven't approved.

```
---
title: Pricing
description: Plans and prices.
---
import PlanCard from "../components/PlanCard.tsx";

# Pricing

<PlanCard name="Team" price="$20 a month" />
```

One difference: an MDX page is code, like a layout. It runs when the site is built, so vagejs can't clean it up the way it cleans HTML in Markdown pages. Keep MDX for content you'd trust in a layout.

## Who React, Vue and MDX in vagejs are for

-   ### Teams that already think in React
    
    Reuse the components and habits you have, without turning a content site into an app.
    
-   ### Sites that need one or two interactive parts
    
    A price calculator, a filter or a short quiz, on a site that's otherwise static.
    
-   ### Anyone moving from a component framework
    
    Keep your layouts as components, and gain built-in checks and SEO files along the way.
    

## What it costs

Sites that don't use components install nothing extra. Add React, Vue or MDX when you need them; if one is missing, the build tells you the exact command to install it.

An island does cost JavaScript. `vage audit` counts it on every page, including React itself (about 215 KB), which is over the default 100 KB budget. So adding one is a decision you make, not an accident. For many jobs, plain HTML does the same: a `<details>` element opens and closes, and a form can send without any script.

terminal

```
npm install react react-dom                  # React layouts
npm install --save-dev @mdx-js/mdx           # plus React, for MDX pages
npm install vue && npm install --save-dev @vitejs/plugin-vue   # Vue layouts
```

## The limits, for now

Here's what doesn't work yet, so you can plan around it.

-   Interactive components are React only. Vue components work in layouts, as HTML.
-   Interactive components take plain data (text, numbers, lists) and can't contain other interactive components.
-   CSS imported inside components isn't collected. Put your styles in `public/` and link them from the layout.

If you need islands in Vue or Svelte, or a site that's mostly interactive, see [how vagejs compares](https://vagejs.com/compare/) with other tools.

## More on React, Vue and MDX in vagejs

React support arrived in version 0.10 for layouts and MDX pages, and in 0.11 for interactive components.

-   Step by step: [add an interactive React component to a static site](https://vagejs.com/guides/interactive-react-component-static-site/)
-   Every option and rule: [React, Vue and MDX in the docs](https://vagejs.com/docs/components/)
-   Other features: [all vagejs features](https://vagejs.com/features/)

## Questions about React, Vue and MDX

### Do I need to install React to use vagejs?

No. A site without components doesn't need React, Vue or MDX at all. Install each one when you start using it. If a page or layout needs a package that's missing, the build stops and prints the exact install command.

### Why doesn't useState or onClick do anything in my component?

Only components marked with `client:load`, `client:visible` or `client:idle` run in the browser. Everything else is turned into HTML once, when the site is built, so state, effects and click handlers do nothing there. Mark the component interactive if it needs them.

### How do I style my components?

Put your CSS in `public/` and link it from your layout. CSS inside components, such as a Vue `<style>` block or `import "./card.css"`, isn't added to the site.

### Can I edit MDX pages in the browser editor?

Not yet. The editor that `npm run dev` opens lists `.md` pages only, so edit `.mdx` pages in your code editor.
