Getting Started
A quick tutorial to get you up and running with Apsara.
This guide walks you through installing Apsara and building your first component.
Prerequisites
Apsara requires:
- Node.js 22 or later
- React 19
React and React DOM are peer dependencies. Make sure your project has them installed:
1npm install react react-dom
Installation
Install the package using your preferred package manager:
1npm install @raystack/apsara
Try a preview build
Every pull request on GitHub gets a canary build, published automatically via pkg.pr.new. This lets you try out unreleased changes before they ship to npm. The PR will have a comment with an install command, for example:
1pnpm add https://pkg.pr.new/raystack/apsara/@raystack/apsara@<pr-number>
Setup
Three steps, in order. The styles and the provider are needed once, at the root of the app.
1. Import styles
Add the CSS import at the root of your application, before any component renders:
1import "@raystack/apsara/style.css";
This single stylesheet includes all component styles and CSS custom properties (tokens) for theming.
2. Add Theme
Wrap your application with Theme to enable theming support:
1import { Theme } from "@raystack/apsara";23function App() {4 return (5 <Theme defaultTheme="system">6 <YourApp />7 </Theme>8 );9}
The defaultTheme prop accepts "light", "dark", or "system" (follows OS preference).
3. Use components
Import and use components directly:
1import { Button, Flex, Text } from "@raystack/apsara";23function Example() {4 return (5 <Flex direction="column" gap={4}>6 <Text size="regular" weight="medium">Welcome to Apsara</Text>7 <Flex gap={3}>8 <Button variant="solid" color="accent">Primary Action</Button>9 <Button variant="outline">Secondary</Button>10 </Flex>11 </Flex>12 );13}
Framework setup
Where the two setup steps go depends on the framework.
Next.js (App Router)
Add the provider to your root layout:
1// app/layout.tsx2import { Theme } from "@raystack/apsara";3import "@raystack/apsara/style.css";45export default function RootLayout({ children }: { children: React.ReactNode }) {6 return (7 <html lang="en" suppressHydrationWarning>8 <body>9 <Theme defaultTheme="system">10 {children}11 </Theme>12 </body>13 </html>14 );15}
The suppressHydrationWarning attribute is required because Theme injects a script to prevent theme flash during hydration.
Vite
Add the provider to your main entry file:
1// main.tsx2import React from "react";3import ReactDOM from "react-dom/client";4import { Theme } from "@raystack/apsara";5import "@raystack/apsara/style.css";6import App from "./App";78ReactDOM.createRoot(document.getElementById("root")!).render(9 <React.StrictMode>10 <Theme defaultTheme="system">11 <App />12 </Theme>13 </React.StrictMode>14);
Optional: normalize CSS
Apsara includes an optional normalize stylesheet that keeps rendering consistent across browsers while preserving useful defaults:
1import "@raystack/apsara/normalize.css";2import "@raystack/apsara/style.css";
Import it before the main stylesheet if you choose to use it.
Importing icons
Apsara exports a set of icons that can be imported separately:
1import { Button } from "@raystack/apsara";2import { SearchIcon, XIcon } from "@raystack/apsara/icons";34<Button leadingIcon={<SearchIcon />}>Search</Button>
Importing hooks
Utility hooks such as useCopyToClipboard, useDebouncedState, and useMouse are available from a dedicated export:
1import { Button } from "@raystack/apsara";2import { useCopyToClipboard } from "@raystack/apsara/hooks";34function CopyButton({ value }: { value: string }) {5 const { copy } = useCopyToClipboard();67 return <Button onClick={() => copy(value)}>Copy</Button>;8}
To read or change the active theme, use useTheme from the main entry:
1import { Button, useTheme } from "@raystack/apsara";23function ThemeToggle() {4 const { resolvedTheme, setTheme } = useTheme();56 return (7 <Button onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}>8 Toggle Theme9 </Button>10 );11}
Next steps
- Theme Overview — Configure colors, spacing, and style variants
- Button — Start with a common component
- DataView — Build data-rich interfaces