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 CSS | v4.0 or later |
| Node.js | 20.0 or later (for tooling) |
| Frameworks | Next.js · Vite · Astro · Remix · SvelteKit · Nuxt · Rails · Phoenix |
| TypeScript | Optional. 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.
# 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 tailwindcssWire 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 */
@import "tailwindcss";
@plugin "@lumora-design/core";Tailwind v4 is JIT-only
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>.
<!-- 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.
<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.
pnpm add @lumora-design/react// app/SaveButton.tsx
import { LumoraButton } from "@lumora-design/react";
export function SaveButton() {
return <LumoraButton variant="primary">Save changes</LumoraButton>;
}Tree-shakeable
Vue adapter
The Vue package mirrors the React API as Vue 3 components with slot-based composition.
pnpm add @lumora-design/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
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 -->
<!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 apply | Confirm @plugin "@lumora-design/core" appears after @import "tailwindcss". Restart the dev server after editing CSS. |
| Wrong colors | Check that data-lm-theme is set on <html>. Inspect the element to confirm the CSS variables resolved. |
| FOUC on theme switch | Inject a small inline script in <head> that reads localStorage and applies data-lm-theme before paint. See the theming guide. |
| Adapter classes mismatch | Pin @lumora-design/core and @lumora-design/react to matching minor versions — they share the class contract. |