Back to list
cameronapak

bknd-registration

by cameronapak

A no-build, un-bloated stack built upon Web Standards that feels freeing to use and can be deployed anywhere.

23🍴 2📅 Jan 21, 2026

SKILL.md


name: bknd-registration description: Use when setting up user registration flows in a Bknd application. Covers registration configuration, enabling/disabling registration, default roles, password validation, registration forms, and custom fields.

User Registration Setup

Configure and implement user self-registration in Bknd applications.

Prerequisites

  • Bknd project with auth enabled (bknd-setup-auth)
  • Password strategy configured
  • For SDK: bknd package installed

When to Use UI Mode

  • Testing registration endpoint via admin panel
  • Viewing registered users

UI steps: Admin Panel > Auth > Test password/register endpoint

When to Use Code Mode

  • Building registration forms in frontend
  • Configuring registration settings
  • Adding validation and error handling

Registration Configuration

Enable/Disable Registration

import { serve } from "bknd/adapter/bun";

serve({
  connection: { url: "file:data.db" },
  config: {
    auth: {
      enabled: true,
      allow_register: true,  // Enable self-registration (default: true)
      default_role_register: "user",  // Role assigned on registration
      strategies: {
        password: {
          type: "password",
          config: {
            hashing: "bcrypt",  // "plain" | "sha256" | "bcrypt"
            minLength: 8,       // Minimum password length
          },
        },
      },
      roles: {
        user: { implicit_allow: false },
      },
    },
  },
});

Config options:

OptionTypeDefaultDescription
allow_registerbooleantrueEnable self-registration
default_role_registerstring-Role for new users
minLengthnumber8Minimum password length

SDK Registration

import { Api } from "bknd";

const api = new Api({
  host: "http://localhost:7654",
  storage: localStorage,  // Persist token
});

async function register(email: string, password: string) {
  const { ok, data, status } = await api.auth.register("password", {
    email,
    password,
  });

  if (ok) {
    // Token stored automatically - user is logged in
    return data.user;
  }

  if (status === 409) throw new Error("Email already registered");
  if (status === 400) throw new Error("Invalid email or password");
  throw new Error("Registration failed");
}

Response:

{
  ok: boolean;
  data?: {
    user: { id: number; email: string; role?: string };
    token: string;
  };
  status: number;
}

REST API Registration

curl -X POST http://localhost:7654/api/auth/password/register \
  -H "Content-Type: application/json" \
  -d '{"email": "user@example.com", "password": "securepassword123"}'

Responses:

StatusMeaning
201Success - returns user + token
400Invalid email/password or too short
403Registration disabled
409Email already registered

React Integration

Registration Form

import { useState } from "react";
import { useApp } from "bknd/react";

function RegisterForm({ onSuccess }: { onSuccess?: () => void }) {
  const { api } = useApp();
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);

  async function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    setError(null);

    if (password !== confirmPassword) {
      setError("Passwords do not match");
      return;
    }

    if (password.length < 8) {
      setError("Password must be at least 8 characters");
      return;
    }

    setLoading(true);
    const { ok, status } = await api.auth.register("password", {
      email,
      password,
    });
    setLoading(false);

    if (ok) {
      onSuccess?.();
    } else if (status === 409) {
      setError("Email already registered");
    } else {
      setError("Registration failed");
    }
  }

  return (
    <form onSubmit={handleSubmit}>
      {error && <p className="error">{error}</p>}
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="password"
        value={password}
        onChange={(e) => setPassword(e.target.value)}
        placeholder="Password"
        minLength={8}
        required
      />
      <input
        type="password"
        value={confirmPassword}
        onChange={(e) => setConfirmPassword(e.target.value)}
        placeholder="Confirm Password"
        required
      />
      <button disabled={loading}>
        {loading ? "Creating..." : "Create Account"}
      </button>
    </form>
  );
}

Using useAuth Hook

import { useAuth } from "@bknd/react";

function RegisterPage() {
  const { user, isLoading, register } = useAuth();

  if (isLoading) return <div>Loading...</div>;
  if (user) return <Navigate to="/dashboard" />;

  async function handleRegister(email: string, password: string) {
    await register("password", { email, password });
  }

  return <RegisterForm onSuccess={() => navigate("/dashboard")} />;
}

Custom Fields After Registration

Registration only accepts email and password. Add custom fields after:

// 1. Extend users entity
const schema = em({
  users: entity("users", {
    email: text().required().unique(),
    name: text(),
    avatar: text(),
  }),
});

// 2. Update user after registration
const { data } = await api.auth.register("password", { email, password });

await api.data.updateOne("users", data.user.id, {
  name: "John Doe",
  avatar: "https://...",
});

Invite-Only Apps

Disable public registration:

{
  auth: {
    allow_register: false,  // Disable self-registration
  },
}

// Admin creates users via seed or plugin
await app.module.auth.createUser({
  email: "invited@example.com",
  password: tempPassword,
  role: "user",
});

Common Pitfalls

Registration Disabled

Problem: Registration not allowed (403)

Fix: { auth: { allow_register: true } }

Role Not Found

Problem: Role "user" not found

Fix: Define role before using:

{
  auth: {
    roles: { user: { implicit_allow: false } },
    default_role_register: "user",
  },
}

User Already Exists

Problem: 409 error

Fix: Handle gracefully:

if (status === 409) {
  setError("Email already registered. Try logging in instead.");
}

Token Not Stored

Problem: User not logged in after registration

Fix: Provide storage:

const api = new Api({
  host: "http://localhost:7654",
  storage: localStorage,  // Required for persistence
});

Custom Fields Ignored

Problem: Extra fields passed to registration not saved

Cause: Registration only accepts email/password

Fix: Update user after registration (see Custom Fields section)

Verification

# 1. Test registration
curl -X POST http://localhost:7654/api/auth/password/register \
  -H "Content-Type: application/json" \
  -d '{"email": "test@example.com", "password": "password123"}'

# 2. Verify token works
curl http://localhost:7654/api/auth/me \
  -H "Authorization: Bearer <token>"

DOs and DON'Ts

DO:

  • Use bcrypt hashing in production
  • Validate password length client-side to match server config
  • Handle 409 error with login suggestion
  • Store token with storage: localStorage
  • Define roles before using default_role_register

DON'T:

  • Use hashing: "plain" in production
  • Expect custom fields in registration payload
  • Forget to handle registration errors
  • Disable registration without alternative user creation
  • bknd-setup-auth - Configure authentication system
  • bknd-create-user - Programmatic user creation (admin/seed)
  • bknd-login-flow - Login/logout functionality
  • bknd-password-reset - Password reset flow

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon