Plugins

Username

Add username sign-up and username/password sign-in.

The username plugin lets users sign up and sign in with a username instead of an email. Kernia stores a normalized (lower-cased) username for uniqueness plus an optional displayUsername that preserves the casing the user typed.

Installation

Add the plugin to your server

Pass username() to your Kernia config. Length bounds and validators are optional constructor arguments.

auth.py
import os
from kernia import KerniaOptions
from kernia.auth import init
from kernia.plugins.username import username

auth = init(KerniaOptions(
    database=adapter,
    secret=os.environ["KERNIA_SECRET"],
    base_url=os.environ["KERNIA_BASE_URL"],
    plugins=[username(min_username_length=3, max_username_length=30)],
))

Add the client plugin

Kernia speaks the Better Auth wire protocol, so the official JavaScript client works unchanged. Add the username client plugin:

auth-client.ts
import { createAuthClient } from "better-auth/client";
import { usernameClient } from "better-auth/client/plugins";

export const authClient = createAuthClient({
  baseURL: "/api/auth",
  plugins: [usernameClient()],
});

Usage

Sign up with a username

Sign-up attaches the username to a standard account. Pass username (and optionally displayUsername) alongside the usual fields.

await authClient.signUp.email({
  email: "user@example.com",
  name: "Ada",
  password: "the-password",
  username: "ada",
  displayUsername: "Ada",
});

Sign in with a username

await authClient.signIn.username({
  username: "ada",
  password: "the-password",
});

Check whether a username is available

Useful for inline validation on a sign-up form before submitting.

const { data } = await authClient.isUsernameAvailable({ username: "ada" });
// data.available -> boolean

Options

Pass these as keyword arguments to username(...):

OptionTypeDefaultDescription
min_username_lengthint3Minimum allowed username length.
max_username_lengthint30Maximum allowed username length.
username_validator(str) -> boolCustom check; return False to reject a username.
display_username_validator(str) -> boolCustom check for the display username.
username_normalization(str) -> str | boollowercaseNormalizer applied before storage; pass False to keep casing.
display_username_normalization(str) -> str | boolNormalizer for the display username.

Schema

The plugin extends the core user table:

username
stringrequired
Normalized, unique username used for lookup (nullable).
displayUsername
stringrequired
Original-casing username for display (nullable).

Generate a migration before enabling it against a persistent database.

Lookups use the normalized username, so Ada and ada collide. Keep displayUsername for presentation and never query against it for uniqueness.