# Installation

> One command, or a manual install when you want to own every line.

## One command

```sh
npx astro add moonarc
```

This installs `@moonarc/core` and the `moonarc` integration entry, adds
the integration to `astro.config.mjs`, and that is the whole setup. The
integration does three small things you would otherwise do by hand:

1. Injects `@moonarc/core/styles/base.css` on every page: the theme-aware
   tokens (`--ma-ease-out`, `--ma-edge`, …) every component reads.
2. Adds a 92-byte inline script to `<head>` that sets `data-ma-js` on `<html>`
   before first paint, and again after every `<ClientRouter />` navigation.
   Entrance effects hide content only behind that attribute, so a page whose
   JavaScript never runs still shows everything.
3. Optionally adds the package to `vite.ssr.noExternal`. It is off by default
   because Astro 5, 6 and 7 do not need it.

Then import what you use:

```astro
---
import Reveal from '@moonarc/core/Reveal';
---
<Reveal><h2>Hello</h2></Reveal>
```

Each component is its own subpath export, so importing one never pulls the
stylesheet or script of another.

## Manual install

If you prefer no integration, install the components package:

```sh
npm install @moonarc/core
```

Then do by hand what the integration does:

```js title="astro.config.mjs"
// nothing needed
```

```astro title="src/layouts/Base.astro"
---
import '@moonarc/core/styles/base.css';
import { gateScript } from '@moonarc/core';
---
<head>
  <style is:inline>@layer theme, base, components, utilities;</style>
  <script is:inline set:html={gateScript} />
</head>
```

The `<style>` line fixes the order of the cascade layers before any
stylesheet loads. `base.css` opens with the same statement, and the
integration imports it ahead of everything else on every page. Without the
integration, a component's CSS can load first. `components` is then the
first layer declared and ranks lowest, so a reset in `base` (Tailwind's
preflight is one) beats every component rule. Keep the statement first in
`<head>`.

`gateScript` is the text the integration injects. It sets `data-ma-js` again
after every navigation. The older one-line gate set it once, and lost it for
the rest of the visit at the first navigation from a page that loads no
Moonarc script.

:::note Without the gate script
Scroll reveals are visible from the start. Nothing breaks, and nothing
animates in.
:::

## Copy the source with the shadcn CLI

Every component page has the full source and a shadcn-compatible registry
command:

```sh
npx shadcn@latest add https://moonarc.dev/r/reveal.json
```

The registry item brings the shared runtime with it. Components that compose
another (SplitText uses Reveal) declare that as a registry dependency.

The CLI needs a `components.json`, which an Astro project does not have, and
the copied files import one another through the `@/*` alias.
[Setup](/setup/#registry) has both files, written so that `package.json`
stays as it is. Files land in `src/components/moonarc/` and
`src/lib/moonarc/`, and the base stylesheet in `src/styles/moonarc.css`.

Import that stylesheet once, and give the layout the same two lines in
`<head>` as a manual install: the layer statement first, then the gate.
`@moonarc/core` is not installed this way, so put the gate's text from
[the integration](/docs/integration/#jsgate) inside the
`<script is:inline>` instead of `gateScript`.

## Requirements

- Astro 5, 6 or 7. Verified on every release against all three, in `static`
  and `server` output.
- No Tailwind required. Components use scoped, layered CSS and custom
  properties. The Tailwind token layer is opt-in (see
  [motion tokens](/docs/motion-tokens/)).
- The Node version your Astro major requires: 22.12 or later for Astro 6
  and 7; 18.20.8, 20.3 or a later 20, or 22 and later for Astro 5.