Skip to content

Astro

Install newt/ui in an Astro site, where React and Vue components can live side by side as islands.

Choose the brand hue, the radius and the font in newt/create, and it prints a preset code. Pass that code to init and the project comes out already wearing it.

pnpm dlx create astro@latest
npx create astro@latest
yarn dlx create astro@latest
bunx create astro@latest
pnpm dlx newtui@latest init --preset <code>
npx newtui@latest init --preset <code>
yarn dlx newtui@latest init --preset <code>
bunx newtui@latest init --preset <code>
pnpm dlx newtui@latest add button
npx newtui@latest add button
yarn dlx newtui@latest add button
bunx newtui@latest add button

Astro has no scaffold template, so the project is created by its own tool first and init runs inside the result. It detects the framework, the bundler and the stylesheet on its own.

pnpm dlx create astro@latest
npx create astro@latest
yarn dlx create astro@latest
bunx create astro@latest
pnpm dlx newtui@latest init
npx newtui@latest init
yarn dlx newtui@latest init
bunx newtui@latest init
pnpm dlx newtui@latest add button
npx newtui@latest add button
yarn dlx newtui@latest add button
bunx newtui@latest add button

Create the site and add a framework

npm create astro@latest my-site
npx astro add react
npx astro add vue

Both integrations can be installed at once. This site runs them together: the switcher at the top of the page decides which island paints, and the other one’s markup is hidden rather than unmounted.

Add Tailwind

npx astro add tailwind
@import "tailwindcss";

Declare the alias

{
  "compilerOptions": {
    "paths": { "@/*": ["./src/*"] }
  }
}

Astro resolves tsconfig paths on its own, so there is no second copy to keep in the Vite config.

Run init

pnpm dlx newtui@latest init --framework react
npx newtui@latest init --framework react
yarn dlx newtui@latest init --framework react
bunx newtui@latest init --framework react
pnpm dlx newtui@latest init --framework vue --bundler vite
npx newtui@latest init --framework vue --bundler vite
yarn dlx newtui@latest init --framework vue --bundler vite
bunx newtui@latest init --framework vue --bundler vite

A site with both integrations has both frameworks in its dependencies, so name the one you want the components written for. Running init twice with different --framework values is fine: the tokens are written once and skipped after that.

Load the stylesheet and mark the root

---
import "../styles/global.css"
---

<html lang="en">
  <body class="newt-root">
    <slot />
  </body>
</html>

Add a component

pnpm dlx newtui@latest add button
npx newtui@latest add button
yarn dlx newtui@latest add button
bunx newtui@latest add button

An interactive component is an island, so it needs a client: directive. A static one does not.

---
import { Button } from "@/components/ui/button"
---

<Button client:load variant="primary">Send</Button>
---
import { Button } from "@/components/ui/button"
---

<Button client:load variant="primary">Send</Button>

What init writes

components.json                 the config, shared with shadcn
src/styles/global.css           the --newt-* token block
src/lib/utils.ts                cn()
src/components/ui/button.tsx    add button (React)

The Vue flavour writes a folder per component instead — Button.vue plus an index.ts barrel.

Two frameworks in one site

Nothing stops a site from carrying both registries: they share the same --newt-* tokens, so a React island and a Vue island rendered next to each other are indistinguishable. Keep them in separate directories — components/ui for one and components/ui-vue for the other — and point components.json at whichever you are adding to at the time.

See Dark mode for the theme toggle, and RTL if the site has to run right to left.