@bettercone/ui
v0.5.2
Published
Production-ready Better Auth UI components.
Maintainers
Readme
@bettercone/ui
Comprehensive Better Auth UI component library with production-ready components for authentication, billing, teams, and api key.
Recent Updates: Enhanced compatibility with React 19, Tailwind v4, and modern stacks. See CHANGELOG.md for detailed release notes.
Installation
Recommended: One-command setup (installs everything automatically)
npx @bettercone/ui initThis CLI command will:
- ✅ Install
@bettercone/uiandbetter-auth - ✅ Initialize shadcn/ui (if not already set up)
- ✅ Install all required shadcn/ui dependencies
- ✅ Install essential shadcn/ui components (Button, Card, Input, etc.)
- ✅ Set up your project automatically
No manual shadcn/ui setup required! The CLI handles everything.
Manual Installation (Alternative)
If you prefer manual setup or have existing shadcn/ui configuration:
npm install @bettercone/ui better-auth
# or
pnpm add @bettercone/ui better-auth
# or
yarn add @bettercone/ui better-authThen initialize shadcn/ui manually:
npx shadcn@latest init
npx shadcn@latest add button card input label skeleton alert avatar badge checkbox dialog dropdown-menu form progress radio-group select separator switch table tabs textarea alert-dialog drawer chart stepper input-otpSetup
1. Install the package
The npx @bettercone/ui init command from above handles this step automatically.
2. Import the CSS
Add the following import to your global CSS file (e.g., app/globals.css or src/index.css):
@import "@bettercone/ui/css";3. Configure Better Auth
Set up Better Auth in your project. See the Better Auth documentation for details.
Note: shadcn/ui components (Button, Card, Input, etc.) are now available in your components/ui/ folder and can be imported directly from there. They are not bundled in @bettercone/ui to avoid duplication.
Quick Start
Authentication Components
"use client";
import { AuthView } from "@bettercone/ui";
import { authClient } from "@/lib/auth-client";
export default function SignInPage() {
return <AuthView authClient={authClient} />;
}Organization Management
import { OrganizationSwitcher, OrganizationMembersCard } from "@bettercone/ui";
export default function OrganizationPage() {
return (
<div className="container mx-auto py-8">
<OrganizationSwitcher authClient={authClient} />
<OrganizationMembersCard authClient={authClient} />
</div>
);
}Billing Dashboard
"use client";
import { BillingDashboard } from "@bettercone/ui";
import { authClient } from "@/lib/auth-client"; // Your Better Auth client
export default function BillingPage() {
return (
<div className="container mx-auto py-8">
<BillingDashboard
authClient={authClient}
subscriptionCardProps={{
onManageSubscription: async (subscription) => {
// Open Stripe billing portal or your payment provider
const response = await fetch("/api/billing/portal");
const { url } = await response.json();
window.location.href = url;
}
}}
/>
</div>
);
}Components Overview
Authentication
AuthView- Complete authentication view with routingAuthForm- Reusable form wrapperAuthCallback- OAuth callback handlerPasskeyButton- Passkey authenticationPasskeySetupWizard- 5-step passkey registration wizardProviderButton- Social OAuth provider buttonMagicLinkButton- Magic link authenticationEmailOTPButton- Email OTP triggerOneTap- Google One TapSignOut- Sign out componentPhoneSignInForm- Sign in with phone number and passwordPhoneSignUpForm- Sign up with phone number and OTP verificationAnonymousSignInButton- Sign in as guest without PIIAnonymousUpgradeCard- Encourage anonymous users to link authenticationDeviceAuthorizationCard- User code input for device authorizationDeviceApprovalCard- Approve or deny device authorization requestsDeviceCodeDisplay- Display device codes for CLI/IoT applications
Security & Email
PasskeyCell- Individual passkey displayPasskeysCard- Passkey managementTwoFactorCard- Two-factor authentication settingsTwoFactorPasswordDialog- Password verification for 2FABackupCodesDialog- Backup codes displayChangePasswordCard- Password change formChangeEmailCard- Email change with verificationEmailVerificationBanner- Prompt email verification with resendSessionsCard- Active sessions listSessionCell- Individual session displayPhoneNumberCard- Manage phone number with OTP verification
Organizations
OrganizationView- Complete organization management interfaceOrganizationSettingsCards- Organization settings cards (logo, name, slug, delete)OrganizationSwitcher- Switch between organizationsCreateOrganizationDialog- Create new organizationDeleteOrganizationCard- Delete organizationOrganizationMembersCard- Members listRemoveMemberDialog- Remove memberUpdateMemberRoleDialog- Change member roleTransferOwnershipDialog- Transfer organization ownershipOrganizationInvitationsCard- Pending invitationsInviteMemberDialog- Send invitationAcceptInvitationCard- Accept invitationUserInvitationsCard- User's pending invitationsOrganizationNameCard- Edit organization nameOrganizationSlugCard- Edit organization slugOrganizationLogoCard- Upload organization logoLeaveOrganizationDialog- Leave organization
Account Management
AccountView- Account settings viewDeleteAccountCard- Account deletionDeleteAccountDialog- Confirm deletionLinkAccountCard- Link OAuth providers to accountUnlinkAccountCard- Unlink OAuth providers from account
Dashboard & Analytics
UsageHistoryChart- Interactive usage visualization with chartsUsageDashboard- Complete usage metrics dashboardApiUsageCard- API usage tracking with limitsFeatureAccessCard- Feature availability by plan
Developer Tools
ApiKeysCard- API keys listApiKeyCell- Individual API keyCreateApiKeyDialog- Create new API key
Admin Tools
UserManagementTable- Admin table for user managementBanUserDialog- Ban users with reason and durationImpersonateUserDialog- Impersonate users for support
Enterprise SSO & OIDC Provider
SSOConfigCard- Complete OIDC & SAML SSO configurationSAMLSetupWizard- Guided 5-step SAML setup wizardOIDCProviderCard- OAuth2/OIDC Provider client management
User Components
UserButton- User menu dropdownUserAvatar- User avatar display
Utility Components
SignedIn- Conditional render when signed inSignedOut- Conditional render when signed outAuthLoading- Loading state handlerRedirectToSignIn- Auto redirect to sign inRedirectToSignUp- Auto redirect to sign upPasswordInput- Password field with toggle visibilityFormError- Form error display- Provider icons for social authentication
Billing Components
SubscriptionCard- Current subscription display with Stripe integrationPaymentMethodCard- Payment methods managementInvoiceHistoryCard- Invoice listBillingDashboard- Complete billing page
Usage Tracking
ApiUsageCard- API usage with chartsStorageUsageCard- Storage usageFeatureAccessCard- Feature access by planUsageDashboard- Complete usage page
Team Management
SeatAllocationCard- Team seat managementTeamBillingCard- Team billing overviewTeamDashboard- Complete team page
Pricing
PricingCard- Plan selection with monthly/yearly toggle and auto-checkout
Web3/SIWE
SiweSignInButton- Sign In With Ethereum wallet connectionWalletConnectionCard- Manage connected Web3 wallets (Ethereum, Polygon, Arbitrum, Base, Optimism)
Detailed Component Examples
Authentication
Complete Auth Flow
import { AuthView, AuthUIProvider } from "@bettercone/ui";
import { authClient } from "@/lib/auth-client";
export default function AuthPage() {
return (
<AuthUIProvider
authClient={authClient}
credentials={true}
signUp={true}
social={{
providers: ["google", "github"]
}}
>
<AuthView />
</AuthUIProvider>
);
}Organization Switcher
import { OrganizationSwitcher } from "@bettercone/ui";
<OrganizationSwitcher
authClient={authClient}
onCreate={() => {
// Handle organization creation
}}
/>Phone Authentication
Phone number authentication with OTP verification.
import { PhoneSignInForm, PhoneSignUpForm, PhoneNumberCard, AuthUIProvider } from "@bettercone/ui";
import { authClient } from "@/lib/auth-client";
// Sign in with phone number and password
export function PhoneSignIn() {
return (
<AuthUIProvider authClient={authClient}>
<PhoneSignInForm
redirectTo="/dashboard"
localization={{}}
/>
</AuthUIProvider>
);
}
// Sign up with phone number and OTP
export function PhoneSignUp() {
return (
<AuthUIProvider authClient={authClient}>
<PhoneSignUpForm
redirectTo="/dashboard"
localization={{}}
/>
</AuthUIProvider>
);
}
// Manage phone number in settings
export function PhoneSettings() {
return (
<AuthUIProvider authClient={authClient}>
<PhoneNumberCard />
</AuthUIProvider>
);
}Requirements:
- Better Auth
phoneNumberplugin configured - SMS provider configured (Twilio, etc.)
// Better Auth configuration
import { betterAuth } from "better-auth";
import { phoneNumber } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
phoneNumber({
sendOtp: async (phoneNumber, code) => {
// Send SMS with your provider
await twilioClient.messages.create({
to: phoneNumber,
from: process.env.TWILIO_PHONE_NUMBER,
body: `Your verification code is: ${code}`
});
}
})
]
});Web3/SIWE Components
Sign In With Ethereum (SIWE) for Web3 wallet authentication.
import { SiweSignInButton, WalletConnectionCard, AuthUIProvider } from "@bettercone/ui";
import { authClient } from "@/lib/auth-client";
// SIWE Sign-In Button
export function Web3SignIn() {
return (
<AuthUIProvider authClient={authClient}>
<SiweSignInButton
onSuccess={(address) => {
console.log("Signed in with wallet:", address);
}}
onError={(error) => {
console.error("SIWE error:", error);
}}
className="w-full"
/>
</AuthUIProvider>
);
}
// Wallet Connection Management
export function WalletSettings() {
return (
<AuthUIProvider authClient={authClient}>
<WalletConnectionCard
onConnect={() => {
console.log("Connect new wallet");
}}
onDisconnect={(walletId) => {
console.log("Disconnect wallet:", walletId);
}}
/>
</AuthUIProvider>
);
}Requirements:
- Better Auth
siweplugin configured - Wallet provider (MetaMask, WalletConnect, etc.)
// Better Auth configuration
import { betterAuth } from "better-auth";
import { siwe } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
siwe({
domain: process.env.NEXT_PUBLIC_APP_DOMAIN,
getNonce: async () => {
// Generate secure nonce
return crypto.randomBytes(16).toString("base64");
}
})
]
});Supported Chains:
- Ethereum (chainId: 1)
- Polygon (chainId: 137)
- Arbitrum (chainId: 42161)
- Base (chainId: 8453)
- Optimism (chainId: 10)
Two-Factor Authentication
import { TwoFactorCard } from "@bettercone/ui";
<TwoFactorCard
authClient={authClient}
onEnable={(secret) => {
// Handle 2FA enablement
}}
/>Billing
Displays current subscription with Stripe integration.
Requirements:
- Better Auth
stripeplugin configured - Stripe account with products/prices set up
// Better Auth configuration
import { betterAuth } from "better-auth";
import { stripe } from "better-auth/plugins";
export const auth = betterAuth({
plugins: [
stripe({
publishableKey: process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!,
secretKey: process.env.STRIPE_SECRET_KEY!
})
]
});SubscriptionCard
Displays current subscription with management actions.
import { SubscriptionCard } from "@bettercone/ui";
<SubscriptionCard
authClient={authClient}
onManageSubscription={async (subscription, organization) => {
// Handle billing portal navigation
}}
onAction={(action, subscription) => {
// Handle upgrade/cancel actions
}}
showActions={true}
localization={{
currentPlan: "Current Plan",
manageSubscription: "Manage Subscription"
}}
/>PaymentMethodCard
Payment method management via billing portal.
import { PaymentMethodCard } from "@bettercone/ui";
<PaymentMethodCard
authClient={authClient}
onManagePayment={async (subscription, organization) => {
// Open payment management
}}
/>InvoiceHistoryCard
Invoice viewing and download functionality.
import { InvoiceHistoryCard } from "@bettercone/ui";
<InvoiceHistoryCard
authClient={authClient}
onViewInvoices={async (subscription, organization) => {
// Open billing portal to invoices
}}
maxInvoices={5}
/>Pricing Components
PricingCard
Plan selection with monthly/yearly toggle and automatic Stripe checkout.
import { PricingCard, type PricingPlan } from "@bettercone/ui";
const plan: PricingPlan = {
id: "pro",
name: "Pro",
description: "For growing teams",
priceMonthly: 29,
priceYearly: 290,
stripePriceIdMonthly: "price_xxx", // Stripe price ID
stripePriceIdYearly: "price_yyy", // Stripe price ID
features: [
"Unlimited API calls",
"Advanced analytics",
"Priority support"
],
popular: true
};
<PricingCard
plan={plan}
billingInterval="monthly"
authClient={authClient}
onSubscribe={async (planId, interval) => {
// Automatic Stripe checkout via Better Auth
await authClient.stripe.createCheckoutSession({
priceId: interval === "monthly"
? plan.stripePriceIdMonthly
: plan.stripePriceIdYearly,
successUrl: `${window.location.origin}/billing/success`,
cancelUrl: `${window.location.origin}/pricing`
});
}}
/>Usage Components
ApiUsageCard
API call tracking with progress bars and warnings.
import { ApiUsageCard } from "@bettercone/ui";
<ApiUsageCard
current={8500}
limit={10000}
warningThreshold={80}
onUpgrade={() => {
// Navigate to pricing
}}
/>StorageUsageCard
Storage usage tracking with alerts.
import { StorageUsageCard } from "@bettercone/ui";
<StorageUsageCard
currentBytes={4500000000} // 4.5GB
limitBytes={5000000000} // 5GB
warningThreshold={80}
onUpgrade={() => {
// Navigate to pricing
}}
/>FeatureAccessCard
Feature flag display with locked/unlocked states.
import { FeatureAccessCard, type FeatureAccess } from "@bettercone/ui";
const features: FeatureAccess = {
planId: "pro",
advancedAnalytics: true,
apiAccess: true,
customIntegrations: false,
prioritySupport: false
};
<FeatureAccessCard
features={features}
onUpgrade={() => {
// Navigate to pricing
}}
/>Team Components
SeatAllocationCard
Team seat management with warnings.
import { SeatAllocationCard, type SeatAllocationData } from "@bettercone/ui";
const data: SeatAllocationData = {
usedSeats: 8,
totalSeats: 10,
planName: "Team",
members: [
{ id: "1", name: "John Doe", email: "[email protected]", role: "admin" }
]
};
<SeatAllocationCard
data={data}
onUpgrade={() => {
// Navigate to pricing
}}
onInviteMember={() => {
// Open invite dialog
}}
showMemberList={true}
/>TeamBillingCard
Organization-level billing summary.
import { TeamBillingCard } from "@bettercone/ui";
<TeamBillingCard
organization={organization}
subscription={subscription}
onManageBilling={() => {
// Open billing portal
}}
onChangePlan={() => {
// Navigate to pricing
}}
/>Backend-Agnostic Architecture
All components accept a BetterAuthClient interface, making them compatible with any Better Auth backend:
import type { BetterAuthClient } from "@bettercone/ui";
// Works with Convex
import { authClient } from "@convex-dev/better-auth";
// Works with Prisma
import { createAuthClient } from "better-auth/react";
// Works with Supabase, Drizzle, etc.Customization
Class Names
All components accept className and classNames props for granular styling:
<SubscriptionCard
className="shadow-xl"
classNames={{
header: "bg-primary text-white",
title: "text-2xl",
content: "p-6"
}}
/>Localization
Components support partial localization:
<SubscriptionCard
localization={{
currentPlan: "Plan Atual",
manageSubscription: "Gerenciar Assinatura",
noActiveSubscription: "Nenhuma assinatura ativa"
}}
/>TypeScript Support
Full TypeScript support with comprehensive type definitions:
import type {
BetterAuthClient,
BetterAuthSession,
BetterAuthSubscription,
SubscriptionCardProps,
PricingPlan,
FeatureAccess
} from "@bettercone/ui";Loading States
All components include skeleton variants:
import { SubscriptionCardSkeleton } from "@bettercone/ui";
{isLoading ? <SubscriptionCardSkeleton /> : <SubscriptionCard {...props} />}License
MIT © BetterCone
