Skip to content
Documentation menu
Get started · 5 min

Installation

Add Lumora to any Tailwind v4 project in two lines. Optional React and Vue packages are thin typed wrappers over the same lm-* class API.

Requirements

Lumora UI is a Tailwind CSS v4 plugin. It runs anywhere Tailwind v4 runs.

Tailwind CSSv4.0 or later
Node.js20.0 or later (for tooling)
FrameworksNext.js · Vite · Astro · Remix · SvelteKit · Nuxt · Rails · Phoenix
TypeScriptOptional. Adapters ship full type definitions.

Install the plugin

Pick your package manager. The core plugin and Tailwind v4 are the only required dependencies — adapters are optional.

terminal
# pnpm
pnpm add @lumora-design/core tailwindcss

# npm
npm install @lumora-design/core tailwindcss

# yarn
yarn add @lumora-design/core tailwindcss

# bun
bun add @lumora-design/core tailwindcss

Wire it into your CSS

Add the Tailwind import and the Lumora plugin to your top-level stylesheet. That's the whole installation.

app/globals.css
/* app/globals.css */
@import "tailwindcss";
@plugin "@lumora-design/core";

Tailwind v4 is JIT-only

Lumora components are added via Tailwind's addComponents API. Tailwind v4 only emits CSS for classes you actually use, so unused components add zero bytes to your bundle.

Set the theme

Lumora reads the active theme from a data-lm-theme attribute on any ancestor — usually <html>.

layout.html
<!-- app/layout.html -->
<html data-lm-theme="lumora-dark">
  ...
</html>

Without the attribute, Lumora falls back to lumora-light. See the theming guide for runtime switching, custom themes, and per-tenant theming.

Verify the install

Drop this into any page. You should see a Lumora primary button with gradient and focus ring.

app/page.htmlhtml
<button class="lm-btn lm-btn-primary lm-btn-md">It works</button>
  • Button has a primary background with a subtle vertical gradient.
  • Hovering lifts it 1px and brightens the shadow.
  • Focusing it (Tab key) shows a 3px focus ring.
  • All animations respect prefers-reduced-motion.

React adapter

Optional. The React package emits the same lm-* classes with typed props for variants, sizes, states, and compound structures.

terminal
pnpm add @lumora-design/react
app/SaveButton.tsx
// app/SaveButton.tsx
import { LumoraButton } from "@lumora-design/react";

export function SaveButton() {
  return <LumoraButton variant="primary">Save changes</LumoraButton>;
}

Tree-shakeable

Each component is a named export. Bundlers strip what you don't import — typical app ships under 4 KB of adapter code.

Vue adapter

The Vue package mirrors the React API as Vue 3 components with slot-based composition.

terminal
pnpm add @lumora-design/vue
App.vue
<!-- App.vue -->
<script setup lang="ts">
import { LumoraButton } from "@lumora-design/vue";
</script>

<template>
  <LumoraButton variant="primary">Save changes</LumoraButton>
</template>

Framework recipes

Next.js (App Router)

Add the data attribute to <html> in your root layout, then import your stylesheet in the same file.

app/layout.tsx
// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html lang="en" data-lm-theme="lumora-dark">
      <body>{children}</body>
    </html>
  );
}

Vite (any framework)

Set the data attribute on the root HTML element and link your stylesheet from main.css.

index.html
<!-- index.html -->
<!DOCTYPE html>
<html lang="en" data-lm-theme="lumora-dark">
  <head>
    <link rel="stylesheet" href="/src/main.css" />
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/src/main.ts"></script>
  </body>
</html>

Astro / Rails / Phoenix

Same shape: include the Tailwind plugin in your CSS pipeline, set data-lm-theme on the root HTML element. Lumora has no framework-specific code.

Troubleshooting

Classes don't applyConfirm @plugin "@lumora-design/core" appears after @import "tailwindcss". Restart the dev server after editing CSS.
Wrong colorsCheck that data-lm-theme is set on <html>. Inspect the element to confirm the CSS variables resolved.
FOUC on theme switchInject a small inline script in <head> that reads localStorage and applies data-lm-theme before paint. See the theming guide.
Adapter classes mismatchPin @lumora-design/core and @lumora-design/react to matching minor versions — they share the class contract.