npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@blimu/react

v0.7.0

Published

React components and hooks for Blimu authentication and authorization

Readme

@blimu/react

React components and hooks for Blimu authentication and authorization.

Features

  • 🔐 Drop-in Authentication Components - Pre-built UI components like UserButton
  • 🎨 Fully Customizable - Theme system with CSS variables and className overrides
  • 🌓 Dark Mode Support - Built-in light and dark theme variants
  • 🎯 TypeScript First - Complete type safety with IntelliSense support
  • Tailwind CSS v4 - Modern CSS-first configuration
  • 🪝 React Hooks - useAuth, useUser, and more
  • 🧩 Headless UI - Built on Radix UI primitives

Installation

npm install @blimu/react
# or
yarn add @blimu/react
# or
pnpm add @blimu/react

Peer Dependencies

This library requires:

  • react ^18.0.0 || ^19.0.0
  • react-dom ^18.0.0 || ^19.0.0
  • tailwindcss ^4.0.0 (optional, but recommended)

Quick Start

1. Wrap your app with BlimuProvider

import { BlimuProvider } from '@blimu/react';
import '@blimu/react/styles';

function App() {
  return (
    <BlimuProvider publishableKey="pk_...">
      <YourApp />
    </BlimuProvider>
  );
}

2. Use authentication components

import { UserButton } from '@blimu/react';

function Header() {
  return (
    <header>
      <h1>My App</h1>
      <UserButton />
    </header>
  );
}

3. Access authentication state

import { useAuth, useUser } from '@blimu/react';

function Dashboard() {
  const { isAuthenticated, login, logout } = useAuth();
  const { user } = useUser();

  if (!isAuthenticated) {
    return <button onClick={() => login()}>Sign In</button>;
  }

  return (
    <div>
      <h1>Welcome, {user?.firstName}!</h1>
      <button onClick={() => logout()}>Sign Out</button>
    </div>
  );
}

Styling & Customization

Default Setup (with Tailwind CSS v4)

If you're using Tailwind CSS v4, import the stylesheet in your app:

import '@blimu/react/styles';

This gives you the default Blimu theme with dark mode support.

Theme Customization

Option 1: Theme Prop (Easiest)

Customize colors and border radius via the theme prop:

<BlimuProvider
  publishableKey="pk_..."
  theme={{
    colors: {
      primary: 'oklch(0.5 0.2 250)',      // Custom blue
      background: '#ffffff',              // Hex colors work too
      foreground: 'rgb(0, 0, 0)',         // Or RGB
    },
    radius: 'lg',  // 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full' | custom CSS value
  }}
>
  <YourApp />
</BlimuProvider>

Option 2: CSS Variables (Maximum Control)

Override CSS variables in your global styles:

/* your-app.css */
:root {
  --blimu-primary: oklch(0.45 0.25 264);
  --blimu-primary-foreground: oklch(1 0 0);
  --blimu-radius: 0.5rem;
  /* See full list of variables below */
}

.dark {
  --blimu-primary: oklch(0.7 0.2 264);
  --blimu-background: oklch(0.15 0 0);
}

Available CSS Variables:

/* Colors */
--blimu-background
--blimu-foreground
--blimu-card
--blimu-card-foreground
--blimu-popover
--blimu-popover-foreground
--blimu-primary
--blimu-primary-foreground
--blimu-secondary
--blimu-secondary-foreground
--blimu-muted
--blimu-muted-foreground
--blimu-accent
--blimu-accent-foreground
--blimu-destructive
--blimu-destructive-foreground
--blimu-border
--blimu-input
--blimu-ring

/* Border Radius */
--blimu-radius

Option 3: className Overrides (Component Level)

Every component accepts className and classes props:

<UserButton
  className="custom-user-button"
  classes={{
    trigger: 'hover:scale-105 transition-transform',
    avatar: 'ring-2 ring-blue-500',
    popover: 'shadow-2xl',
    userName: 'font-bold',
  }}
  onManageAccount={() => router.push('/settings')}
/>

Dark Mode

Blimu components automatically support dark mode when a .dark class is present on any parent element:

// Using next-themes
import { ThemeProvider } from 'next-themes';

<ThemeProvider attribute="class">
  <BlimuProvider publishableKey="pk_...">
    <YourApp />
  </BlimuProvider>
</ThemeProvider>

Or manually:

<div className="dark">
  <BlimuProvider publishableKey="pk_...">
    <YourApp />
  </BlimuProvider>
</div>

Components

UserButton

A button that displays the current user's avatar and provides account management options.

import { UserButton } from '@blimu/react';

<UserButton
  className="custom-class"
  classes={{
    trigger: 'hover:opacity-90',
    avatar: 'ring-2 ring-primary',
    popover: 'shadow-xl',
    userName: 'font-semibold',
    manageAccountButton: 'hover:bg-accent',
    signOutButton: 'hover:bg-destructive/10',
  }}
  onManageAccount={() => {
    // Navigate to account settings
  }}
/>

Props:

  • className?: string - Custom class for the root element
  • classes?: object - Object of classes for sub-elements
  • onManageAccount?: () => void - Callback when "Manage account" is clicked

RedirectToSignIn

Redirects unauthenticated users to the sign-in page.

import { RedirectToSignIn } from '@blimu/react';

function ProtectedPage() {
  return (
    <>
      <RedirectToSignIn returnUrl="/dashboard" />
      <Dashboard />
    </>
  );
}

Hooks

useAuth

Access authentication state and methods.

import { useAuth } from '@blimu/react';

function Component() {
  const {
    state,              // Full auth state object
    isAuthenticated,    // Boolean
    isLoading,          // Boolean
    login,              // (returnUrl?) => void
    logout,             // () => Promise<void>
    getToken,           // (options) => Promise<string | null>
  } = useAuth();
}

useUser

Get the current user object.

import { useUser } from '@blimu/react';

function Profile() {
  const { user } = useUser();

  return (
    <div>
      <h1>{user?.firstName} {user?.lastName}</h1>
      <p>{user?.email}</p>
    </div>
  );
}

User object:

interface User {
  id: string;
  email: string;
  firstName?: string | null;
  lastName?: string | null;
  emailVerified: boolean;
}

useBlimu

Access the Blimu client and configuration.

import { useBlimu } from '@blimu/react';

function Component() {
  const { client, config } = useBlimu();
}

TypeScript

Full TypeScript support with exported types:

import type {
  User,
  AuthState,
  BlimuConfig,
  BlimuTheme,
  BlimuThemeColors,
  UserButtonProps,
} from '@blimu/react';

// Type-safe theme configuration
const theme: BlimuTheme = {
  colors: {
    primary: 'oklch(0.5 0.2 250)',
  },
  radius: 'lg',
};

// Component props are fully typed
const userButtonProps: UserButtonProps = {
  className: 'my-button',
  onManageAccount: () => console.log('Account'),
};

Framework Guides

Next.js (App Router)

// app/layout.tsx
import { BlimuProvider } from '@blimu/react';
import '@blimu/react/styles';

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <BlimuProvider publishableKey={process.env.NEXT_PUBLIC_BLIMU_PUBLISHABLE_KEY!}>
          {children}
        </BlimuProvider>
      </body>
    </html>
  );
}

Next.js (Pages Router)

// pages/_app.tsx
import { BlimuProvider } from '@blimu/react';
import '@blimu/react/styles';
import type { AppProps } from 'next/app';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <BlimuProvider publishableKey={process.env.NEXT_PUBLIC_BLIMU_PUBLISHABLE_KEY!}>
      <Component {...pageProps} />
    </BlimuProvider>
  );
}

Vite + React

// main.tsx
import { BlimuProvider } from '@blimu/react';
import '@blimu/react/styles';
import ReactDOM from 'react-dom/client';
import App from './App';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <BlimuProvider publishableKey={import.meta.env.VITE_BLIMU_PUBLISHABLE_KEY}>
    <App />
  </BlimuProvider>
);

Remix

// app/root.tsx
import { BlimuProvider } from '@blimu/react';
import styles from '@blimu/react/styles';

export const links = () => [
  { rel: 'stylesheet', href: styles },
];

export default function Root() {
  return (
    <html>
      <head>
        <Links />
      </head>
      <body>
        <BlimuProvider publishableKey={process.env.BLIMU_PUBLISHABLE_KEY!}>
          <Outlet />
        </BlimuProvider>
      </body>
    </html>
  );
}

Advanced Usage

Protected Routes

import { useAuth, RedirectToSignIn } from '@blimu/react';

function ProtectedRoute({ children }) {
  const { isAuthenticated, isLoading } = useAuth();

  if (isLoading) {
    return <div>Loading...</div>;
  }

  if (!isAuthenticated) {
    return <RedirectToSignIn />;
  }

  return <>{children}</>;
}

Getting Tokens

import { useAuth } from '@blimu/react';

function ApiCall() {
  const { getToken } = useAuth();

  const fetchData = async () => {
    const token = await getToken({ template: 'web' });

    const response = await fetch('/api/data', {
      headers: {
        Authorization: `Bearer ${token}`,
      },
    });
  };
}

Custom Components

Build your own components using the hooks:

import { useUser, useAuth } from '@blimu/react';

function CustomUserMenu() {
  const { user } = useUser();
  const { logout } = useAuth();

  if (!user) return null;

  return (
    <div className="menu">
      <img src={user.avatarUrl} alt={user.firstName} />
      <span>{user.email}</span>
      <button onClick={logout}>Sign Out</button>
    </div>
  );
}

Examples

See the examples directory for complete working examples:

  • Next.js App Router
  • Next.js Pages Router
  • Vite + React
  • Remix
  • Custom styling examples

Troubleshooting

Tailwind classes not working

Make sure you've imported the styles:

import '@blimu/react/styles';

If you're using Tailwind CSS v4 in your app, the Blimu components will inherit your Tailwind configuration.

Dark mode not working

Ensure a .dark class is added to a parent element:

<div className="dark">
  <BlimuProvider>...</BlimuProvider>
</div>

TypeScript errors

Make sure @blimu/react is installed and your tsconfig.json has:

{
  "compilerOptions": {
    "moduleResolution": "bundler",
    "jsx": "react-jsx"
  }
}

API Reference

Full API documentation available at docs.blimu.dev

License

MIT

Support